rdoc 8.0.0 → 8.1.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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -3
  3. data/RI.md +75 -75
  4. data/exe/rdoc +2 -2
  5. data/lib/rdoc/code_object/alias.rb +71 -69
  6. data/lib/rdoc/code_object/any_method.rb +305 -303
  7. data/lib/rdoc/code_object/attr.rb +150 -148
  8. data/lib/rdoc/code_object/class_module.rb +798 -792
  9. data/lib/rdoc/code_object/constant.rb +175 -173
  10. data/lib/rdoc/code_object/context/section.rb +142 -138
  11. data/lib/rdoc/code_object/context.rb +926 -958
  12. data/lib/rdoc/code_object/extend.rb +7 -5
  13. data/lib/rdoc/code_object/include.rb +7 -5
  14. data/lib/rdoc/code_object/method_attr.rb +326 -319
  15. data/lib/rdoc/code_object/mixin.rb +97 -95
  16. data/lib/rdoc/code_object/normal_class.rb +77 -78
  17. data/lib/rdoc/code_object/normal_module.rb +61 -59
  18. data/lib/rdoc/code_object/require.rb +23 -39
  19. data/lib/rdoc/code_object/single_class.rb +21 -19
  20. data/lib/rdoc/code_object/top_level.rb +212 -219
  21. data/lib/rdoc/code_object.rb +305 -303
  22. data/lib/rdoc/comment.rb +275 -273
  23. data/lib/rdoc/cross_reference.rb +192 -190
  24. data/lib/rdoc/encoding.rb +105 -103
  25. data/lib/rdoc/erb_partial.rb +13 -11
  26. data/lib/rdoc/erbio.rb +29 -27
  27. data/lib/rdoc/generator/aliki.rb +161 -153
  28. data/lib/rdoc/generator/darkfish.rb +645 -635
  29. data/lib/rdoc/generator/json_index.rb +233 -229
  30. data/lib/rdoc/generator/markup.rb +164 -146
  31. data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
  32. data/lib/rdoc/generator/pot/po.rb +52 -51
  33. data/lib/rdoc/generator/pot/po_entry.rb +138 -132
  34. data/lib/rdoc/generator/pot.rb +85 -81
  35. data/lib/rdoc/generator/ri.rb +23 -19
  36. data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
  37. data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
  38. data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
  39. data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
  40. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
  41. data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
  42. data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
  43. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
  44. data/lib/rdoc/generator.rb +48 -46
  45. data/lib/rdoc/i18n/locale.rb +99 -95
  46. data/lib/rdoc/i18n/text.rb +109 -105
  47. data/lib/rdoc/i18n.rb +7 -5
  48. data/lib/rdoc/markdown/byte_runtime.rb +80 -0
  49. data/lib/rdoc/markdown.kpeg +15 -11
  50. data/lib/rdoc/markdown.rb +40 -47
  51. data/lib/rdoc/markup/block_quote.rb +12 -8
  52. data/lib/rdoc/markup/document.rb +127 -123
  53. data/lib/rdoc/markup/formatter.rb +219 -215
  54. data/lib/rdoc/markup/include.rb +33 -29
  55. data/lib/rdoc/markup/indented_paragraph.rb +37 -33
  56. data/lib/rdoc/markup/inline_parser.rb +281 -277
  57. data/lib/rdoc/markup/list.rb +80 -88
  58. data/lib/rdoc/markup/list_item.rb +73 -85
  59. data/lib/rdoc/markup/paragraph.rb +23 -19
  60. data/lib/rdoc/markup/parser.rb +501 -497
  61. data/lib/rdoc/markup/pre_process.rb +283 -279
  62. data/lib/rdoc/markup/raw.rb +2 -2
  63. data/lib/rdoc/markup/rule.rb +16 -12
  64. data/lib/rdoc/markup/to_ansi.rb +143 -139
  65. data/lib/rdoc/markup/to_bs.rb +72 -68
  66. data/lib/rdoc/markup/to_html.rb +594 -565
  67. data/lib/rdoc/markup/to_html_crossref.rb +234 -230
  68. data/lib/rdoc/markup/to_html_snippet.rb +232 -227
  69. data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
  70. data/lib/rdoc/markup/to_label.rb +63 -59
  71. data/lib/rdoc/markup/to_markdown.rb +212 -208
  72. data/lib/rdoc/markup/to_rdoc.rb +336 -332
  73. data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
  74. data/lib/rdoc/markup/to_test.rb +60 -56
  75. data/lib/rdoc/markup/to_tt_only.rb +84 -80
  76. data/lib/rdoc/markup/verbatim.rb +62 -58
  77. data/lib/rdoc/markup.rb +198 -196
  78. data/lib/rdoc/options.rb +1063 -1061
  79. data/lib/rdoc/parser/c.rb +1039 -1037
  80. data/lib/rdoc/parser/changelog.rb +319 -315
  81. data/lib/rdoc/parser/markdown.rb +17 -13
  82. data/lib/rdoc/parser/rbs.rb +239 -235
  83. data/lib/rdoc/parser/rd.rb +17 -13
  84. data/lib/rdoc/parser/ruby.rb +1245 -1124
  85. data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
  86. data/lib/rdoc/parser/simple.rb +31 -27
  87. data/lib/rdoc/parser/text.rb +12 -8
  88. data/lib/rdoc/parser.rb +228 -220
  89. data/lib/rdoc/rbs_helper.rb +1 -1
  90. data/lib/rdoc/rd/inline.rb +57 -53
  91. data/lib/rdoc/rd.rb +90 -88
  92. data/lib/rdoc/rdoc.rb +500 -491
  93. data/lib/rdoc/ri/driver.rb +1140 -1135
  94. data/lib/rdoc/ri/formatter.rb +7 -3
  95. data/lib/rdoc/ri/paths.rb +140 -136
  96. data/lib/rdoc/ri/servlet.rb +354 -350
  97. data/lib/rdoc/ri/store.rb +4 -2
  98. data/lib/rdoc/ri/task.rb +55 -51
  99. data/lib/rdoc/ri.rb +14 -12
  100. data/lib/rdoc/rubygems_hook.rb +183 -181
  101. data/lib/rdoc/server.rb +349 -347
  102. data/lib/rdoc/stats/normal.rb +46 -42
  103. data/lib/rdoc/stats/quiet.rb +39 -35
  104. data/lib/rdoc/stats/verbose.rb +35 -31
  105. data/lib/rdoc/stats.rb +365 -363
  106. data/lib/rdoc/store.rb +888 -902
  107. data/lib/rdoc/task.rb +260 -256
  108. data/lib/rdoc/text.rb +135 -133
  109. data/lib/rdoc/token_stream.rb +101 -93
  110. data/lib/rdoc/tom_doc.rb +203 -201
  111. data/lib/rdoc/version.rb +1 -1
  112. metadata +4 -5
  113. data/lib/rdoc/markdown/literals.kpeg +0 -21
  114. data/lib/rdoc/markdown/literals.rb +0 -454
@@ -1,261 +1,265 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # Subclass of the RDoc::Markup::ToHtml class that supports looking up method
4
- # names, classes, etc to create links. RDoc::CrossReference is used to
5
- # generate those links based on the current context.
2
+ module RDoc
3
+ class Markup
4
+ ##
5
+ # Subclass of the RDoc::Markup::ToHtml class that supports looking up method
6
+ # names, classes, etc to create links. RDoc::CrossReference is used to
7
+ # generate those links based on the current context.
6
8
 
7
- class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
9
+ class ToHtmlCrossref < Markup::ToHtml
8
10
 
9
- # :stopdoc:
10
- ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP
11
- CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP
12
- # :startdoc:
11
+ # :stopdoc:
12
+ ALL_CROSSREF_REGEXP = CrossReference::ALL_CROSSREF_REGEXP
13
+ CROSSREF_REGEXP = CrossReference::CROSSREF_REGEXP
14
+ # :startdoc:
13
15
 
14
- ##
15
- # RDoc::CodeObject for generating references
16
+ ##
17
+ # RDoc::CodeObject for generating references
16
18
 
17
- attr_accessor :context
19
+ attr_accessor :context
18
20
 
19
- ##
20
- # Should we show '#' characters on method references?
21
+ ##
22
+ # Should we show '#' characters on method references?
21
23
 
22
- attr_accessor :show_hash
24
+ attr_accessor :show_hash
23
25
 
24
- ##
25
- # Creates a new crossref resolver that generates links relative to +context+
26
- # which lives at +from_path+ in the generated files. '#' characters on
27
- # references are removed unless +show_hash+ is true. Only method names
28
- # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true.
26
+ ##
27
+ # Creates a new crossref resolver that generates links relative to +context+
28
+ # which lives at +from_path+ in the generated files. '#' characters on
29
+ # references are removed unless +show_hash+ is true. Only method names
30
+ # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true.
29
31
 
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
- raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
32
+ def initialize(from_path, context, pipe: false, output_decoration: true,
33
+ hyperlink_all: false, show_hash: false,
34
+ autolink_excluded_words: [], warn_missing_rdoc_ref: true)
35
+ raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
34
36
 
35
- super(pipe: pipe, output_decoration: output_decoration)
37
+ super(pipe: pipe, output_decoration: output_decoration)
36
38
 
37
- @context = context
38
- @from_path = from_path
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
39
+ @context = context
40
+ @from_path = from_path
41
+ @hyperlink_all = hyperlink_all
42
+ @show_hash = show_hash
43
+ @autolink_excluded_words = autolink_excluded_words
44
+ @warn_missing_rdoc_ref = warn_missing_rdoc_ref
43
45
 
44
- @cross_reference = RDoc::CrossReference.new @context
45
- end
46
-
47
- # :nodoc:
48
- def init_link_notation_regexp_handlings
49
- add_regexp_handling_RDOCLINK
50
-
51
- # The crossref must be linked before tidylink because Klass.method[:sym]
52
- # will be processed as a tidylink first and will be broken.
53
- crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
54
- @markup.add_regexp_handling crossref_re, :CROSSREF
55
- end
56
-
57
- ##
58
- # Creates a link to the reference +name+ if the name exists. If +text+ is
59
- # given it is used as the link text, otherwise +name+ is used.
60
- # Returns +nil+ if the link target could not be resolved.
61
-
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
65
-
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
71
- code = false
72
- else
73
- text ||= convert_string(display)
74
- end
75
-
76
- link(name, text, code, rdoc_ref: rdoc_ref)
77
- end
78
-
79
- ##
80
- # We're invoked when any text matches the CROSSREF pattern. If we find the
81
- # corresponding reference, generate a link. If the name we're looking for
82
- # contains no punctuation, we look for it up the module/class chain. For
83
- # example, ToHtml is found, even without the <tt>RDoc::Markup::</tt> prefix,
84
- # because we look for it in module Markup first.
85
-
86
- def handle_regexp_CROSSREF(name)
87
- return convert_string(name) if in_tidylink_label?
88
- return name if @autolink_excluded_words&.include?(name)
89
-
90
- return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails
91
-
92
- unless @hyperlink_all then
93
- # This ensures that words entirely consisting of lowercase letters will
94
- # not have cross-references generated (to suppress lots of erroneous
95
- # cross-references to "new" in text, for instance)
96
- return name if name =~ /\A[a-z]*\z/
97
- end
98
- cross_reference(name, rdoc_ref: false) || convert_string(name)
99
- end
100
-
101
- ##
102
- # Handles <tt>rdoc-ref:</tt> scheme links and allows RDoc::Markup::ToHtml to
103
- # handle other schemes.
104
-
105
- def handle_regexp_HYPERLINK(url)
106
- return convert_string(url) if in_tidylink_label?
107
-
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
115
- end
116
-
117
- ##
118
- # +target+ is an rdoc-schemed link that will be converted into a hyperlink.
119
- # For the rdoc-ref scheme the cross-reference will be looked up and the
120
- # given name will be used.
121
- #
122
- # All other contents are handled by
123
- # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]
124
-
125
- def handle_regexp_RDOCLINK(url)
126
- case url
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)
46
+ @cross_reference = CrossReference.new @context
133
47
  end
134
- else
135
- super
136
- end
137
- end
138
48
 
139
- ##
140
- # Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
141
- # RDoc::Markup::ToHtml to handle other schemes.
49
+ # :nodoc:
50
+ def init_link_notation_regexp_handlings
51
+ add_regexp_handling_RDOCLINK
142
52
 
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
150
- end
151
-
152
- ##
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.
53
+ # The crossref must be linked before tidylink because Klass.method[:sym]
54
+ # will be processed as a tidylink first and will be broken.
55
+ crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
56
+ @markup.add_regexp_handling crossref_re, :CROSSREF
57
+ end
156
58
 
157
- def link(name, html_string, code = true, rdoc_ref: false)
158
- if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
159
- name = $1
160
- label = $'
161
- end
59
+ ##
60
+ # Creates a link to the reference +name+ if the name exists. If +text+ is
61
+ # given it is used as the link text, otherwise +name+ is used.
62
+ # Returns +nil+ if the link target could not be resolved.
63
+
64
+ def cross_reference(name, text = nil, code = true, rdoc_ref: false)
65
+ # Strip '#' for link display text (e.g. #method shows as "method" in links)
66
+ display = !@show_hash && name.start_with?('#') ? name[1..] : name
67
+
68
+ if !display.end_with?('+@', '-@') && match = display.match(/(.*[^#:])?@(.*)/)
69
+ context_name = match[1]
70
+ label = convert_string(Text.decode_legacy_label(match[2]))
71
+ text ||= "#{label} at <code>#{convert_string(context_name)}</code>" if context_name
72
+ text ||= label
73
+ code = false
74
+ else
75
+ text ||= convert_string(display)
76
+ end
77
+
78
+ link(name, text, code, rdoc_ref: rdoc_ref)
79
+ end
162
80
 
163
- ref = @cross_reference.resolve name if name
81
+ ##
82
+ # We're invoked when any text matches the CROSSREF pattern. If we find the
83
+ # corresponding reference, generate a link. If the name we're looking for
84
+ # contains no punctuation, we look for it up the module/class chain. For
85
+ # example, ToHtml is found, even without the <tt>RDoc::Markup::</tt> prefix,
86
+ # because we look for it in module Markup first.
87
+
88
+ def handle_regexp_CROSSREF(name)
89
+ return convert_string(name) if in_tidylink_label?
90
+ return convert_string(name) if @autolink_excluded_words&.include?(name)
91
+
92
+ return convert_string(name) if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails
93
+
94
+ unless @hyperlink_all
95
+ # This ensures that words entirely consisting of lowercase letters will
96
+ # not have cross-references generated (to suppress lots of erroneous
97
+ # cross-references to "new" in text, for instance)
98
+ return name if name =~ /\A[a-z]*\z/
99
+ end
100
+ cross_reference(name, rdoc_ref: false) || convert_string(name)
101
+ end
164
102
 
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
103
+ ##
104
+ # Handles <tt>rdoc-ref:</tt> scheme links and allows RDoc::Markup::ToHtml to
105
+ # handle other schemes.
170
106
 
171
- if ref
172
- path = ref.as_href(@from_path)
107
+ def handle_regexp_HYPERLINK(url)
108
+ return convert_string(url) if in_tidylink_label?
173
109
 
174
- if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref)
175
- html_string = "<code>#{html_string}</code>"
110
+ case url
111
+ when /\Ardoc-ref:/
112
+ ref = $'
113
+ cross_reference(ref, rdoc_ref: true) || convert_string(ref)
114
+ else
115
+ super
116
+ end
176
117
  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}`"
118
+
119
+ ##
120
+ # +target+ is an rdoc-schemed link that will be converted into a hyperlink.
121
+ # For the rdoc-ref scheme the cross-reference will be looked up and the
122
+ # given name will be used.
123
+ #
124
+ # All other contents are handled by
125
+ # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]
126
+
127
+ def handle_regexp_RDOCLINK(url)
128
+ case url
129
+ when /\Ardoc-ref:/
130
+ if in_tidylink_label?
131
+ convert_string(url)
132
+ else
133
+ ref = $'
134
+ cross_reference(ref, rdoc_ref: true) || convert_string(ref)
135
+ end
136
+ else
137
+ super
138
+ end
180
139
  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
187
140
 
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
215
- else
216
- path << "##{formatted_label}"
141
+ ##
142
+ # Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
143
+ # RDoc::Markup::ToHtml to handle other schemes.
144
+
145
+ def gen_url(url, text)
146
+ if url =~ /\Ardoc-ref:/
147
+ name = $'
148
+ cross_reference(name, text, name == text, rdoc_ref: true) || text
149
+ else
150
+ super
151
+ end
217
152
  end
218
- end
219
153
 
220
- "<a href=\"#{path}\">#{html_string}</a>"
221
- end
154
+ ##
155
+ # Creates an HTML link to +name+ with the given +html_string+.
156
+ # +html_string+ should be already escaped and may contain HTML tags.
157
+ # Returns the link HTML string, or +nil+ if the reference could not be resolved.
158
+
159
+ def link(name, html_string, code = true, rdoc_ref: false)
160
+ if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
161
+ name = $1
162
+ label = $'
163
+ end
164
+
165
+ ref = @cross_reference.resolve name if name
166
+
167
+ # Non-text source files (C, Ruby, etc.) don't get HTML pages generated,
168
+ # so don't auto-link to them. Explicit rdoc-ref: links are still allowed.
169
+ if !rdoc_ref && TopLevel === ref && !ref.text?
170
+ return
171
+ end
172
+
173
+ if ref
174
+ path = ref.as_href(@from_path)
175
+
176
+ if code and CodeObject === ref and !(TopLevel === ref)
177
+ html_string = "<code>#{html_string}</code>"
178
+ end
179
+ elsif name
180
+ if rdoc_ref && @warn_missing_rdoc_ref
181
+ puts "#{@from_path}: `rdoc-ref:#{name}` can't be resolved for `#{html_string}`"
182
+ end
183
+ return
184
+ else
185
+ # A bare label reference like @foo still produces a valid anchor link
186
+ return unless label
187
+ path = +""
188
+ end
189
+
190
+ if label
191
+ # Decode legacy labels (e.g., "What-27s+Here" -> "What's Here")
192
+ # then convert to GitHub-style anchor format
193
+ decoded_label = Text.decode_legacy_label(label)
194
+ formatted_label = Text.to_anchor(decoded_label)
195
+
196
+ # Case 1: Path already has an anchor (e.g., method link)
197
+ # Input: C1#method@label -> path="C1.html#method-i-m"
198
+ # Output: C1.html#method-i-m-label
199
+ if path =~ /#/
200
+ path << "-#{formatted_label}"
201
+
202
+ # Case 2: Label matches a section title
203
+ # Input: C1@Section -> path="C1.html", section "Section" exists
204
+ # Output: C1.html#section (uses section.aref for GitHub-style)
205
+ elsif (section = ref&.sections&.find { |s| decoded_label == s.title })
206
+ path << "##{section.aref}"
207
+
208
+ # Case 3: Ref has an aref (class/module context)
209
+ # Input: C1@heading -> path="C1.html", ref=C1 class
210
+ # Output: C1.html#class-c1-heading
211
+ elsif ref.respond_to?(:aref)
212
+ path << "##{ref.aref}-#{formatted_label}"
213
+
214
+ # Case 4: No context, just the label (e.g., TopLevel/file)
215
+ # Input: README@section -> path="README_md.html"
216
+ # Output: README_md.html#section
217
+ else
218
+ path << "##{formatted_label}"
219
+ end
220
+ end
221
+
222
+ "<a href=\"#{path}\">#{html_string}</a>"
223
+ end
222
224
 
223
- def handle_TT(code)
224
- emit_inline(tt_cross_reference(code) || "<code>#{convert_string(code)}</code>")
225
- end
225
+ def handle_TT(code)
226
+ emit_inline(tt_cross_reference(code) || "<code>#{convert_string(code)}</code>")
227
+ end
226
228
 
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
229
+ # Applies additional special handling on top of the one defined in ToHtml.
230
+ # When a tidy link is <tt>{Foo}[rdoc-ref:Foo]</tt>, the label part is surrounded by <tt><code></code></tt>.
231
+ # TODO: reconsider this workaround.
232
+ def apply_tidylink_label_special_handling(label, url)
233
+ if url == "rdoc-ref:#{label}" && cross_reference(label)&.include?('<code>')
234
+ "<code>#{convert_string(label)}</code>"
235
+ else
236
+ super
237
+ end
238
+ end
237
239
 
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>')
240
+ # Handles cross-reference and suppressed-crossref inside tt tag.
241
+ # Returns nil if code is not an existing cross-reference nor a suppressed-crossref.
242
+ def tt_cross_reference(code)
243
+ return if in_tidylink_label?
244
+
245
+ crossref_regexp = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
246
+ # REGEXP sometimes matches a string that starts with a backslash but is not a
247
+ # suppressed cross-reference (for example, `\+`), so the backslash-removed
248
+ # part needs to be checked against crossref_regexp.
249
+ match = crossref_regexp.match(code.delete_prefix('\\'))
250
+ return unless match && match.begin(1).zero?
251
+ return unless match.post_match.match?(/\A[[:punct:]\s]*\z/)
252
+
253
+ # cross_reference(file_page) may return a link without code tag.
254
+ # We need to check it because this method shouldn't return an html text without code tag.
255
+ if code.start_with?('\\')
256
+ # Remove leading backslash if crossref exists
257
+ "<code>#{convert_string(code[1..])}</code>" if cross_reference(code[1..])&.include?('<code>')
258
+ else
259
+ html = cross_reference(code)
260
+ html if html&.include?('<code>')
261
+ end
262
+ end
259
263
  end
260
264
  end
261
265
  end