diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index c5e4f62c97..dab486aaae 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -184,38 +184,35 @@ def link(name, text, code = true, rdoc_ref: false)
end
end
- def convert_flow(flow)
+ def convert_flow(flow_items, &block)
res = []
i = 0
- while i < flow.size
- item = flow[i]
- i += 1
+ while i < flow_items.size
+ item = flow_items[i]
+
case item
- when RDoc::Markup::AttrChanger then
- # Make "+Class#method+" a cross reference
- if tt_tag?(item.turn_on) and
- 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
- then
- text = yield text, res if defined?(yield)
+ when RDoc::Markup::AttrChanger
+ if (text = convert_tt_crossref(flow_items, i))
+ text = block.call(text, res) if block
res << text
- i += 2
+ i += 3
next
end
+
off_tags res, item
- on_tags res, item
- when String then
+ on_tags res, item
+ i += 1
+ when String
text = convert_string(item)
- text = yield text, res if defined?(yield)
+ text = block.call(text, res) if block
res << text
- when RDoc::Markup::RegexpHandling then
+ i += 1
+ when RDoc::Markup::RegexpHandling
text = convert_regexp_handling(item)
- text = yield text, res if defined?(yield)
+ text = block.call(text, res) if block
res << text
+ i += 1
else
raise "Unknown flow element: #{item.inspect}"
end
@@ -223,4 +220,37 @@ def convert_flow(flow)
res.join('')
end
+
+ private
+
+ ##
+ # Detects ... spans that contain a single cross-reference candidate.
+ # When the candidate occupies the whole span (aside from trailing
+ # punctuation), the tt markup is replaced by the resolved cross-reference.
+
+ def convert_tt_crossref(flow_items, index)
+ opener = flow_items[index]
+ return unless tt_tag?(opener.turn_on)
+
+ string = flow_items[index + 1]
+ closer = flow_items[index + 2]
+
+ return unless String === string
+ return unless RDoc::Markup::AttrChanger === closer
+ return unless tt_tag?(closer.turn_off, true)
+
+ crossref_regexp = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
+ match = crossref_regexp.match(string)
+ return unless match
+ return unless match.begin(1).zero?
+
+ trailing = match.post_match
+ # Only convert when the remainder is punctuation/whitespace so other tt text stays literal.
+ return unless trailing.match?(/\A[[:punct:]\s]*\z/)
+
+ text = cross_reference(string)
+ return if text == string
+
+ text
+ end
end
diff --git a/test/rdoc/rdoc_markup_to_html_crossref_test.rb b/test/rdoc/rdoc_markup_to_html_crossref_test.rb
index a52c7f1506..e6836ea4c2 100644
--- a/test/rdoc/rdoc_markup_to_html_crossref_test.rb
+++ b/test/rdoc/rdoc_markup_to_html_crossref_test.rb
@@ -33,6 +33,24 @@ def test_convert_CROSSREF
assert_equal para("# :stopdoc:
:"), result
end
+ def test_convert_CROSSREF_backslash_in_tt
+ @options.hyperlink_all = false
+
+ formatter = RDoc::Markup::ToHtmlCrossref.new(@options, 'C9.html', @c9_b)
+
+ result = formatter.convert 'C1'
+ assert_equal para('C1
'), result
+
+ result = formatter.convert '.bar.hello()'
+ assert_equal para('.bar.hello()
'), result
+
+ result = formatter.convert '.bar.hello(\)'
+ assert_equal para('.bar.hello(\)
'), result
+
+ result = formatter.convert '.bar.hello(\\\\)'
+ assert_equal para('.bar.hello(\\)
'), result
+ end
+
def test_convert_CROSSREF_ignored_excluded_words
@options.autolink_excluded_words = ['C1']