Class RDoc::Markup::ToHtml
In: markup/to_html.rb
Parent: RDoc::Markup::Formatter

Methods

Public Class methods

[Source]

    # File markup/to_html.rb, line 21
21:   def initialize
22:     super
23: 
24:     # external hyperlinks
25:     @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
26: 
27:     # and links of the form  <text>[<url>]
28:     @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
29: 
30:     init_tags
31:   end

Public Instance methods

[Source]

     # File markup/to_html.rb, line 175
175:   def accept_blank_line(am, fragment)
176:     # @res << annotate("<p />") << "\n"
177:   end

[Source]

     # File markup/to_html.rb, line 179
179:   def accept_heading(am, fragment)
180:     @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
181:   end

[Source]

     # File markup/to_html.rb, line 156
156:   def accept_list_end(am, fragment)
157:     if tag = @in_list_entry.pop
158:       @res << annotate(tag) << "\n"
159:     end
160:     @res << html_list_name(fragment.type, false) << "\n"
161:   end

[Source]

     # File markup/to_html.rb, line 163
163:   def accept_list_item(am, fragment)
164:     if tag = @in_list_entry.last
165:       @res << annotate(tag) << "\n"
166:     end
167: 
168:     @res << list_item_start(am, fragment)
169: 
170:     @res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
171: 
172:     @in_list_entry[-1] = list_end_for(fragment.type)
173:   end

[Source]

     # File markup/to_html.rb, line 151
151:   def accept_list_start(am, fragment)
152:     @res << html_list_name(fragment.type, true) << "\n"
153:     @in_list_entry.push false
154:   end

[Source]

     # File markup/to_html.rb, line 133
133:   def accept_paragraph(am, fragment)
134:     @res << annotate("<p>") + "\n"
135:     @res << wrap(convert_flow(am.flow(fragment.txt)))
136:     @res << annotate("</p>") + "\n"
137:   end

[Source]

     # File markup/to_html.rb, line 145
145:   def accept_rule(am, fragment)
146:     size = fragment.param
147:     size = 10 if size > 10
148:     @res << "<hr size=\"#{size}\"></hr>"
149:   end

[Source]

     # File markup/to_html.rb, line 139
139:   def accept_verbatim(am, fragment)
140:     @res << annotate("<pre>") + "\n"
141:     @res << CGI.escapeHTML(fragment.txt)
142:     @res << annotate("</pre>") << "\n"
143:   end

Add a new set of HTML tags for an attribute. We allow separate start and end tags for flexibility.

[Source]

     # File markup/to_html.rb, line 108
108:   def add_tag(name, start, stop)
109:     @attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
110:   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.

[Source]

     # File markup/to_html.rb, line 117
117:   def annotate(tag)
118:     tag
119:   end

[Source]

     # File markup/to_html.rb, line 237
237:   def convert_flow(flow)
238:     res = ""
239: 
240:     flow.each do |item|
241:       case item
242:       when String
243:         res << convert_string(item)
244:       when RDoc::Markup::AttrChanger
245:         off_tags(res, item)
246:         on_tags(res,  item)
247:       when RDoc::Markup::Special
248:         res << convert_special(item)
249:       else
250:         raise "Unknown flow element: #{item.inspect}"
251:       end
252:     end
253: 
254:     res
255:   end

[Source]

     # File markup/to_html.rb, line 303
303:   def convert_heading(level, flow)
304:     res =
305:       annotate("<h#{level}>") +
306:       convert_flow(flow) +
307:       annotate("</h#{level}>\n")
308:   end

[Source]

     # File markup/to_html.rb, line 290
290:   def convert_special(special)
291:     handled = false
292:     RDoc::Markup::Attribute.each_name_of(special.type) do |name|
293:       method_name = "handle_special_#{name}"
294:       if self.respond_to? method_name
295:         special.text = send(method_name, special)
296:         handled = true
297:       end
298:     end
299:     raise "Unhandled special: #{special}" unless handled
300:     special.text
301:   end

some of these patterns are taken from SmartyPants...

[Source]

     # File markup/to_html.rb, line 260
260:   def convert_string(item)
261:     CGI.escapeHTML(item).
262: 
263:     # convert -- to em-dash, (-- to en-dash)
264:       gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
265: 
266:     # convert ... to elipsis (and make sure .... becomes .<elipsis>)
267:       gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
268: 
269:     # convert single closing quote
270:       gsub(%r{([^ \t\r\n\[\{\(])\'}, '\1&#8217;').
271:       gsub(%r{\'(?=\W|s\b)}, '&#8217;').
272: 
273:     # convert single opening quote
274:       gsub(/'/, '&#8216;').
275: 
276:     # convert double closing quote
277:       gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}, '\1&#8221;').
278: 
279:     # convert double opening quote
280:       gsub(/'/, '&#8220;').
281: 
282:     # convert copyright
283:       gsub(/\(c\)/, '&#169;').
284: 
285:     # convert and registered trademark
286:       gsub(/\(r\)/, '&#174;')
287: 
288:   end

[Source]

     # File markup/to_html.rb, line 129
129:   def end_accepting
130:     @res
131:   end

Generate a hyperlink for url, labeled with text. Handle the special cases for img: and link: described under handle_special_HYPEDLINK

[Source]

    # File markup/to_html.rb, line 37
37:   def gen_url(url, text)
38:     if url =~ /([A-Za-z]+):(.*)/ then
39:       type = $1
40:       path = $2
41:     else
42:       type = "http"
43:       path = url
44:       url  = "http://#{url}"
45:     end
46: 
47:     if type == "link" then
48:       url = if path[0, 1] == '#' then # is this meaningful?
49:               path
50:             else
51:               RDoc::Generator.gen_url @from_path, path
52:             end
53:     end
54: 
55:     if (type == "http" or type == "link") and
56:        url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
57:       "<img src=\"#{url}\" />"
58: 
59:     elsif type == "link"
60:       "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
61:     else
62:       "<a href=\"#{url}\" target=\"_top\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
63:     end
64:   end

And we‘re invoked with a potential external hyperlink mailto: just gets inserted. http: links are checked to see if they reference an image. If so, that image gets inserted using an <img> tag. Otherwise a conventional <a href> is used. We also support a special type of hyperlink, link:, which is a reference to a local file whose path is relative to the —op directory.

[Source]

    # File markup/to_html.rb, line 74
74:   def handle_special_HYPERLINK(special)
75:     url = special.text
76:     gen_url url, url
77:   end

Here‘s a hypedlink where the label is different to the URL

 <label>[url] or {long label}[url]

[Source]

    # File markup/to_html.rb, line 83
83:   def handle_special_TIDYLINK(special)
84:     text = special.text
85: 
86:     return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
87: 
88:     label = $1
89:     url   = $2
90:     gen_url url, label
91:   end

[Source]

     # File markup/to_html.rb, line 310
310:   def html_list_name(list_type, is_open_tag)
311:     tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}")
312:     annotate(tags[ is_open_tag ? 0 : 1])
313:   end

Set up the standard mapping of attributes to HTML tags

[Source]

     # File markup/to_html.rb, line 96
 96:   def init_tags
 97:     @attr_tags = [
 98:       InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
 99:       InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT),   "<tt>", "</tt>"),
100:       InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM),   "<em>", "</em>"),
101:     ]
102:   end

[Source]

     # File markup/to_html.rb, line 343
343:   def list_end_for(fragment_type)
344:     case fragment_type
345:     when :BULLET, :NUMBER, :UPPERALPHA, :LOWERALPHA then
346:       "</li>"
347:     when :LABELED then
348:       "</dd>"
349:     when :NOTE then
350:       "</td></tr>"
351:     else
352:       raise "Invalid list type"
353:     end
354:   end

[Source]

     # File markup/to_html.rb, line 315
315:   def list_item_start(am, fragment)
316:     case fragment.type
317:     when :BULLET, :NUMBER then
318:       annotate("<li>")
319: 
320:     when :UPPERALPHA then
321:       annotate("<li type=\"A\">")
322: 
323:     when :LOWERALPHA then
324:       annotate("<li type=\"a\">")
325: 
326:     when :LABELED then
327:       annotate("<dt>") +
328:         convert_flow(am.flow(fragment.param)) +
329:         annotate("</dt>") +
330:         annotate("<dd>")
331: 
332:     when :NOTE then
333:       annotate("<tr>") +
334:         annotate("<td valign=\"top\">") +
335:         convert_flow(am.flow(fragment.param)) +
336:         annotate("</td>") +
337:         annotate("<td>")
338:     else
339:       raise "Invalid list type"
340:     end
341:   end

[Source]

     # File markup/to_html.rb, line 226
226:   def off_tags(res, item)
227:     attr_mask = item.turn_off
228:     return if attr_mask.zero?
229: 
230:     @attr_tags.reverse_each do |tag|
231:       if attr_mask & tag.bit != 0
232:         res << annotate(tag.off)
233:       end
234:     end
235:   end

[Source]

     # File markup/to_html.rb, line 215
215:   def on_tags(res, item)
216:     attr_mask = item.turn_on
217:     return if attr_mask.zero?
218: 
219:     @attr_tags.each do |tag|
220:       if attr_mask & tag.bit != 0
221:         res << annotate(tag.on)
222:       end
223:     end
224:   end

Here‘s the client side of the visitor pattern

[Source]

     # File markup/to_html.rb, line 124
124:   def start_accepting
125:     @res = ""
126:     @in_list_entry = []
127:   end

This is a higher speed (if messier) version of wrap

[Source]

     # File markup/to_html.rb, line 186
186:   def wrap(txt, line_len = 76)
187:     res = ""
188:     sp = 0
189:     ep = txt.length
190:     while sp < ep
191:       # scan back for a space
192:       p = sp + line_len - 1
193:       if p >= ep
194:         p = ep
195:       else
196:         while p > sp and txt[p] != ?\s
197:           p -= 1
198:         end
199:         if p <= sp
200:           p = sp + line_len
201:           while p < ep and txt[p] != ?\s
202:             p += 1
203:           end
204:         end
205:       end
206:       res << txt[sp...p] << "\n"
207:       sp = p
208:       sp += 1 while sp < ep and txt[sp] == ?\s
209:     end
210:     res
211:   end

[Validate]