rdoc 6.13.0 → 6.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +1 -1
  3. data/README.md +112 -0
  4. data/RI.md +1 -1
  5. data/lib/rdoc/code_object/any_method.rb +4 -4
  6. data/lib/rdoc/code_object/attr.rb +3 -3
  7. data/lib/rdoc/code_object/class_module.rb +18 -16
  8. data/lib/rdoc/code_object/constant.rb +5 -5
  9. data/lib/rdoc/code_object/context/section.rb +8 -7
  10. data/lib/rdoc/code_object/context.rb +19 -19
  11. data/lib/rdoc/code_object/method_attr.rb +7 -6
  12. data/lib/rdoc/code_object/mixin.rb +3 -3
  13. data/lib/rdoc/code_object/normal_class.rb +1 -1
  14. data/lib/rdoc/code_object/normal_module.rb +1 -1
  15. data/lib/rdoc/code_object/single_class.rb +1 -1
  16. data/lib/rdoc/code_object/top_level.rb +28 -33
  17. data/lib/rdoc/code_object.rb +3 -3
  18. data/lib/rdoc/comment.rb +196 -14
  19. data/lib/rdoc/cross_reference.rb +4 -4
  20. data/lib/rdoc/encoding.rb +4 -4
  21. data/lib/rdoc/erb_partial.rb +1 -1
  22. data/lib/rdoc/erbio.rb +2 -2
  23. data/lib/rdoc/generator/aliki.rb +42 -0
  24. data/lib/rdoc/generator/darkfish.rb +20 -16
  25. data/lib/rdoc/generator/json_index.rb +3 -3
  26. data/lib/rdoc/generator/markup.rb +12 -0
  27. data/lib/rdoc/generator/pot/message_extractor.rb +4 -4
  28. data/lib/rdoc/generator/pot/po.rb +1 -1
  29. data/lib/rdoc/generator/pot/po_entry.rb +7 -7
  30. data/lib/rdoc/generator/pot.rb +1 -1
  31. data/lib/rdoc/generator/ri.rb +1 -1
  32. data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +8 -0
  33. data/lib/rdoc/generator/template/aliki/_footer.rhtml +23 -0
  34. data/lib/rdoc/generator/template/aliki/_head.rhtml +158 -0
  35. data/lib/rdoc/generator/template/aliki/_header.rhtml +56 -0
  36. data/lib/rdoc/generator/template/aliki/_icons.rhtml +208 -0
  37. data/lib/rdoc/generator/template/aliki/_sidebar_ancestors.rhtml +16 -0
  38. data/lib/rdoc/generator/template/aliki/_sidebar_classes.rhtml +15 -0
  39. data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +25 -0
  40. data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +25 -0
  41. data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +16 -0
  42. data/lib/rdoc/generator/template/aliki/_sidebar_methods.rhtml +41 -0
  43. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +67 -0
  44. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +15 -0
  45. data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +21 -0
  46. data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +3 -0
  47. data/lib/rdoc/generator/template/aliki/class.rhtml +220 -0
  48. data/lib/rdoc/generator/template/aliki/css/rdoc.css +1737 -0
  49. data/lib/rdoc/generator/template/aliki/index.rhtml +22 -0
  50. data/lib/rdoc/generator/template/aliki/js/aliki.js +483 -0
  51. data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +299 -0
  52. data/lib/rdoc/generator/template/aliki/js/search.js +120 -0
  53. data/lib/rdoc/generator/template/aliki/js/theme-toggle.js +112 -0
  54. data/lib/rdoc/generator/template/aliki/page.rhtml +18 -0
  55. data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +14 -0
  56. data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +65 -0
  57. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +3 -3
  58. data/lib/rdoc/generator/template/darkfish/_head.rhtml +16 -16
  59. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -8
  60. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -8
  61. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +7 -6
  62. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +6 -6
  63. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +19 -19
  64. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +2 -2
  65. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +1 -0
  66. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +3 -3
  67. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +14 -14
  68. data/lib/rdoc/generator/template/darkfish/class.rhtml +62 -60
  69. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +2 -0
  70. data/lib/rdoc/generator/template/darkfish/index.rhtml +4 -3
  71. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +21 -1
  72. data/lib/rdoc/generator/template/darkfish/js/search.js +11 -1
  73. data/lib/rdoc/generator/template/darkfish/page.rhtml +2 -1
  74. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +2 -1
  75. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +19 -19
  76. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +19 -17
  77. data/lib/rdoc/generator/template/json_index/js/searcher.js +48 -6
  78. data/lib/rdoc/generator.rb +1 -0
  79. data/lib/rdoc/markdown.kpeg +72 -18
  80. data/lib/rdoc/markdown.rb +411 -547
  81. data/lib/rdoc/markup/attribute_manager.rb +5 -5
  82. data/lib/rdoc/markup/attributes.rb +3 -3
  83. data/lib/rdoc/markup/blank_line.rb +2 -2
  84. data/lib/rdoc/markup/block_quote.rb +1 -1
  85. data/lib/rdoc/markup/document.rb +8 -8
  86. data/lib/rdoc/markup/formatter.rb +12 -12
  87. data/lib/rdoc/markup/hard_break.rb +3 -3
  88. data/lib/rdoc/markup/heading.rb +4 -4
  89. data/lib/rdoc/markup/include.rb +3 -3
  90. data/lib/rdoc/markup/indented_paragraph.rb +3 -3
  91. data/lib/rdoc/markup/list.rb +4 -4
  92. data/lib/rdoc/markup/list_item.rb +4 -4
  93. data/lib/rdoc/markup/paragraph.rb +2 -2
  94. data/lib/rdoc/markup/parser.rb +11 -11
  95. data/lib/rdoc/markup/pre_process.rb +39 -15
  96. data/lib/rdoc/markup/raw.rb +5 -5
  97. data/lib/rdoc/markup/rule.rb +2 -2
  98. data/lib/rdoc/markup/table.rb +4 -4
  99. data/lib/rdoc/markup/to_ansi.rb +7 -3
  100. data/lib/rdoc/markup/to_bs.rb +10 -6
  101. data/lib/rdoc/markup/to_html.rb +182 -30
  102. data/lib/rdoc/markup/to_html_crossref.rb +58 -28
  103. data/lib/rdoc/markup/to_html_snippet.rb +17 -17
  104. data/lib/rdoc/markup/to_joined_paragraph.rb +1 -1
  105. data/lib/rdoc/markup/to_label.rb +6 -5
  106. data/lib/rdoc/markup/to_markdown.rb +12 -12
  107. data/lib/rdoc/markup/to_rdoc.rb +40 -31
  108. data/lib/rdoc/markup/to_table_of_contents.rb +3 -3
  109. data/lib/rdoc/markup/to_test.rb +1 -1
  110. data/lib/rdoc/markup/to_tt_only.rb +8 -8
  111. data/lib/rdoc/markup/verbatim.rb +3 -3
  112. data/lib/rdoc/markup.rb +3 -3
  113. data/lib/rdoc/options.rb +53 -23
  114. data/lib/rdoc/parser/c.rb +31 -62
  115. data/lib/rdoc/parser/changelog.rb +9 -9
  116. data/lib/rdoc/parser/prism_ruby.rb +122 -114
  117. data/lib/rdoc/parser/ruby.rb +51 -51
  118. data/lib/rdoc/parser/ruby_tools.rb +5 -7
  119. data/lib/rdoc/parser/simple.rb +5 -22
  120. data/lib/rdoc/parser.rb +8 -8
  121. data/lib/rdoc/rd/inline.rb +4 -4
  122. data/lib/rdoc/rd.rb +1 -1
  123. data/lib/rdoc/rdoc.rb +9 -8
  124. data/lib/rdoc/ri/driver.rb +49 -49
  125. data/lib/rdoc/ri/paths.rb +2 -2
  126. data/lib/rdoc/ri/task.rb +3 -3
  127. data/lib/rdoc/rubygems_hook.rb +14 -11
  128. data/lib/rdoc/servlet.rb +15 -15
  129. data/lib/rdoc/stats/normal.rb +1 -1
  130. data/lib/rdoc/stats/quiet.rb +1 -1
  131. data/lib/rdoc/stats/verbose.rb +3 -3
  132. data/lib/rdoc/stats.rb +12 -12
  133. data/lib/rdoc/store.rb +32 -32
  134. data/lib/rdoc/task.rb +6 -6
  135. data/lib/rdoc/text.rb +11 -11
  136. data/lib/rdoc/token_stream.rb +14 -2
  137. data/lib/rdoc/tom_doc.rb +8 -8
  138. data/lib/rdoc/version.rb +1 -1
  139. data/man/ri.1 +2 -0
  140. data/rdoc.gemspec +72 -0
  141. metadata +61 -6
  142. data/README.rdoc +0 -142
@@ -20,29 +20,29 @@ class RDoc::Markup::Raw
20
20
  ##
21
21
  # Appends +text+
22
22
 
23
- def << text
23
+ def <<(text)
24
24
  @parts << text
25
25
  end
26
26
 
27
- def == other # :nodoc:
27
+ def ==(other) # :nodoc:
28
28
  self.class == other.class and @parts == other.parts
29
29
  end
30
30
 
31
31
  ##
32
32
  # Calls #accept_raw+ on +visitor+
33
33
 
34
- def accept visitor
34
+ def accept(visitor)
35
35
  visitor.accept_raw self
36
36
  end
37
37
 
38
38
  ##
39
39
  # Appends +other+'s parts
40
40
 
41
- def merge other
41
+ def merge(other)
42
42
  @parts.concat other.parts
43
43
  end
44
44
 
45
- def pretty_print q # :nodoc:
45
+ def pretty_print(q) # :nodoc:
46
46
  self.class.name =~ /.*::(\w{1,4})/i
47
47
 
48
48
  q.group 2, "[#{$1.downcase}: ", ']' do
@@ -7,11 +7,11 @@ class RDoc::Markup::Rule < Struct.new :weight
7
7
  ##
8
8
  # Calls #accept_rule on +visitor+
9
9
 
10
- def accept visitor
10
+ def accept(visitor)
11
11
  visitor.accept_rule self
12
12
  end
13
13
 
14
- def pretty_print q # :nodoc:
14
+ def pretty_print(q) # :nodoc:
15
15
  q.group 2, '[rule:', ']' do
16
16
  q.pp weight
17
17
  end
@@ -13,23 +13,23 @@ class RDoc::Markup::Table
13
13
  attr_accessor :body
14
14
 
15
15
  # Creates new instance
16
- def initialize header, align, body
16
+ def initialize(header, align, body)
17
17
  @header, @align, @body = header, align, body
18
18
  end
19
19
 
20
20
  # :stopdoc:
21
- def == other
21
+ def ==(other)
22
22
  self.class == other.class and
23
23
  @header == other.header and
24
24
  @align == other.align and
25
25
  @body == other.body
26
26
  end
27
27
 
28
- def accept visitor
28
+ def accept(visitor)
29
29
  visitor.accept_table @header, @body, @align
30
30
  end
31
31
 
32
- def pretty_print q
32
+ def pretty_print(q)
33
33
  q.group 2, '[Table: ', ']' do
34
34
  q.group 2, '[Head: ', ']' do
35
35
  q.seplist @header.zip(@align) do |text, align|
@@ -7,7 +7,7 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
7
7
  ##
8
8
  # Creates a new ToAnsi visitor that is ready to output vibrant ANSI color!
9
9
 
10
- def initialize markup = nil
10
+ def initialize(markup = nil)
11
11
  super
12
12
 
13
13
  @headings.clear
@@ -28,7 +28,7 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
28
28
  ##
29
29
  # Overrides indent width to ensure output lines up correctly.
30
30
 
31
- def accept_list_item_end list_item
31
+ def accept_list_item_end(list_item)
32
32
  width = case @list_type.last
33
33
  when :BULLET then
34
34
  2
@@ -52,7 +52,7 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
52
52
  ##
53
53
  # Adds coloring to note and label list items
54
54
 
55
- def accept_list_item_start list_item
55
+ def accept_list_item_start(list_item)
56
56
  bullet = case @list_type.last
57
57
  when :BULLET then
58
58
  '*'
@@ -81,6 +81,10 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
81
81
  end
82
82
  end
83
83
 
84
+ def calculate_text_width(text)
85
+ text.gsub(/\e\[[\d;]*m/, '').size
86
+ end
87
+
84
88
  ##
85
89
  # Starts accepting with a reset screen
86
90
 
@@ -10,7 +10,7 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
10
10
  ##
11
11
  # Returns a new ToBs that is ready for hot backspace action!
12
12
 
13
- def initialize markup = nil
13
+ def initialize(markup = nil)
14
14
  super
15
15
 
16
16
  @in_b = false
@@ -30,7 +30,7 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
30
30
  ##
31
31
  # Makes heading text bold.
32
32
 
33
- def accept_heading heading
33
+ def accept_heading(heading)
34
34
  use_prefix or @res << ' ' * @indent
35
35
  @res << @headings[heading.level][0]
36
36
  @in_b = true
@@ -43,7 +43,7 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
43
43
  ##
44
44
  # Prepares the visitor for consuming +list_item+
45
45
 
46
- def accept_list_item_start list_item
46
+ def accept_list_item_start(list_item)
47
47
  type = @list_type.last
48
48
 
49
49
  case type
@@ -65,10 +65,14 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
65
65
  end
66
66
  end
67
67
 
68
+ def calculate_text_width(text)
69
+ text.gsub(/_\x08/, '').gsub(/\x08./, '').size
70
+ end
71
+
68
72
  ##
69
73
  # Turns on or off regexp handling for +convert_string+
70
74
 
71
- def annotate tag
75
+ def annotate(tag)
72
76
  case tag
73
77
  when '+b' then @in_b = true
74
78
  when '-b' then @in_b = false
@@ -81,14 +85,14 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
81
85
  ##
82
86
  # Calls convert_string on the result of convert_regexp_handling
83
87
 
84
- def convert_regexp_handling target
88
+ def convert_regexp_handling(target)
85
89
  convert_string super
86
90
  end
87
91
 
88
92
  ##
89
93
  # Adds bold or underline mixed with backspaces
90
94
 
91
- def convert_string string
95
+ def convert_string(string)
92
96
  return string unless @in_b or @in_em
93
97
  chars = if @in_b then
94
98
  string.chars.map do |char| "#{char}\b#{char}" end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'cgi/util'
2
+ require 'cgi/escape'
3
+ require 'cgi/util' unless defined?(CGI::EscapeExt)
3
4
 
4
5
  ##
5
6
  # Outputs RDoc markup as HTML.
@@ -42,7 +43,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
42
43
  ##
43
44
  # Creates a new formatter that will output HTML
44
45
 
45
- def initialize options, markup = nil
46
+ def initialize(options, markup = nil)
46
47
  super
47
48
 
48
49
  @code_object = nil
@@ -82,7 +83,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
82
83
  add_regexp_handling_TIDYLINK
83
84
  end
84
85
 
85
- def handle_RDOCLINK url # :nodoc:
86
+ def handle_RDOCLINK(url) # :nodoc:
86
87
  case url
87
88
  when /^rdoc-ref:/
88
89
  CGI.escapeHTML($')
@@ -98,7 +99,10 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
98
99
 
99
100
  gen_url CGI.escapeHTML(url), CGI.escapeHTML(text)
100
101
  when /^rdoc-image:/
101
- url, alt = $'.split(":", 2) # Split the string after "rdoc-image:" into url and alt
102
+ # Split the string after "rdoc-image:" into url and alt.
103
+ # "path/to/image.jpg:alt text" => ["path/to/image.jpg", "alt text"]
104
+ # "http://example.com/path/to/image.jpg:alt text" => ["http://example.com/path/to/image.jpg", "alt text"]
105
+ url, alt = $'.split(/:(?!\/)/, 2)
102
106
  if alt && !alt.empty?
103
107
  %[<img src="#{CGI.escapeHTML(url)}" alt="#{CGI.escapeHTML(alt)}">]
104
108
  else
@@ -112,7 +116,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
112
116
  ##
113
117
  # +target+ is a <code><br></code>
114
118
 
115
- def handle_regexp_HARD_BREAK target
119
+ def handle_regexp_HARD_BREAK(target)
116
120
  '<br>'
117
121
  end
118
122
 
@@ -143,7 +147,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
143
147
  # For the +rdoc-label+ scheme the footnote and label prefixes are stripped
144
148
  # when creating a link. All other contents will be linked verbatim.
145
149
 
146
- def handle_regexp_RDOCLINK target
150
+ def handle_regexp_RDOCLINK(target)
147
151
  handle_RDOCLINK target.text
148
152
  end
149
153
 
@@ -154,19 +158,16 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
154
158
  def handle_regexp_TIDYLINK(target)
155
159
  text = target.text
156
160
 
157
- return text unless
158
- text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/
159
-
160
- label = $1
161
- url = CGI.escapeHTML($2)
161
+ if tidy_link_capturing?
162
+ return finish_tidy_link(text)
163
+ end
162
164
 
163
- if /^rdoc-image:/ =~ label
164
- label = handle_RDOCLINK(label)
165
- else
166
- label = CGI.escapeHTML(label)
165
+ if text.start_with?('{') && !text.include?('}')
166
+ start_tidy_link text
167
+ return ''
167
168
  end
168
169
 
169
- gen_url url, label
170
+ convert_complete_tidy_link(text)
170
171
  end
171
172
 
172
173
  # :section: Visitor
@@ -192,7 +193,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
192
193
  ##
193
194
  # Adds +block_quote+ to the output
194
195
 
195
- def accept_block_quote block_quote
196
+ def accept_block_quote(block_quote)
196
197
  @res << "\n<blockquote>"
197
198
 
198
199
  block_quote.parts.each do |part|
@@ -205,7 +206,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
205
206
  ##
206
207
  # Adds +paragraph+ to the output
207
208
 
208
- def accept_paragraph paragraph
209
+ def accept_paragraph(paragraph)
209
210
  @res << "\n<p>"
210
211
  text = paragraph.text @hard_break
211
212
  text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K\r?\n(?=(?(1)(#{SPACE_SEPARATED_LETTER_CLASS})?))/o) {
@@ -218,7 +219,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
218
219
  ##
219
220
  # Adds +verbatim+ to the output
220
221
 
221
- def accept_verbatim verbatim
222
+ def accept_verbatim(verbatim)
222
223
  text = verbatim.text.rstrip
223
224
 
224
225
  klass = nil
@@ -248,7 +249,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
248
249
  ##
249
250
  # Adds +rule+ to the output
250
251
 
251
- def accept_rule rule
252
+ def accept_rule(rule)
252
253
  @res << "<hr>\n"
253
254
  end
254
255
 
@@ -301,7 +302,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
301
302
  # Adds +heading+ to the output. The headings greater than 6 are trimmed to
302
303
  # level 6.
303
304
 
304
- def accept_heading heading
305
+ def accept_heading(heading)
305
306
  level = [6, heading.level].min
306
307
 
307
308
  label = heading.label @code_object
@@ -311,25 +312,27 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
311
312
  else
312
313
  "\n<h#{level}>"
313
314
  end
314
- @res << to_html(heading.text)
315
- unless @options.pipe then
316
- @res << "<span><a href=\"##{label}\">&para;</a>"
317
- @res << " <a href=\"#top\">&uarr;</a></span>"
315
+
316
+ if @options.pipe
317
+ @res << to_html(heading.text)
318
+ else
319
+ @res << "<a href=\"##{label}\">#{to_html(heading.text)}</a>"
318
320
  end
321
+
319
322
  @res << "</h#{level}>\n"
320
323
  end
321
324
 
322
325
  ##
323
326
  # Adds +raw+ to the output
324
327
 
325
- def accept_raw raw
328
+ def accept_raw(raw)
326
329
  @res << raw.parts.join("\n")
327
330
  end
328
331
 
329
332
  ##
330
333
  # Adds +table+ to the output
331
334
 
332
- def accept_table header, body, aligns
335
+ def accept_table(header, body, aligns)
333
336
  @res << "\n<table role=\"table\">\n<thead>\n<tr>\n"
334
337
  header.zip(aligns) do |text, align|
335
338
  @res << '<th'
@@ -362,7 +365,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
362
365
  # Generate a link to +url+ with content +text+. Handles the special cases
363
366
  # for img: and link: described under handle_regexp_HYPERLINK
364
367
 
365
- def gen_url url, text
368
+ def gen_url(url, text)
366
369
  scheme, url, id = parse_url url
367
370
 
368
371
  if %w[http https link].include?(scheme) and
@@ -436,7 +439,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
436
439
  ##
437
440
  # Returns true if text is valid ruby syntax
438
441
 
439
- def parseable? text
442
+ def parseable?(text)
440
443
  verbose, $VERBOSE = $VERBOSE, nil
441
444
  catch(:valid) do
442
445
  eval("BEGIN { throw :valid, true }\n#{text}")
@@ -450,8 +453,157 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
450
453
  ##
451
454
  # Converts +item+ to HTML using RDoc::Text#to_html
452
455
 
453
- def to_html item
456
+ def to_html(item)
454
457
  super convert_flow @am.flow item
455
458
  end
456
459
 
460
+ private
461
+
462
+ def convert_flow(flow_items)
463
+ res = []
464
+
465
+ flow_items.each do |item|
466
+ case item
467
+ when String
468
+ append_flow_fragment res, convert_string(item)
469
+ when RDoc::Markup::AttrChanger
470
+ off_tags res, item
471
+ on_tags res, item
472
+ when RDoc::Markup::RegexpHandling
473
+ append_flow_fragment res, convert_regexp_handling(item)
474
+ else
475
+ raise "Unknown flow element: #{item.inspect}"
476
+ end
477
+ end
478
+
479
+ res.join
480
+ end
481
+
482
+ def append_flow_fragment(res, fragment)
483
+ return if fragment.nil? || fragment.empty?
484
+
485
+ emit_tidy_link_fragment(res, fragment)
486
+ end
487
+
488
+ def append_to_tidy_label(fragment)
489
+ @tidy_link_buffer << fragment
490
+ end
491
+
492
+ ##
493
+ # Matches an entire tidy link with a braced label "{label}[url]".
494
+ #
495
+ # Capture 1: label contents.
496
+ # Capture 2: URL text.
497
+ # Capture 3: trailing content.
498
+ TIDY_LINK_WITH_BRACES = /\A\{(.*?)\}\[(.*?)\](.*)\z/
499
+
500
+ ##
501
+ # Matches the tail of a braced tidy link when the opening brace was
502
+ # consumed earlier while accumulating the label text.
503
+ #
504
+ # Capture 1: remaining label content.
505
+ # Capture 2: URL text.
506
+ # Capture 3: trailing content.
507
+ TIDY_LINK_WITH_BRACES_TAIL = /\A(.*?)\}\[(.*?)\](.*)\z/
508
+
509
+ ##
510
+ # Matches a tidy link with a single-word label "label[url]".
511
+ #
512
+ # Capture 1: the single-word label (no whitespace).
513
+ # Capture 2: URL text between the brackets.
514
+ TIDY_LINK_SINGLE_WORD = /\A(\S+)\[(.*?)\](.*)\z/
515
+
516
+ def convert_complete_tidy_link(text)
517
+ return text unless
518
+ text =~ TIDY_LINK_WITH_BRACES or text =~ TIDY_LINK_SINGLE_WORD
519
+
520
+ label = $1
521
+ url = CGI.escapeHTML($2)
522
+
523
+ label_html = if /^rdoc-image:/ =~ label
524
+ handle_RDOCLINK(label)
525
+ else
526
+ render_tidy_link_label(label)
527
+ end
528
+
529
+ gen_url url, label_html
530
+ end
531
+
532
+ def emit_tidy_link_fragment(res, fragment)
533
+ if tidy_link_capturing?
534
+ append_to_tidy_label fragment
535
+ else
536
+ res << fragment
537
+ end
538
+ end
539
+
540
+ def finish_tidy_link(text)
541
+ label_tail, url, trailing = extract_tidy_link_parts(text)
542
+ append_to_tidy_label CGI.escapeHTML(label_tail) unless label_tail.empty?
543
+
544
+ return '' unless url
545
+
546
+ label_html = @tidy_link_buffer
547
+ @tidy_link_buffer = nil
548
+ link = gen_url(url, label_html)
549
+
550
+ return link if trailing.empty?
551
+
552
+ link + CGI.escapeHTML(trailing)
553
+ end
554
+
555
+ def extract_tidy_link_parts(text)
556
+ if text =~ TIDY_LINK_WITH_BRACES
557
+ [$1, CGI.escapeHTML($2), $3]
558
+ elsif text =~ TIDY_LINK_WITH_BRACES_TAIL
559
+ [$1, CGI.escapeHTML($2), $3]
560
+ elsif text =~ TIDY_LINK_SINGLE_WORD
561
+ [$1, CGI.escapeHTML($2), $3]
562
+ else
563
+ [text, nil, '']
564
+ end
565
+ end
566
+
567
+ def on_tags(res, item)
568
+ each_attr_tag(item.turn_on) do |tag|
569
+ emit_tidy_link_fragment(res, annotate(tag.on))
570
+ @in_tt += 1 if tt? tag
571
+ end
572
+ end
573
+
574
+ def off_tags(res, item)
575
+ each_attr_tag(item.turn_off, true) do |tag|
576
+ emit_tidy_link_fragment(res, annotate(tag.off))
577
+ @in_tt -= 1 if tt? tag
578
+ end
579
+ end
580
+
581
+ def start_tidy_link(text)
582
+ @tidy_link_buffer = String.new
583
+ append_to_tidy_label CGI.escapeHTML(text.delete_prefix('{'))
584
+ end
585
+
586
+ def tidy_link_capturing?
587
+ !!@tidy_link_buffer
588
+ end
589
+
590
+ def render_tidy_link_label(label)
591
+ RDoc::Markup::LinkLabelToHtml.render(label, @options, @from_path)
592
+ end
593
+ end
594
+
595
+ ##
596
+ # Formatter dedicated to rendering tidy link labels without mutating the
597
+ # calling formatter's state.
598
+
599
+ class RDoc::Markup::LinkLabelToHtml < RDoc::Markup::ToHtml
600
+ def self.render(label, options, from_path)
601
+ new(options, from_path).to_html(label)
602
+ end
603
+
604
+ def initialize(options, from_path = nil)
605
+ super(options)
606
+
607
+ self.from_path = from_path if from_path
608
+ end
457
609
  end
@@ -58,7 +58,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
58
58
  # Creates a link to the reference +name+ if the name exists. If +text+ is
59
59
  # given it is used as the link text, otherwise +name+ is used.
60
60
 
61
- def cross_reference name, text = nil, code = true, rdoc_ref: false
61
+ def cross_reference(name, text = nil, code = true, rdoc_ref: false)
62
62
  lookup = name
63
63
 
64
64
  name = name[1..-1] unless @show_hash if name[0, 1] == '#'
@@ -101,7 +101,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
101
101
  # Handles <tt>rdoc-ref:</tt> scheme links and allows RDoc::Markup::ToHtml to
102
102
  # handle other schemes.
103
103
 
104
- def handle_regexp_HYPERLINK target
104
+ def handle_regexp_HYPERLINK(target)
105
105
  url = target.text
106
106
 
107
107
  case url
@@ -120,7 +120,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
120
120
  # All other contents are handled by
121
121
  # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]
122
122
 
123
- def handle_regexp_RDOCLINK target
123
+ def handle_regexp_RDOCLINK(target)
124
124
  url = target.text
125
125
 
126
126
  case url
@@ -135,7 +135,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
135
135
  # Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
136
136
  # RDoc::Markup::ToHtml to handle other schemes.
137
137
 
138
- def gen_url url, text
138
+ def gen_url(url, text)
139
139
  if url =~ /\Ardoc-ref:/
140
140
  name = $'
141
141
  cross_reference name, text, name == text, rdoc_ref: true
@@ -147,7 +147,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
147
147
  ##
148
148
  # Creates an HTML link to +name+ with the given +text+.
149
149
 
150
- def link name, text, code = true, rdoc_ref: false
150
+ def link(name, text, code = true, rdoc_ref: false)
151
151
  if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
152
152
  name = $1
153
153
  label = $'
@@ -184,38 +184,35 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
184
184
  end
185
185
  end
186
186
 
187
- def convert_flow(flow)
187
+ def convert_flow(flow_items, &block)
188
188
  res = []
189
189
 
190
190
  i = 0
191
- while i < flow.size
192
- item = flow[i]
193
- i += 1
191
+ while i < flow_items.size
192
+ item = flow_items[i]
193
+
194
194
  case item
195
- when RDoc::Markup::AttrChanger then
196
- # Make "+Class#method+" a cross reference
197
- if tt_tag?(item.turn_on) and
198
- String === (str = flow[i]) and
199
- RDoc::Markup::AttrChanger === flow[i+1] and
200
- tt_tag?(flow[i+1].turn_off, true) and
201
- (@options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP).match?(str) and
202
- (text = cross_reference str) != str
203
- then
204
- text = yield text, res if defined?(yield)
205
- res << text
206
- i += 2
195
+ when RDoc::Markup::AttrChanger
196
+ if !tidy_link_capturing? && (text = convert_tt_crossref(flow_items, i))
197
+ text = block.call(text, res) if block
198
+ append_flow_fragment res, text
199
+ i += 3
207
200
  next
208
201
  end
202
+
209
203
  off_tags res, item
210
- on_tags res, item
211
- when String then
204
+ on_tags res, item
205
+ i += 1
206
+ when String
212
207
  text = convert_string(item)
213
- text = yield text, res if defined?(yield)
214
- res << text
215
- when RDoc::Markup::RegexpHandling then
208
+ text = block.call(text, res) if block
209
+ append_flow_fragment res, text
210
+ i += 1
211
+ when RDoc::Markup::RegexpHandling
216
212
  text = convert_regexp_handling(item)
217
- text = yield text, res if defined?(yield)
218
- res << text
213
+ text = block.call(text, res) if block
214
+ append_flow_fragment res, text
215
+ i += 1
219
216
  else
220
217
  raise "Unknown flow element: #{item.inspect}"
221
218
  end
@@ -223,4 +220,37 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
223
220
 
224
221
  res.join('')
225
222
  end
223
+
224
+ private
225
+
226
+ ##
227
+ # Detects <tt>...</tt> spans that contain a single cross-reference candidate.
228
+ # When the candidate occupies the whole span (aside from trailing
229
+ # punctuation), the tt markup is replaced by the resolved cross-reference.
230
+
231
+ def convert_tt_crossref(flow_items, index)
232
+ opener = flow_items[index]
233
+ return unless tt_tag?(opener.turn_on)
234
+
235
+ string = flow_items[index + 1]
236
+ closer = flow_items[index + 2]
237
+
238
+ return unless String === string
239
+ return unless RDoc::Markup::AttrChanger === closer
240
+ return unless tt_tag?(closer.turn_off, true)
241
+
242
+ crossref_regexp = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
243
+ match = crossref_regexp.match(string)
244
+ return unless match
245
+ return unless match.begin(1).zero?
246
+
247
+ trailing = match.post_match
248
+ # Only convert when the remainder is punctuation/whitespace so other tt text stays literal.
249
+ return unless trailing.match?(/\A[[:punct:]\s]*\z/)
250
+
251
+ text = cross_reference(string)
252
+ return if text == string
253
+
254
+ text
255
+ end
226
256
  end