Skip to content

Commit 58b0238

Browse files
st0012claude
andcommitted
Fix backslash in RDoc monofont causing unwanted linking
When text in <tt> tags contains backslashes (e.g., <tt>.bar.hello(\)</tt>), RDoc was incorrectly creating cross-reference links because the backslash matched the escaped character pattern in CROSSREF_REGEXP. This fix adds a check to prevent cross-referencing when the match is solely due to escaped characters that don't represent valid method/class references. Fixes #1390 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent e0e24f2 commit 58b0238

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

lib/rdoc/markup/to_html_crossref.rb

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,18 @@ def handle_regexp_CROSSREF(target)
9494
return name if name =~ /\A[a-z]*\z/
9595
end
9696

97+
# Check if the match is solely due to an escaped character pattern.
98+
# If the text contains backslash escapes but doesn't match any
99+
# valid cross-reference pattern (class, method, etc.), return as-is
100+
if name =~ /\\/ &&
101+
name !~ /\A#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}\z/o &&
102+
name !~ /\A\\?#{CLASS_REGEXP_STR}\z/o &&
103+
name !~ /\A\\?\##{METHOD_REGEXP_STR}\z/o &&
104+
name !~ /\A::#{METHOD_REGEXP_STR}\z/o &&
105+
name !~ /\A\.\.\/|[-\/\w]+[_\/.][-\w\/.]+\z/ # filepath pattern
106+
return name
107+
end
108+
97109
cross_reference name, rdoc_ref: false
98110
end
99111

@@ -198,13 +210,29 @@ def convert_flow(flow)
198210
String === (str = flow[i]) and
199211
RDoc::Markup::AttrChanger === flow[i+1] and
200212
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
213+
(@options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP).match?(str)
203214
then
204-
text = yield text, res if defined?(yield)
205-
res << text
206-
i += 2
207-
next
215+
# Check if the match is solely due to an escaped character pattern.
216+
# If the text contains backslash escapes but doesn't match any
217+
# valid cross-reference pattern (class, method, etc.), skip cross-referencing
218+
if str =~ /\\/ &&
219+
str !~ /\A#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}\z/o &&
220+
str !~ /\A\\?#{CLASS_REGEXP_STR}\z/o &&
221+
str !~ /\A\\?\##{METHOD_REGEXP_STR}\z/o &&
222+
str !~ /\A::#{METHOD_REGEXP_STR}\z/o &&
223+
str !~ /\A\.\.\/|[-\/\w]+[_\/.][-\w\/.]+\z/ # filepath pattern
224+
# Don't cross-reference, just output the text wrapped in code tags
225+
text = "<code>#{CGI.escapeHTML(str)}</code>"
226+
text = yield text, res if defined?(yield)
227+
res << text
228+
i += 2
229+
next
230+
elsif (text = cross_reference str) != str
231+
text = yield text, res if defined?(yield)
232+
res << text
233+
i += 2
234+
next
235+
end
208236
end
209237
off_tags res, item
210238
on_tags res, item

test/rdoc/rdoc_markup_to_html_crossref_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ def test_convert_CROSSREF
3333
assert_equal para("<code># :stopdoc:</code>:"), result
3434
end
3535

36+
def test_convert_CROSSREF_backslash_escapes_in_monofont
37+
# Test that backslash escapes in monofont don't create unwanted links
38+
result = @to.convert '<tt>.bar.hello(\)</tt>'
39+
assert_equal para("<code>.bar.hello(\\)</code>"), result
40+
41+
result = @to.convert '<tt>.bar.hello(\\\\)</tt>'
42+
assert_equal para("<code>.bar.hello(\\)</code>"), result
43+
44+
# Regular method references should still work
45+
result = @to.convert '<tt>C1#m</tt>'
46+
assert_equal para("<a href=\"C1.html#method-i-m\"><code>C1#m</code></a>"), result
47+
48+
result = @to.convert '<tt>C1.m</tt>'
49+
assert_equal para("<a href=\"C1.html#method-c-m\"><code>C1.m</code></a>"), result
50+
end
51+
3652
def test_convert_CROSSREF_ignored_excluded_words
3753
@options.autolink_excluded_words = ['C1']
3854

0 commit comments

Comments
 (0)