diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb index c5e4f62c97..c0bfb3eb70 100644 --- a/lib/rdoc/markup/to_html_crossref.rb +++ b/lib/rdoc/markup/to_html_crossref.rb @@ -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 @@ -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 = "#{CGI.escapeHTML(str)}" + 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 diff --git a/test/rdoc/rdoc_markup_to_html_crossref_test.rb b/test/rdoc/rdoc_markup_to_html_crossref_test.rb index a52c7f1506..3404bd9256 100644 --- a/test/rdoc/rdoc_markup_to_html_crossref_test.rb +++ b/test/rdoc/rdoc_markup_to_html_crossref_test.rb @@ -33,6 +33,22 @@ def test_convert_CROSSREF assert_equal para("# :stopdoc::"), result end + def test_convert_CROSSREF_backslash_escapes_in_monofont + # Test that backslash escapes in monofont don't create unwanted links + result = @to.convert '.bar.hello(\)' + assert_equal para(".bar.hello(\\)"), result + + result = @to.convert '.bar.hello(\\\\)' + assert_equal para(".bar.hello(\\)"), result + + # Regular method references should still work + result = @to.convert 'C1#m' + assert_equal para("C1#m"), result + + result = @to.convert 'C1.m' + assert_equal para("C1.m"), result + end + def test_convert_CROSSREF_ignored_excluded_words @options.autolink_excluded_words = ['C1']