Class | SM::ToHtml |
In: |
markup/simple_markup/to_html.rb
|
Parent: | Object |
LIST_TYPE_TO_HTML | = | { ListBase::BULLET => [ "<ul>", "</ul>" ], ListBase::NUMBER => [ "<ol>", "</ol>" ], ListBase::UPPERALPHA => [ "<ol>", "</ol>" ], ListBase::LOWERALPHA => [ "<ol>", "</ol>" ], ListBase::LABELED => [ "<dl>", "</dl>" ], ListBase::NOTE => [ "<table>", "</table>" ], } |
InlineTag | = | Struct.new(:bit, :on, :off) |
# File markup/simple_markup/to_html.rb, line 105 105: def accept_blank_line(am, fragment) 106: # @res << annotate("<p />") << "\n" 107: end
# File markup/simple_markup/to_html.rb, line 109 109: def accept_heading(am, fragment) 110: @res << convert_heading(fragment.head_level, am.flow(fragment.txt)) 111: end
# File markup/simple_markup/to_html.rb, line 89 89: def accept_list_end(am, fragment) 90: if tag = @in_list_entry.pop 91: @res << annotate(tag) << "\n" 92: end 93: @res << html_list_name(fragment.type, false) <<"\n" 94: end
# File markup/simple_markup/to_html.rb, line 96 96: def accept_list_item(am, fragment) 97: if tag = @in_list_entry.last 98: @res << annotate(tag) << "\n" 99: end 100: @res << list_item_start(am, fragment) 101: @res << wrap(convert_flow(am.flow(fragment.txt))) << "\n" 102: @in_list_entry[-1] = list_end_for(fragment.type) 103: end
# File markup/simple_markup/to_html.rb, line 84 84: def accept_list_start(am, fragment) 85: @res << html_list_name(fragment.type, true) <<"\n" 86: @in_list_entry.push false 87: end
# File markup/simple_markup/to_html.rb, line 66 66: def accept_paragraph(am, fragment) 67: @res << annotate("<p>") + "\n" 68: @res << wrap(convert_flow(am.flow(fragment.txt))) 69: @res << annotate("</p>") + "\n" 70: end
# File markup/simple_markup/to_html.rb, line 78 78: def accept_rule(am, fragment) 79: size = fragment.param 80: size = 10 if size > 10 81: @res << "<hr size=\"#{size}\"></hr>" 82: end
# File markup/simple_markup/to_html.rb, line 72 72: def accept_verbatim(am, fragment) 73: @res << annotate("<pre>") + "\n" 74: @res << CGI.escapeHTML(fragment.txt) 75: @res << annotate("</pre>") << "\n" 76: end
Given an HTML tag, decorate it with class information and the like if required. This is a no-op in the base class, but is overridden in HTML output classes that implement style sheets
# File markup/simple_markup/to_html.rb, line 50 50: def annotate(tag) 51: tag 52: end
# File markup/simple_markup/to_html.rb, line 170 170: def convert_flow(flow) 171: res = "" 172: flow.each do |item| 173: case item 174: when String 175: res << convert_string(item) 176: when AttrChanger 177: off_tags(res, item) 178: on_tags(res, item) 179: when Special 180: res << convert_special(item) 181: else 182: raise "Unknown flow element: #{item.inspect}" 183: end 184: end 185: res 186: end
# File markup/simple_markup/to_html.rb, line 234 234: def convert_heading(level, flow) 235: res = 236: annotate("<h#{level}>") + 237: convert_flow(flow) + 238: annotate("</h#{level}>\n") 239: end
# File markup/simple_markup/to_html.rb, line 221 221: def convert_special(special) 222: handled = false 223: Attribute.each_name_of(special.type) do |name| 224: method_name = "handle_special_#{name}" 225: if self.respond_to? method_name 226: special.text = send(method_name, special) 227: handled = true 228: end 229: end 230: raise "Unhandled special: #{special}" unless handled 231: special.text 232: end
some of these patterns are taken from SmartyPants...
# File markup/simple_markup/to_html.rb, line 190 190: def convert_string(item) 191: CGI.escapeHTML(item). 192: 193: 194: # convert -- to em-dash, (-- to en-dash) 195: gsub(/---?/, '—'). #gsub(/--/, '–'). 196: 197: # convert ... to elipsis (and make sure .... becomes .<elipsis>) 198: gsub(/\.\.\.\./, '.…').gsub(/\.\.\./, '…'). 199: 200: # convert single closing quote 201: gsub(%r{([^ \t\r\n\[\{\(])\'}) { "#$1’" }. 202: gsub(%r{\'(?=\W|s\b)}) { "’" }. 203: 204: # convert single opening quote 205: gsub(/'/, '‘'). 206: 207: # convert double closing quote 208: gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}) { "#$1”" }. 209: 210: # convert double opening quote 211: gsub(/'/, '“'). 212: 213: # convert copyright 214: gsub(/\(c\)/, '©'). 215: 216: # convert and registered trademark 217: gsub(/\(r\)/, '®') 218: 219: end
# File markup/simple_markup/to_html.rb, line 241 241: def html_list_name(list_type, is_open_tag) 242: tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}") 243: annotate(tags[ is_open_tag ? 0 : 1]) 244: end
Set up the standard mapping of attributes to HTML tags
# File markup/simple_markup/to_html.rb, line 28 28: def init_tags 29: @attr_tags = [ 30: InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"), 31: InlineTag.new(SM::Attribute.bitmap_for(:TT), "<tt>", "</tt>"), 32: InlineTag.new(SM::Attribute.bitmap_for(:EM), "<em>", "</em>"), 33: ] 34: end
# File markup/simple_markup/to_html.rb, line 274 274: def list_end_for(fragment_type) 275: case fragment_type 276: when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA 277: "</li>" 278: when ListBase::LABELED 279: "</dd>" 280: when ListBase::NOTE 281: "</td></tr>" 282: else 283: raise "Invalid list type" 284: end 285: end
# File markup/simple_markup/to_html.rb, line 246 246: def list_item_start(am, fragment) 247: case fragment.type 248: when ListBase::BULLET, ListBase::NUMBER 249: annotate("<li>") 250: 251: when ListBase::UPPERALPHA 252: annotate("<li type=\"A\">") 253: 254: when ListBase::LOWERALPHA 255: annotate("<li type=\"a\">") 256: 257: when ListBase::LABELED 258: annotate("<dt>") + 259: convert_flow(am.flow(fragment.param)) + 260: annotate("</dt>") + 261: annotate("<dd>") 262: 263: when ListBase::NOTE 264: annotate("<tr>") + 265: annotate("<td valign=\"top\">") + 266: convert_flow(am.flow(fragment.param)) + 267: annotate("</td>") + 268: annotate("<td>") 269: else 270: raise "Invalid list type" 271: end 272: end
# File markup/simple_markup/to_html.rb, line 159 159: def off_tags(res, item) 160: attr_mask = item.turn_off 161: return if attr_mask.zero? 162: 163: @attr_tags.reverse_each do |tag| 164: if attr_mask & tag.bit != 0 165: res << annotate(tag.off) 166: end 167: end 168: end
# File markup/simple_markup/to_html.rb, line 148 148: def on_tags(res, item) 149: attr_mask = item.turn_on 150: return if attr_mask.zero? 151: 152: @attr_tags.each do |tag| 153: if attr_mask & tag.bit != 0 154: res << annotate(tag.on) 155: end 156: end 157: end
Here‘s the client side of the visitor pattern
# File markup/simple_markup/to_html.rb, line 57 57: def start_accepting 58: @res = "" 59: @in_list_entry = [] 60: end
This is a higher speed (if messier) version of wrap
# File markup/simple_markup/to_html.rb, line 115 115: def wrap(txt, line_len = 76) 116: res = "" 117: sp = 0 118: ep = txt.length 119: while sp < ep 120: # scan back for a space 121: p = sp + line_len - 1 122: if p >= ep 123: p = ep 124: else 125: while p > sp and txt[p] != ?\s 126: p -= 1 127: end 128: if p <= sp 129: p = sp + line_len 130: while p < ep and txt[p] != ?\s 131: p += 1 132: end 133: end 134: end 135: res << txt[sp...p] << "\n" 136: sp = p 137: sp += 1 while sp < ep and txt[sp] == ?\s 138: end 139: res 140: end