@@ -59,21 +59,24 @@ def init_link_notation_regexp_handlings
5959 # given it is used as the link text, otherwise +name+ is used.
6060
6161 def cross_reference ( name , text = nil , code = true , rdoc_ref : false )
62- lookup = name
62+ # What to show when the reference doesn't resolve to a link:
63+ # caller-provided text if any, otherwise the original name (preserving '#').
64+ fallback = text || name
6365
64- name = name [ 1 ..-1 ] unless @show_hash if name [ 0 , 1 ] == '#'
66+ # Strip '#' for link display text (e.g. #method shows as "method" in links)
67+ display = !@show_hash && name . start_with? ( '#' ) ? name [ 1 ..] : name
6568
66- if !name . end_with? ( '+@' , '-@' ) && match = name . match ( /(.*[^#:])?@(.*)/ )
69+ if !display . end_with? ( '+@' , '-@' ) && match = display . match ( /(.*[^#:])?@(.*)/ )
6770 context_name = match [ 1 ]
6871 label = RDoc ::Text . decode_legacy_label ( match [ 2 ] )
6972 text ||= "#{ label } at <code>#{ context_name } </code>" if context_name
7073 text ||= label
7174 code = false
7275 else
73- text ||= name
76+ text ||= display
7477 end
7578
76- link lookup , text , code , rdoc_ref : rdoc_ref
79+ link ( name , text , code , rdoc_ref : rdoc_ref ) || fallback
7780 end
7881
7982 ##
@@ -150,6 +153,7 @@ def gen_url(url, text)
150153
151154 ##
152155 # Creates an HTML link to +name+ with the given +text+.
156+ # Returns the link HTML string, or +nil+ if the reference could not be resolved.
153157
154158 def link ( name , text , code = true , rdoc_ref : false )
155159 if !( name . end_with? ( '+@' , '-@' ) ) and name =~ /(.*[^#:])?@/
@@ -162,56 +166,60 @@ def link(name, text, code = true, rdoc_ref: false)
162166 # Non-text source files (C, Ruby, etc.) don't get HTML pages generated,
163167 # so don't auto-link to them. Explicit rdoc-ref: links are still allowed.
164168 if !rdoc_ref && RDoc ::TopLevel === ref && !ref . text?
165- return text
169+ return
166170 end
167171
168172 case ref
169- when String then
173+ when String
170174 if rdoc_ref && @warn_missing_rdoc_ref
171175 puts "#{ @from_path } : `rdoc-ref:#{ name } ` can't be resolved for `#{ text } `"
172176 end
173- ref
177+ return
178+ when nil
179+ # A bare label reference like @foo still produces a valid anchor link
180+ return unless label
181+ path = +""
174182 else
175- path = ref ? ref . as_href ( @from_path ) : + ""
183+ path = ref . as_href ( @from_path )
176184
177185 if code and RDoc ::CodeObject === ref and !( RDoc ::TopLevel === ref )
178186 text = "<code>#{ CGI . escapeHTML text } </code>"
179187 end
188+ end
180189
181- if label
182- # Decode legacy labels (e.g., "What-27s+Here" -> "What's Here")
183- # then convert to GitHub-style anchor format
184- decoded_label = RDoc ::Text . decode_legacy_label ( label )
185- formatted_label = RDoc ::Text . to_anchor ( decoded_label )
186-
187- # Case 1: Path already has an anchor (e.g., method link)
188- # Input: C1#method@label -> path="C1.html#method-i-m"
189- # Output: C1.html#method-i-m-label
190- if path =~ /#/
191- path << "-#{ formatted_label } "
192-
193- # Case 2: Label matches a section title
194- # Input: C1@Section -> path="C1.html", section "Section" exists
195- # Output: C1.html#section (uses section.aref for GitHub-style)
196- elsif ( section = ref &.sections &.find { |s | decoded_label == s . title } )
197- path << "##{ section . aref } "
198-
199- # Case 3: Ref has an aref (class/module context)
200- # Input: C1@heading -> path="C1.html", ref=C1 class
201- # Output: C1.html#class-c1-heading
202- elsif ref . respond_to? ( :aref )
203- path << "##{ ref . aref } -#{ formatted_label } "
204-
205- # Case 4: No context, just the label (e.g., TopLevel/file)
206- # Input: README@section -> path="README_md.html"
207- # Output: README_md.html#section
208- else
209- path << "##{ formatted_label } "
210- end
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 = RDoc ::Text . decode_legacy_label ( label )
194+ formatted_label = RDoc ::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 } "
211219 end
212-
213- "<a href=\" #{ path } \" >#{ text } </a>"
214220 end
221+
222+ "<a href=\" #{ path } \" >#{ text } </a>"
215223 end
216224
217225 def handle_TT ( code )
0 commit comments