@@ -57,26 +57,23 @@ def init_link_notation_regexp_handlings
5757 ##
5858 # Creates a link to the reference +name+ if the name exists. If +text+ is
5959 # given it is used as the link text, otherwise +name+ is used.
60+ # Returns +nil+ if the link target could not be resolved.
6061
6162 def cross_reference ( name , text = nil , code = true , rdoc_ref : false )
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
65-
6663 # Strip '#' for link display text (e.g. #method shows as "method" in links)
6764 display = !@show_hash && name . start_with? ( '#' ) ? name [ 1 ..] : name
6865
6966 if !display . end_with? ( '+@' , '-@' ) && match = display . match ( /(.*[^#:])?@(.*)/ )
7067 context_name = match [ 1 ]
71- label = RDoc ::Text . decode_legacy_label ( match [ 2 ] )
72- text ||= "#{ label } at <code>#{ context_name } </code>" if context_name
68+ label = convert_string ( RDoc ::Text . decode_legacy_label ( match [ 2 ] ) )
69+ text ||= "#{ label } at <code>#{ convert_string ( context_name ) } </code>" if context_name
7370 text ||= label
7471 code = false
7572 else
76- text ||= display
73+ text ||= convert_string ( display )
7774 end
7875
79- link ( name , text , code , rdoc_ref : rdoc_ref ) || fallback
76+ link ( name , text , code , rdoc_ref : rdoc_ref )
8077 end
8178
8279 ##
@@ -98,8 +95,7 @@ def handle_regexp_CROSSREF(name)
9895 # cross-references to "new" in text, for instance)
9996 return name if name =~ /\A [a-z]*\z /
10097 end
101-
102- cross_reference name , rdoc_ref : false
98+ cross_reference ( name , rdoc_ref : false ) || convert_string ( name )
10399 end
104100
105101 ##
@@ -111,7 +107,8 @@ def handle_regexp_HYPERLINK(url)
111107
112108 case url
113109 when /\A rdoc-ref:/
114- cross_reference $', rdoc_ref : true
110+ ref = $'
111+ cross_reference ( ref , rdoc_ref : true ) || convert_string ( ref )
115112 else
116113 super
117114 end
@@ -131,7 +128,8 @@ def handle_regexp_RDOCLINK(url)
131128 if in_tidylink_label?
132129 convert_string ( url )
133130 else
134- cross_reference $', rdoc_ref : true
131+ ref = $'
132+ cross_reference ( ref , rdoc_ref : true ) || convert_string ( ref )
135133 end
136134 else
137135 super
@@ -145,46 +143,46 @@ def handle_regexp_RDOCLINK(url)
145143 def gen_url ( url , text )
146144 if url =~ /\A rdoc-ref:/
147145 name = $'
148- cross_reference name , text , name == text , rdoc_ref : true
146+ cross_reference ( name , text , name == text , rdoc_ref : true ) || text
149147 else
150148 super
151149 end
152150 end
153151
154152 ##
155- # 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.
156155 # Returns the link HTML string, or +nil+ if the reference could not be resolved.
157156
158- def link ( name , text , code = true , rdoc_ref : false )
157+ def link ( name , html_string , code = true , rdoc_ref : false )
159158 if !( name . end_with? ( '+@' , '-@' ) ) and name =~ /(.*[^#:])?@/
160159 name = $1
161160 label = $'
162161 end
163162
164- ref = @cross_reference . resolve name , text if name
163+ ref = @cross_reference . resolve name if name
165164
166165 # Non-text source files (C, Ruby, etc.) don't get HTML pages generated,
167166 # so don't auto-link to them. Explicit rdoc-ref: links are still allowed.
168167 if !rdoc_ref && RDoc ::TopLevel === ref && !ref . text?
169168 return
170169 end
171170
172- case ref
173- when String
171+ if ref
172+ path = ref . as_href ( @from_path )
173+
174+ if code and RDoc ::CodeObject === ref and !( RDoc ::TopLevel === ref )
175+ html_string = "<code>#{ html_string } </code>"
176+ end
177+ elsif name
174178 if rdoc_ref && @warn_missing_rdoc_ref
175- puts "#{ @from_path } : `rdoc-ref:#{ name } ` can't be resolved for `#{ text } `"
179+ puts "#{ @from_path } : `rdoc-ref:#{ name } ` can't be resolved for `#{ html_string } `"
176180 end
177181 return
178- when nil
182+ else
179183 # A bare label reference like @foo still produces a valid anchor link
180184 return unless label
181185 path = +""
182- else
183- path = ref . as_href ( @from_path )
184-
185- if code and RDoc ::CodeObject === ref and !( RDoc ::TopLevel === ref )
186- text = "<code>#{ CGI . escapeHTML text } </code>"
187- end
188186 end
189187
190188 if label
@@ -219,33 +217,45 @@ def link(name, text, code = true, rdoc_ref: false)
219217 end
220218 end
221219
222- "<a href=\" #{ path } \" >#{ text } </a>"
220+ "<a href=\" #{ path } \" >#{ html_string } </a>"
223221 end
224222
225223 def handle_TT ( code )
226- emit_inline ( tt_cross_reference ( code ) || "<code>#{ CGI . escapeHTML code } </code>" )
224+ emit_inline ( tt_cross_reference ( code ) || "<code>#{ convert_string ( code ) } </code>" )
227225 end
228226
229227 # Applies additional special handling on top of the one defined in ToHtml.
230228 # When a tidy link is <tt>{Foo}[rdoc-ref:Foo]</tt>, the label part is surrounded by <tt><code></code></tt>.
231229 # TODO: reconsider this workaround.
232230 def apply_tidylink_label_special_handling ( label , url )
233- if url == "rdoc-ref:#{ label } " && cross_reference ( label ) . include? ( '<code>' )
231+ if url == "rdoc-ref:#{ label } " && cross_reference ( label ) & .include? ( '<code>' )
234232 "<code>#{ convert_string ( label ) } </code>"
235233 else
236234 super
237235 end
238236 end
239237
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.
240240 def tt_cross_reference ( code )
241241 return if in_tidylink_label?
242242
243243 crossref_regexp = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
244- match = crossref_regexp . match ( code )
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 ( '\\' ) )
245248 return unless match && match . begin ( 1 ) . zero?
246249 return unless match . post_match . match? ( /\A [[:punct:]\s ]*\z / )
247250
248- ref = cross_reference ( code )
249- ref if ref != code
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
250260 end
251261end
0 commit comments