Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions lib/rdoc/markup/to_html_crossref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ def handle_regexp_CROSSREF(target)
return name if name =~ /\A[a-z]*\z/
end

# Check if the match is solely due to an escaped character pattern.
# If the text contains backslash escapes but doesn't match any
# valid cross-reference pattern (class, method, etc.), return as-is
if name =~ /\\/ &&
name !~ /\A#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}\z/o &&
name !~ /\A\\?#{CLASS_REGEXP_STR}\z/o &&
name !~ /\A\\?\##{METHOD_REGEXP_STR}\z/o &&
name !~ /\A::#{METHOD_REGEXP_STR}\z/o &&
name !~ /\A\.\.\/|[-\/\w]+[_\/.][-\w\/.]+\z/ # filepath pattern
return name
end

cross_reference name, rdoc_ref: false
end

Expand Down Expand Up @@ -198,13 +210,29 @@ def convert_flow(flow)
String === (str = flow[i]) and
RDoc::Markup::AttrChanger === flow[i+1] and
tt_tag?(flow[i+1].turn_off, true) and
(@options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP).match?(str) and
(text = cross_reference str) != str
(@options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP).match?(str)
then
text = yield text, res if defined?(yield)
res << text
i += 2
next
# Check if the match is solely due to an escaped character pattern.
# If the text contains backslash escapes but doesn't match any
# valid cross-reference pattern (class, method, etc.), skip cross-referencing
if str =~ /\\/ &&
str !~ /\A#{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}\z/o &&
str !~ /\A\\?#{CLASS_REGEXP_STR}\z/o &&
str !~ /\A\\?\##{METHOD_REGEXP_STR}\z/o &&
str !~ /\A::#{METHOD_REGEXP_STR}\z/o &&
str !~ /\A\.\.\/|[-\/\w]+[_\/.][-\w\/.]+\z/ # filepath pattern
# Don't cross-reference, just output the text wrapped in code tags
text = "<code>#{CGI.escapeHTML(str)}</code>"
text = yield text, res if defined?(yield)
res << text
i += 2
next
elsif (text = cross_reference str) != str
text = yield text, res if defined?(yield)
res << text
i += 2
next
end
end
off_tags res, item
on_tags res, item
Expand Down
16 changes: 16 additions & 0 deletions test/rdoc/rdoc_markup_to_html_crossref_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ def test_convert_CROSSREF
assert_equal para("<code># :stopdoc:</code>:"), result
end

def test_convert_CROSSREF_backslash_escapes_in_monofont
# Test that backslash escapes in monofont don't create unwanted links
result = @to.convert '<tt>.bar.hello(\)</tt>'
assert_equal para("<code>.bar.hello(\\)</code>"), result

result = @to.convert '<tt>.bar.hello(\\\\)</tt>'
assert_equal para("<code>.bar.hello(\\)</code>"), result

# Regular method references should still work
result = @to.convert '<tt>C1#m</tt>'
assert_equal para("<a href=\"C1.html#method-i-m\"><code>C1#m</code></a>"), result

result = @to.convert '<tt>C1.m</tt>'
assert_equal para("<a href=\"C1.html#method-c-m\"><code>C1.m</code></a>"), result
end

def test_convert_CROSSREF_ignored_excluded_words
@options.autolink_excluded_words = ['C1']

Expand Down
Loading