@@ -158,19 +158,16 @@ def handle_regexp_RDOCLINK(target)
158158 def handle_regexp_TIDYLINK ( target )
159159 text = target . text
160160
161- return text unless
162- text =~ /^\{ (.*)\} \[ (.*?)\] $/ or text =~ /^(\S +)\[ (.*?)\] $/
163-
164- label = $1
165- url = CGI . escapeHTML ( $2)
161+ if tidy_link_capturing?
162+ return finish_tidy_link ( text )
163+ end
166164
167- if /^rdoc-image:/ =~ label
168- label = handle_RDOCLINK ( label )
169- else
170- label = CGI . escapeHTML ( label )
165+ if text . start_with? ( '{' ) && !text . include? ( '}' )
166+ start_tidy_link text
167+ return ''
171168 end
172169
173- gen_url url , label
170+ convert_complete_tidy_link ( text )
174171 end
175172
176173 # :section: Visitor
@@ -359,7 +356,14 @@ def accept_table(header, body, aligns)
359356 # CGI-escapes +text+
360357
361358 def convert_string ( text )
362- CGI . escapeHTML text
359+ html = CGI . escapeHTML text
360+
361+ if tidy_link_capturing?
362+ append_to_tidy_label html
363+ ''
364+ else
365+ html
366+ end
363367 end
364368
365369 ##
@@ -458,4 +462,104 @@ def to_html(item)
458462 super convert_flow @am . flow item
459463 end
460464
465+ private
466+
467+ def append_to_tidy_label ( fragment )
468+ return unless @tidy_link_buffer
469+
470+ @tidy_link_buffer << fragment
471+ end
472+
473+ def convert_complete_tidy_link ( text )
474+ return text unless
475+ text =~ /^\{ (.*)\} \[ (.*?)\] $/ or text =~ /^(\S +)\[ (.*?)\] $/
476+
477+ label = $1
478+ url = CGI . escapeHTML ( $2)
479+
480+ label_html = if /^rdoc-image:/ =~ label
481+ handle_RDOCLINK ( label )
482+ else
483+ render_tidy_link_label ( label )
484+ end
485+
486+ gen_url url , label_html
487+ end
488+
489+ def emit_tidy_link_fragment ( res , fragment )
490+ if tidy_link_capturing?
491+ append_to_tidy_label fragment
492+ else
493+ res << fragment
494+ end
495+ end
496+
497+ def finish_tidy_link ( text )
498+ label_tail , url , trailing = extract_tidy_link_parts ( text )
499+
500+ append_to_tidy_label CGI . escapeHTML ( label_tail ) unless label_tail . empty?
501+
502+ return '' unless url
503+
504+ label_html = @tidy_link_buffer
505+
506+ @tidy_link_buffer = nil
507+
508+ link = gen_url ( url , label_html )
509+
510+ return link if trailing . empty?
511+
512+ link + CGI . escapeHTML ( trailing )
513+ end
514+
515+ def extract_tidy_link_parts ( text )
516+ if text =~ /^(.*?)\} \[ (.*?)\] (.*)$/
517+ [ $1, CGI . escapeHTML ( $2) , $3]
518+ else
519+ [ text , nil , '' ]
520+ end
521+ end
522+
523+ def on_tags ( res , item )
524+ each_attr_tag ( item . turn_on ) do |tag |
525+ emit_tidy_link_fragment ( res , annotate ( tag . on ) )
526+ @in_tt += 1 if tt? tag
527+ end
528+ end
529+
530+ def off_tags ( res , item )
531+ each_attr_tag ( item . turn_off , true ) do |tag |
532+ emit_tidy_link_fragment ( res , annotate ( tag . off ) )
533+ @in_tt -= 1 if tt? tag
534+ end
535+ end
536+
537+ def start_tidy_link ( text )
538+ @tidy_link_buffer = String . new
539+ append_to_tidy_label CGI . escapeHTML ( text . delete_prefix ( '{' ) )
540+ end
541+
542+ def tidy_link_capturing?
543+ !!@tidy_link_buffer
544+ end
545+
546+ def render_tidy_link_label ( label )
547+ RDoc ::Markup ::LinkLabelToHtml . render ( label , @options , @from_path )
548+ end
549+ end
550+
551+ ##
552+ # Formatter dedicated to rendering tidy link labels without mutating the
553+ # calling formatter's state.
554+
555+ class RDoc ::Markup ::LinkLabelToHtml < RDoc ::Markup ::ToHtml
556+ def self . render ( label , options , from_path )
557+ new ( options , from_path ) . to_html ( label )
558+ end
559+
560+ def initialize ( options , from_path = nil )
561+ super ( options )
562+
563+ self . from_path = from_path if from_path
564+ end
461565end
0 commit comments