rdoc 6.3.4.1 → 8.0.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 (205) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +195 -0
  3. data/History.rdoc +65 -63
  4. data/LEGAL.rdoc +7 -1
  5. data/LICENSE.rdoc +6 -0
  6. data/README.md +236 -0
  7. data/RI.md +842 -0
  8. data/TODO.rdoc +8 -7
  9. data/doc/markup_reference/markdown.md +659 -0
  10. data/doc/markup_reference/rdoc.rdoc +1169 -0
  11. data/exe/rdoc +0 -1
  12. data/lib/rdoc/{alias.rb → code_object/alias.rb} +4 -18
  13. data/lib/rdoc/{any_method.rb → code_object/any_method.rb} +50 -24
  14. data/lib/rdoc/{attr.rb → code_object/attr.rb} +16 -14
  15. data/lib/rdoc/{class_module.rb → code_object/class_module.rb} +225 -58
  16. data/lib/rdoc/{constant.rb → code_object/constant.rb} +44 -10
  17. data/lib/rdoc/code_object/context/section.rb +182 -0
  18. data/lib/rdoc/{context.rb → code_object/context.rb} +78 -106
  19. data/lib/rdoc/{extend.rb → code_object/extend.rb} +0 -1
  20. data/lib/rdoc/{include.rb → code_object/include.rb} +0 -1
  21. data/lib/rdoc/{method_attr.rb → code_object/method_attr.rb} +46 -48
  22. data/lib/rdoc/{mixin.rb → code_object/mixin.rb} +6 -4
  23. data/lib/rdoc/{normal_class.rb → code_object/normal_class.rb} +2 -3
  24. data/lib/rdoc/{normal_module.rb → code_object/normal_module.rb} +2 -3
  25. data/lib/rdoc/{require.rb → code_object/require.rb} +1 -2
  26. data/lib/rdoc/{single_class.rb → code_object/single_class.rb} +5 -1
  27. data/lib/rdoc/{top_level.rb → code_object/top_level.rb} +60 -63
  28. data/lib/rdoc/code_object.rb +11 -39
  29. data/lib/rdoc/code_objects.rb +1 -2
  30. data/lib/rdoc/comment.rb +202 -99
  31. data/lib/rdoc/cross_reference.rb +75 -62
  32. data/lib/rdoc/encoding.rb +8 -24
  33. data/lib/rdoc/erb_partial.rb +1 -2
  34. data/lib/rdoc/erbio.rb +3 -8
  35. data/lib/rdoc/generator/aliki.rb +200 -0
  36. data/lib/rdoc/generator/darkfish.rb +156 -122
  37. data/lib/rdoc/generator/json_index.rb +8 -24
  38. data/lib/rdoc/generator/markup.rb +70 -34
  39. data/lib/rdoc/generator/pot/message_extractor.rb +7 -7
  40. data/lib/rdoc/generator/pot/po.rb +1 -1
  41. data/lib/rdoc/generator/pot/po_entry.rb +8 -8
  42. data/lib/rdoc/generator/pot.rb +1 -5
  43. data/lib/rdoc/generator/ri.rb +1 -2
  44. data/lib/rdoc/generator/template/aliki/DESIGN.md +536 -0
  45. data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +8 -0
  46. data/lib/rdoc/generator/template/aliki/_footer.rhtml +23 -0
  47. data/lib/rdoc/generator/template/aliki/_head.rhtml +163 -0
  48. data/lib/rdoc/generator/template/aliki/_header.rhtml +56 -0
  49. data/lib/rdoc/generator/template/aliki/_icons.rhtml +208 -0
  50. data/lib/rdoc/generator/template/aliki/_sidebar_ancestors.rhtml +16 -0
  51. data/lib/rdoc/generator/template/aliki/_sidebar_classes.rhtml +15 -0
  52. data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +27 -0
  53. data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +27 -0
  54. data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +16 -0
  55. data/lib/rdoc/generator/template/aliki/_sidebar_methods.rhtml +41 -0
  56. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +67 -0
  57. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +15 -0
  58. data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +21 -0
  59. data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +3 -0
  60. data/lib/rdoc/generator/template/aliki/class.rhtml +230 -0
  61. data/lib/rdoc/generator/template/aliki/css/rdoc.css +2181 -0
  62. data/lib/rdoc/generator/template/aliki/index.rhtml +22 -0
  63. data/lib/rdoc/generator/template/aliki/js/aliki.js +513 -0
  64. data/lib/rdoc/generator/template/aliki/js/bash_highlighter.js +167 -0
  65. data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +299 -0
  66. data/lib/rdoc/generator/template/aliki/js/search_controller.js +129 -0
  67. data/lib/rdoc/generator/template/aliki/js/search_navigation.js +105 -0
  68. data/lib/rdoc/generator/template/aliki/js/search_ranker.js +239 -0
  69. data/lib/rdoc/generator/template/aliki/js/theme-toggle.js +112 -0
  70. data/lib/rdoc/generator/template/aliki/page.rhtml +18 -0
  71. data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +14 -0
  72. data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +65 -0
  73. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +3 -3
  74. data/lib/rdoc/generator/template/darkfish/_head.rhtml +35 -14
  75. data/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +1 -5
  76. data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +11 -9
  77. data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +11 -9
  78. data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +7 -6
  79. data/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +20 -11
  80. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +25 -5
  81. data/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +4 -9
  82. data/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +2 -1
  83. data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +4 -4
  84. data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +28 -7
  85. data/lib/rdoc/generator/template/darkfish/_sidebar_toggle.rhtml +3 -0
  86. data/lib/rdoc/generator/template/darkfish/class.rhtml +138 -90
  87. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +420 -358
  88. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf +0 -0
  89. data/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf +0 -0
  90. data/lib/rdoc/generator/template/darkfish/index.rhtml +14 -12
  91. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +59 -3
  92. data/lib/rdoc/generator/template/darkfish/js/search.js +15 -5
  93. data/lib/rdoc/generator/template/darkfish/page.rhtml +7 -6
  94. data/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml +12 -9
  95. data/lib/rdoc/generator/template/darkfish/servlet_root.rhtml +24 -21
  96. data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +35 -21
  97. data/lib/rdoc/generator/template/json_index/js/navigation.js +8 -8
  98. data/lib/rdoc/generator/template/json_index/js/searcher.js +48 -6
  99. data/lib/rdoc/generator.rb +6 -5
  100. data/lib/rdoc/i18n/text.rb +3 -3
  101. data/lib/rdoc/i18n.rb +1 -1
  102. data/lib/rdoc/known_classes.rb +5 -4
  103. data/lib/rdoc/markdown/entities.rb +0 -1
  104. data/lib/rdoc/markdown/literals.kpeg +0 -2
  105. data/lib/rdoc/markdown/literals.rb +0 -1
  106. data/lib/rdoc/markdown.kpeg +140 -62
  107. data/lib/rdoc/markdown.rb +1015 -873
  108. data/lib/rdoc/markup/blank_line.rb +25 -24
  109. data/lib/rdoc/markup/block_quote.rb +1 -2
  110. data/lib/rdoc/markup/document.rb +10 -11
  111. data/lib/rdoc/markup/element.rb +21 -0
  112. data/lib/rdoc/markup/formatter.rb +134 -115
  113. data/lib/rdoc/markup/hard_break.rb +30 -28
  114. data/lib/rdoc/markup/heading.rb +163 -72
  115. data/lib/rdoc/markup/include.rb +3 -4
  116. data/lib/rdoc/markup/indented_paragraph.rb +4 -5
  117. data/lib/rdoc/markup/inline_parser.rb +312 -0
  118. data/lib/rdoc/markup/list.rb +6 -7
  119. data/lib/rdoc/markup/list_item.rb +6 -7
  120. data/lib/rdoc/markup/paragraph.rb +2 -3
  121. data/lib/rdoc/markup/parser.rb +29 -19
  122. data/lib/rdoc/markup/pre_process.rb +39 -18
  123. data/lib/rdoc/markup/raw.rb +52 -56
  124. data/lib/rdoc/markup/rule.rb +2 -3
  125. data/lib/rdoc/markup/table.rb +49 -32
  126. data/lib/rdoc/markup/to_ansi.rb +58 -8
  127. data/lib/rdoc/markup/to_bs.rb +47 -38
  128. data/lib/rdoc/markup/to_html.rb +343 -105
  129. data/lib/rdoc/markup/to_html_crossref.rb +143 -58
  130. data/lib/rdoc/markup/to_html_snippet.rb +78 -76
  131. data/lib/rdoc/markup/to_joined_paragraph.rb +3 -9
  132. data/lib/rdoc/markup/to_label.rb +34 -25
  133. data/lib/rdoc/markup/to_markdown.rb +74 -51
  134. data/lib/rdoc/markup/to_rdoc.rb +141 -82
  135. data/lib/rdoc/markup/to_table_of_contents.rb +4 -5
  136. data/lib/rdoc/markup/to_test.rb +10 -3
  137. data/lib/rdoc/markup/to_tt_only.rb +17 -31
  138. data/lib/rdoc/markup/verbatim.rb +5 -6
  139. data/lib/rdoc/markup.rb +59 -707
  140. data/lib/rdoc/options.rb +228 -101
  141. data/lib/rdoc/parser/c.rb +186 -184
  142. data/lib/rdoc/parser/changelog.rb +57 -13
  143. data/lib/rdoc/parser/markdown.rb +0 -2
  144. data/lib/rdoc/parser/rbs.rb +275 -0
  145. data/lib/rdoc/parser/rd.rb +0 -1
  146. data/lib/rdoc/parser/ruby.rb +963 -2024
  147. data/lib/rdoc/parser/ruby_colorizer.rb +253 -0
  148. data/lib/rdoc/parser/simple.rb +6 -23
  149. data/lib/rdoc/parser/text.rb +0 -1
  150. data/lib/rdoc/parser.rb +35 -14
  151. data/lib/rdoc/rbs_helper.rb +186 -0
  152. data/lib/rdoc/rd/block_parser.rb +659 -11
  153. data/lib/rdoc/rd/block_parser.ry +13 -9
  154. data/lib/rdoc/rd/inline.rb +4 -5
  155. data/lib/rdoc/rd/inline_parser.rb +646 -2
  156. data/lib/rdoc/rd.rb +4 -5
  157. data/lib/rdoc/rdoc.rb +234 -90
  158. data/lib/rdoc/ri/driver.rb +172 -172
  159. data/lib/rdoc/ri/paths.rb +3 -3
  160. data/lib/rdoc/{servlet.rb → ri/servlet.rb} +28 -27
  161. data/lib/rdoc/ri/store.rb +0 -1
  162. data/lib/rdoc/ri/task.rb +3 -3
  163. data/lib/rdoc/ri.rb +5 -5
  164. data/lib/rdoc/rubygems_hook.rb +106 -25
  165. data/lib/rdoc/server.rb +460 -0
  166. data/lib/rdoc/stats/normal.rb +1 -1
  167. data/lib/rdoc/stats/quiet.rb +1 -2
  168. data/lib/rdoc/stats/verbose.rb +3 -5
  169. data/lib/rdoc/stats.rb +158 -136
  170. data/lib/rdoc/store.rb +267 -48
  171. data/lib/rdoc/task.rb +54 -28
  172. data/lib/rdoc/text.rb +60 -120
  173. data/lib/rdoc/token_stream.rb +30 -45
  174. data/lib/rdoc/tom_doc.rb +9 -15
  175. data/lib/rdoc/version.rb +3 -1
  176. data/lib/rdoc.rb +90 -52
  177. data/lib/rubygems_plugin.rb +14 -0
  178. data/man/ri.1 +2 -0
  179. data/rdoc-logo.svg +43 -0
  180. data/rdoc.gemspec +25 -200
  181. metadata +120 -53
  182. data/CONTRIBUTING.rdoc +0 -220
  183. data/ExampleMarkdown.md +0 -37
  184. data/ExampleRDoc.rdoc +0 -208
  185. data/Gemfile +0 -12
  186. data/README.rdoc +0 -129
  187. data/RI.rdoc +0 -57
  188. data/Rakefile +0 -101
  189. data/bin/console +0 -7
  190. data/bin/setup +0 -6
  191. data/lib/rdoc/anon_class.rb +0 -11
  192. data/lib/rdoc/context/section.rb +0 -232
  193. data/lib/rdoc/generator/template/darkfish/.document +0 -0
  194. data/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +0 -19
  195. data/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +0 -9
  196. data/lib/rdoc/generator/template/json_index/.document +0 -1
  197. data/lib/rdoc/ghost_method.rb +0 -7
  198. data/lib/rdoc/markup/attr_changer.rb +0 -23
  199. data/lib/rdoc/markup/attr_span.rb +0 -36
  200. data/lib/rdoc/markup/attribute_manager.rb +0 -409
  201. data/lib/rdoc/markup/attributes.rb +0 -71
  202. data/lib/rdoc/markup/regexp_handling.rb +0 -41
  203. data/lib/rdoc/meta_method.rb +0 -7
  204. data/lib/rdoc/parser/ripper_state_lex.rb +0 -590
  205. data/lib/rdoc/parser/ruby_tools.rb +0 -167
@@ -8,9 +8,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
8
8
 
9
9
  # :stopdoc:
10
10
  ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP
11
- CLASS_REGEXP_STR = RDoc::CrossReference::CLASS_REGEXP_STR
12
11
  CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP
13
- METHOD_REGEXP_STR = RDoc::CrossReference::METHOD_REGEXP_STR
14
12
  # :startdoc:
15
13
 
16
14
  ##
@@ -29,47 +27,53 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
29
27
  # references are removed unless +show_hash+ is true. Only method names
30
28
  # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true.
31
29
 
32
- def initialize(options, from_path, context, markup = nil)
30
+ def initialize(from_path, context, pipe: false, output_decoration: true,
31
+ hyperlink_all: false, show_hash: false,
32
+ autolink_excluded_words: [], warn_missing_rdoc_ref: true)
33
33
  raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
34
34
 
35
- super options, markup
35
+ super(pipe: pipe, output_decoration: output_decoration)
36
36
 
37
37
  @context = context
38
38
  @from_path = from_path
39
- @hyperlink_all = @options.hyperlink_all
40
- @show_hash = @options.show_hash
39
+ @hyperlink_all = hyperlink_all
40
+ @show_hash = show_hash
41
+ @autolink_excluded_words = autolink_excluded_words
42
+ @warn_missing_rdoc_ref = warn_missing_rdoc_ref
41
43
 
42
44
  @cross_reference = RDoc::CrossReference.new @context
43
45
  end
44
46
 
47
+ # :nodoc:
45
48
  def init_link_notation_regexp_handlings
46
49
  add_regexp_handling_RDOCLINK
47
50
 
48
51
  # The crossref must be linked before tidylink because Klass.method[:sym]
49
52
  # will be processed as a tidylink first and will be broken.
50
- crossref_re = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
53
+ crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
51
54
  @markup.add_regexp_handling crossref_re, :CROSSREF
52
-
53
- add_regexp_handling_TIDYLINK
54
55
  end
55
56
 
56
57
  ##
57
58
  # Creates a link to the reference +name+ if the name exists. If +text+ is
58
59
  # given it is used as the link text, otherwise +name+ is used.
60
+ # Returns +nil+ if the link target could not be resolved.
59
61
 
60
- def cross_reference name, text = nil, code = true
61
- lookup = name
62
-
63
- name = name[1..-1] unless @show_hash if name[0, 1] == '#'
62
+ def cross_reference(name, text = nil, code = true, rdoc_ref: false)
63
+ # Strip '#' for link display text (e.g. #method shows as "method" in links)
64
+ display = !@show_hash && name.start_with?('#') ? name[1..] : name
64
65
 
65
- if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/
66
- text ||= "#{CGI.unescape $'} at <code>#{$1}</code>"
66
+ if !display.end_with?('+@', '-@') && match = display.match(/(.*[^#:])?@(.*)/)
67
+ context_name = match[1]
68
+ label = convert_string(RDoc::Text.decode_legacy_label(match[2]))
69
+ text ||= "#{label} at <code>#{convert_string(context_name)}</code>" if context_name
70
+ text ||= label
67
71
  code = false
68
72
  else
69
- text ||= name
73
+ text ||= convert_string(display)
70
74
  end
71
75
 
72
- link lookup, text, code
76
+ link(name, text, code, rdoc_ref: rdoc_ref)
73
77
  end
74
78
 
75
79
  ##
@@ -79,8 +83,9 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
79
83
  # example, ToHtml is found, even without the <tt>RDoc::Markup::</tt> prefix,
80
84
  # because we look for it in module Markup first.
81
85
 
82
- def handle_regexp_CROSSREF(target)
83
- name = target.text
86
+ def handle_regexp_CROSSREF(name)
87
+ return convert_string(name) if in_tidylink_label?
88
+ return name if @autolink_excluded_words&.include?(name)
84
89
 
85
90
  return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails
86
91
 
@@ -90,18 +95,23 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
90
95
  # cross-references to "new" in text, for instance)
91
96
  return name if name =~ /\A[a-z]*\z/
92
97
  end
93
-
94
- cross_reference name
98
+ cross_reference(name, rdoc_ref: false) || convert_string(name)
95
99
  end
96
100
 
97
101
  ##
98
102
  # Handles <tt>rdoc-ref:</tt> scheme links and allows RDoc::Markup::ToHtml to
99
103
  # handle other schemes.
100
104
 
101
- def handle_regexp_HYPERLINK target
102
- return cross_reference $' if target.text =~ /\Ardoc-ref:/
105
+ def handle_regexp_HYPERLINK(url)
106
+ return convert_string(url) if in_tidylink_label?
103
107
 
104
- super
108
+ case url
109
+ when /\Ardoc-ref:/
110
+ ref = $'
111
+ cross_reference(ref, rdoc_ref: true) || convert_string(ref)
112
+ else
113
+ super
114
+ end
105
115
  end
106
116
 
107
117
  ##
@@ -112,12 +122,15 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
112
122
  # All other contents are handled by
113
123
  # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]
114
124
 
115
- def handle_regexp_RDOCLINK target
116
- url = target.text
117
-
125
+ def handle_regexp_RDOCLINK(url)
118
126
  case url
119
- when /\Ardoc-ref:/ then
120
- cross_reference $'
127
+ when /\Ardoc-ref:/
128
+ if in_tidylink_label?
129
+ convert_string(url)
130
+ else
131
+ ref = $'
132
+ cross_reference(ref, rdoc_ref: true) || convert_string(ref)
133
+ end
121
134
  else
122
135
  super
123
136
  end
@@ -127,50 +140,122 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
127
140
  # Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
128
141
  # RDoc::Markup::ToHtml to handle other schemes.
129
142
 
130
- def gen_url url, text
131
- return super unless url =~ /\Ardoc-ref:/
132
-
133
- name = $'
134
- cross_reference name, text, name == text
143
+ def gen_url(url, text)
144
+ if url =~ /\Ardoc-ref:/
145
+ name = $'
146
+ cross_reference(name, text, name == text, rdoc_ref: true) || text
147
+ else
148
+ super
149
+ end
135
150
  end
136
151
 
137
152
  ##
138
- # Creates an HTML link to +name+ with the given +text+.
153
+ # Creates an HTML link to +name+ with the given +html_string+.
154
+ # +html_string+ should be already escaped and may contain HTML tags.
155
+ # Returns the link HTML string, or +nil+ if the reference could not be resolved.
139
156
 
140
- def link name, text, code = true
141
- if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/
157
+ def link(name, html_string, code = true, rdoc_ref: false)
158
+ if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
142
159
  name = $1
143
160
  label = $'
144
161
  end
145
162
 
146
- ref = @cross_reference.resolve name, text
163
+ ref = @cross_reference.resolve name if name
147
164
 
148
- case ref
149
- when String then
150
- ref
151
- else
152
- path = ref.as_href @from_path
165
+ # Non-text source files (C, Ruby, etc.) don't get HTML pages generated,
166
+ # so don't auto-link to them. Explicit rdoc-ref: links are still allowed.
167
+ if !rdoc_ref && RDoc::TopLevel === ref && !ref.text?
168
+ return
169
+ end
170
+
171
+ if ref
172
+ path = ref.as_href(@from_path)
153
173
 
154
174
  if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref)
155
- text = "<code>#{CGI.escapeHTML text}</code>"
175
+ html_string = "<code>#{html_string}</code>"
156
176
  end
177
+ elsif name
178
+ if rdoc_ref && @warn_missing_rdoc_ref
179
+ puts "#{@from_path}: `rdoc-ref:#{name}` can't be resolved for `#{html_string}`"
180
+ end
181
+ return
182
+ else
183
+ # A bare label reference like @foo still produces a valid anchor link
184
+ return unless label
185
+ path = +""
186
+ end
157
187
 
158
- if path =~ /#/ then
159
- path << "-label-#{label}"
160
- elsif ref.sections and
161
- ref.sections.any? { |section| label == section.title } then
162
- path << "##{label}"
188
+ if label
189
+ # Decode legacy labels (e.g., "What-27s+Here" -> "What's Here")
190
+ # then convert to GitHub-style anchor format
191
+ decoded_label = RDoc::Text.decode_legacy_label(label)
192
+ formatted_label = RDoc::Text.to_anchor(decoded_label)
193
+
194
+ # Case 1: Path already has an anchor (e.g., method link)
195
+ # Input: C1#method@label -> path="C1.html#method-i-m"
196
+ # Output: C1.html#method-i-m-label
197
+ if path =~ /#/
198
+ path << "-#{formatted_label}"
199
+
200
+ # Case 2: Label matches a section title
201
+ # Input: C1@Section -> path="C1.html", section "Section" exists
202
+ # Output: C1.html#section (uses section.aref for GitHub-style)
203
+ elsif (section = ref&.sections&.find { |s| decoded_label == s.title })
204
+ path << "##{section.aref}"
205
+
206
+ # Case 3: Ref has an aref (class/module context)
207
+ # Input: C1@heading -> path="C1.html", ref=C1 class
208
+ # Output: C1.html#class-c1-heading
209
+ elsif ref.respond_to?(:aref)
210
+ path << "##{ref.aref}-#{formatted_label}"
211
+
212
+ # Case 4: No context, just the label (e.g., TopLevel/file)
213
+ # Input: README@section -> path="README_md.html"
214
+ # Output: README_md.html#section
163
215
  else
164
- if ref.respond_to?(:aref)
165
- path << "##{ref.aref}-label-#{label}"
166
- else
167
- path << "#label-#{label}"
168
- end
169
- end if label
170
-
171
- "<a href=\"#{path}\">#{text}</a>"
216
+ path << "##{formatted_label}"
217
+ end
172
218
  end
219
+
220
+ "<a href=\"#{path}\">#{html_string}</a>"
173
221
  end
174
222
 
175
- end
223
+ def handle_TT(code)
224
+ emit_inline(tt_cross_reference(code) || "<code>#{convert_string(code)}</code>")
225
+ end
226
+
227
+ # Applies additional special handling on top of the one defined in ToHtml.
228
+ # When a tidy link is <tt>{Foo}[rdoc-ref:Foo]</tt>, the label part is surrounded by <tt><code></code></tt>.
229
+ # TODO: reconsider this workaround.
230
+ def apply_tidylink_label_special_handling(label, url)
231
+ if url == "rdoc-ref:#{label}" && cross_reference(label)&.include?('<code>')
232
+ "<code>#{convert_string(label)}</code>"
233
+ else
234
+ super
235
+ end
236
+ end
176
237
 
238
+ # Handles cross-reference and suppressed-crossref inside tt tag.
239
+ # Returns nil if code is not an existing cross-reference nor a suppressed-crossref.
240
+ def tt_cross_reference(code)
241
+ return if in_tidylink_label?
242
+
243
+ crossref_regexp = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
244
+ # REGEXP sometimes matches a string that starts with a backslash but is not a
245
+ # suppressed cross-reference (for example, `\+`), so the backslash-removed
246
+ # part needs to be checked against crossref_regexp.
247
+ match = crossref_regexp.match(code.delete_prefix('\\'))
248
+ return unless match && match.begin(1).zero?
249
+ return unless match.post_match.match?(/\A[[:punct:]\s]*\z/)
250
+
251
+ # cross_reference(file_page) may return a link without code tag.
252
+ # We need to check it because this method shouldn't return an html text without code tag.
253
+ if code.start_with?('\\')
254
+ # Remove leading backslash if crossref exists
255
+ "<code>#{convert_string(code[1..])}</code>" if cross_reference(code[1..])&.include?('<code>')
256
+ else
257
+ html = cross_reference(code)
258
+ html if html&.include?('<code>')
259
+ end
260
+ end
261
+ end
@@ -34,8 +34,8 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
34
34
  # next word boundary after the given number of +characters+ or +paragraphs+
35
35
  # of text have been encountered.
36
36
 
37
- def initialize options, characters = 100, paragraphs = 3, markup = nil
38
- super options, markup
37
+ def initialize(characters = 100, paragraphs = 3)
38
+ super()
39
39
 
40
40
  @character_limit = characters
41
41
  @paragraph_limit = paragraphs
@@ -50,7 +50,7 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
50
50
  ##
51
51
  # Adds +heading+ to the output as a paragraph
52
52
 
53
- def accept_heading heading
53
+ def accept_heading(heading)
54
54
  @res << "<p>#{to_html heading.text}\n"
55
55
 
56
56
  add_paragraph
@@ -66,7 +66,10 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
66
66
 
67
67
  alias accept_rule ignore
68
68
 
69
- def accept_paragraph paragraph
69
+ ##
70
+ # Adds +paragraph+ to the output
71
+
72
+ def accept_paragraph(paragraph)
70
73
  para = @in_list_entry.last || "<p>"
71
74
 
72
75
  text = paragraph.text @hard_break
@@ -79,20 +82,20 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
79
82
  ##
80
83
  # Finishes consumption of +list_item+
81
84
 
82
- def accept_list_item_end list_item
85
+ def accept_list_item_end(list_item)
83
86
  end
84
87
 
85
88
  ##
86
89
  # Prepares the visitor for consuming +list_item+
87
90
 
88
- def accept_list_item_start list_item
91
+ def accept_list_item_start(list_item)
89
92
  @res << list_item_start(list_item, @list.last)
90
93
  end
91
94
 
92
95
  ##
93
96
  # Prepares the visitor for consuming +list+
94
97
 
95
- def accept_list_start list
98
+ def accept_list_start(list)
96
99
  @list << list.type
97
100
  @res << html_list_name(list.type, true)
98
101
  @in_list_entry.push ''
@@ -101,12 +104,12 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
101
104
  ##
102
105
  # Adds +verbatim+ to the output
103
106
 
104
- def accept_verbatim verbatim
107
+ def accept_verbatim(verbatim)
105
108
  throw :done if @characters >= @character_limit
106
109
  input = verbatim.text.rstrip
107
-
108
- text = truncate input
109
- text << ' ...' unless text == input
110
+ text = truncate(input, @character_limit - @characters)
111
+ @characters += input.length
112
+ text << " #{TO_HTML_CHARACTERS[text.encoding][:ellipsis]}" unless text == input
110
113
 
111
114
  super RDoc::Markup::Verbatim.new text
112
115
 
@@ -125,22 +128,14 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
125
128
  ##
126
129
  # Removes escaping from the cross-references in +target+
127
130
 
128
- def handle_regexp_CROSSREF target
129
- target.text.sub(/\A\\/, '')
130
- end
131
-
132
- ##
133
- # +target+ is a <code><br></code>
134
-
135
- def handle_regexp_HARD_BREAK target
136
- @characters -= 4
137
- '<br>'
131
+ def handle_regexp_CROSSREF(text)
132
+ text.sub(/\A\\/, '')
138
133
  end
139
134
 
140
135
  ##
141
136
  # Lists are paragraphs, but notes and labels have a separator
142
137
 
143
- def list_item_start list_item, list_type
138
+ def list_item_start(list_item, list_type)
144
139
  throw :done if @characters >= @character_limit
145
140
 
146
141
  case list_type
@@ -165,7 +160,7 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
165
160
  # Returns just the text of +link+, +url+ is only used to determine the link
166
161
  # type.
167
162
 
168
- def gen_url url, text
163
+ def gen_url(url, text)
169
164
  if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
170
165
  type = "link"
171
166
  elsif url =~ /([A-Za-z]+):(.*)/ then
@@ -185,7 +180,7 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
185
180
  ##
186
181
  # In snippets, there are no lists
187
182
 
188
- def html_list_name list_type, open_tag
183
+ def html_list_name(list_type, open_tag)
189
184
  ''
190
185
  end
191
186
 
@@ -201,7 +196,7 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
201
196
  ##
202
197
  # Marks up +content+
203
198
 
204
- def convert content
199
+ def convert(content)
205
200
  catch :done do
206
201
  return super
207
202
  end
@@ -209,77 +204,84 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
209
204
  end_accepting
210
205
  end
211
206
 
212
- ##
213
- # Converts flow items +flow+
207
+ def handle_PLAIN_TEXT(text) # :nodoc:
208
+ return if inline_limit_reached?
214
209
 
215
- def convert_flow flow
216
- throw :done if @characters >= @character_limit
210
+ truncated = truncate(text, @inline_character_limit)
211
+ @inline_character_limit -= text.size
212
+ emit_inline(convert_string(truncated))
213
+ end
217
214
 
218
- res = []
219
- @mask = 0
220
-
221
- flow.each do |item|
222
- case item
223
- when RDoc::Markup::AttrChanger then
224
- off_tags res, item
225
- on_tags res, item
226
- when String then
227
- text = convert_string item
228
- res << truncate(text)
229
- when RDoc::Markup::RegexpHandling then
230
- text = convert_regexp_handling item
231
- res << truncate(text)
232
- else
233
- raise "Unknown flow element: #{item.inspect}"
234
- end
235
-
236
- if @characters >= @character_limit then
237
- off_tags res, RDoc::Markup::AttrChanger.new(0, @mask)
238
- break
239
- end
240
- end
215
+ def handle_REGEXP_HANDLING_TEXT(text) # :nodoc:
216
+ return if inline_limit_reached?
241
217
 
242
- res << ' ...' if @characters >= @character_limit
218
+ # We can't truncate text including html tags.
219
+ # Just emit as is, and count all characters including html tag part.
220
+ emit_inline(text)
221
+ @inline_character_limit -= text.size
222
+ end
243
223
 
244
- res.join
224
+ def handle_BOLD(nodes)
225
+ super unless inline_limit_reached?
245
226
  end
246
227
 
247
- ##
248
- # Maintains a bitmask to allow HTML elements to be closed properly. See
249
- # RDoc::Markup::Formatter.
228
+ def handle_BOLD_WORD(word)
229
+ super unless inline_limit_reached?
230
+ end
231
+
232
+ def handle_EM(nodes)
233
+ super unless inline_limit_reached?
234
+ end
250
235
 
251
- def on_tags res, item
252
- @mask ^= item.turn_on
236
+ def handle_EM_WORD(word)
237
+ super unless inline_limit_reached?
238
+ end
253
239
 
254
- super
240
+ def handle_TT(code)
241
+ super unless inline_limit_reached?
255
242
  end
256
243
 
257
- ##
258
- # Maintains a bitmask to allow HTML elements to be closed properly. See
259
- # RDoc::Markup::Formatter.
244
+ def handle_STRIKE(nodes)
245
+ super unless inline_limit_reached?
246
+ end
260
247
 
261
- def off_tags res, item
262
- @mask ^= item.turn_off
248
+ def handle_HARD_BREAK
249
+ super unless inline_limit_reached?
250
+ end
263
251
 
264
- super
252
+ def handle_TIDYLINK(label_part, url)
253
+ traverse_inline_nodes(label_part) unless inline_limit_reached?
265
254
  end
266
255
 
267
- ##
268
- # Truncates +text+ at the end of the first word after the character_limit.
256
+ def inline_limit_reached?
257
+ @inline_character_limit <= 0
258
+ end
269
259
 
270
- def truncate text
271
- length = text.length
272
- characters = @characters
273
- @characters += length
260
+ def handle_inline(text)
261
+ limit = @character_limit - @characters
262
+ return ['', 0] if limit <= 0
263
+ @inline_character_limit = limit
264
+ res = super
265
+ res << " #{TO_HTML_CHARACTERS[text.encoding][:ellipsis]}" if @inline_character_limit <= 0
266
+ @characters += limit - @inline_character_limit
267
+ res
268
+ end
274
269
 
275
- return text if @characters < @character_limit
270
+ def to_html(item)
271
+ throw :done if @characters >= @character_limit
272
+ handle_inline(item)
273
+ end
276
274
 
277
- remaining = @character_limit - characters
275
+ ##
276
+ # Truncates +text+ at the end of the first word after the limit.
277
+
278
+ def truncate(text, limit)
279
+ return text if limit >= text.size
280
+ return '' if limit <= 0
278
281
 
279
- text =~ /\A(.{#{remaining},}?)(\s|$)/m # TODO word-break instead of \s?
282
+ text =~ /\A(.{#{limit},}?)(\s|$)/m # TODO word-break instead of \s?
280
283
 
281
284
  $1
282
285
  end
283
286
 
284
287
  end
285
-
@@ -8,11 +8,6 @@
8
8
  # other markup syntax items will not work.
9
9
 
10
10
  class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
11
-
12
- def initialize # :nodoc:
13
- super nil
14
- end
15
-
16
11
  def start_accepting # :nodoc:
17
12
  end
18
13
 
@@ -22,12 +17,12 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
22
17
  ##
23
18
  # Converts the parts of +paragraph+ to a single entry.
24
19
 
25
- def accept_paragraph paragraph
20
+ def accept_paragraph(paragraph)
26
21
  parts = paragraph.parts.chunk do |part|
27
22
  String === part
28
- end.map do |string, chunk|
23
+ end.flat_map do |string, chunk|
29
24
  string ? chunk.join.rstrip : chunk
30
- end.flatten
25
+ end
31
26
 
32
27
  paragraph.parts.replace parts
33
28
  end
@@ -44,4 +39,3 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
44
39
  alias accept_table ignore
45
40
 
46
41
  end
47
-
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'cgi'
2
+ require 'cgi/escape'
3
+ require 'cgi/util' unless defined?(CGI::EscapeExt)
3
4
 
4
5
  ##
5
6
  # Creates HTML-safe labels suitable for use in id attributes. Tidylinks are
@@ -13,47 +14,57 @@ class RDoc::Markup::ToLabel < RDoc::Markup::Formatter
13
14
  ##
14
15
  # Creates a new formatter that will output HTML-safe labels
15
16
 
16
- def initialize markup = nil
17
- super nil, markup
17
+ def initialize
18
+ super
18
19
 
19
20
  @markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
20
- @markup.add_regexp_handling(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK)
21
-
22
- add_tag :BOLD, '', ''
23
- add_tag :TT, '', ''
24
- add_tag :EM, '', ''
25
21
 
26
22
  @res = []
27
23
  end
28
24
 
29
- ##
30
- # Converts +text+ to an HTML-safe label
25
+ def handle_PLAIN_TEXT(text)
26
+ @res << text
27
+ end
31
28
 
32
- def convert text
33
- label = convert_flow @am.flow text
29
+ def handle_REGEXP_HANDLING_TEXT(text)
30
+ @res << text
31
+ end
34
32
 
35
- CGI.escape(label).gsub('%', '-').sub(/^-/, '')
33
+ def handle_TT(text)
34
+ @res << text
35
+ end
36
+
37
+ def extract_plaintext(text)
38
+ @res = []
39
+ handle_inline(text)
40
+ @res.join
36
41
  end
37
42
 
38
43
  ##
39
- # Converts the CROSSREF +target+ to plain text, removing the suppression
40
- # marker, if any
44
+ # Converts +text+ to an HTML-safe label using GitHub-style anchor formatting.
41
45
 
42
- def handle_regexp_CROSSREF target
43
- text = target.text
46
+ def convert(text)
47
+ label = extract_plaintext(text)
44
48
 
45
- text.sub(/^\\/, '')
49
+ RDoc::Text.to_anchor(label)
46
50
  end
47
51
 
48
52
  ##
49
- # Converts the TIDYLINK +target+ to just the text part
53
+ # Converts +text+ to an HTML-safe label using legacy RDoc formatting.
54
+ # Used for generating backward-compatible anchor aliases.
50
55
 
51
- def handle_regexp_TIDYLINK target
52
- text = target.text
56
+ def convert_legacy(text)
57
+ label = extract_plaintext(text)
53
58
 
54
- return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
59
+ CGI.escape(label).gsub('%', '-').sub(/^-/, '')
60
+ end
55
61
 
56
- $1
62
+ ##
63
+ # Converts the CROSSREF +target+ to plain text, removing the suppression
64
+ # marker, if any
65
+
66
+ def handle_regexp_CROSSREF(text)
67
+ text.sub(/^\\/, '')
57
68
  end
58
69
 
59
70
  alias accept_blank_line ignore
@@ -68,8 +79,6 @@ class RDoc::Markup::ToLabel < RDoc::Markup::Formatter
68
79
  alias accept_rule ignore
69
80
  alias accept_verbatim ignore
70
81
  alias end_accepting ignore
71
- alias handle_regexp_HARD_BREAK ignore
72
82
  alias start_accepting ignore
73
83
 
74
84
  end
75
-