Skip to content
Merged
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
70 changes: 50 additions & 20 deletions lib/rdoc/markup/to_html_crossref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,43 +184,73 @@ 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
end

res.join('')
end

private

##
# Detects <tt>...</tt> 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
18 changes: 18 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,24 @@ def test_convert_CROSSREF
assert_equal para("<code># :stopdoc:</code>:"), 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 '<tt>C1</tt>'
assert_equal para('<a href="C1.html"><code>C1</code></a>'), result

result = formatter.convert '<tt>.bar.hello()</tt>'
assert_equal para('<code>.bar.hello()</code>'), result

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

result = formatter.convert '<tt>.bar.hello(\\\\)</tt>'
assert_equal para('<code>.bar.hello(\\)</code>'), result
end

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

Expand Down
Loading