@@ -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 
@@ -458,4 +455,153 @@ def to_html(item)
458455    super  convert_flow  @am . flow  item 
459456  end 
460457
458+   private 
459+ 
460+   def  convert_flow ( flow_items ) 
461+     res  =  [ ] 
462+ 
463+     flow_items . each  do  |item |
464+       case  item 
465+       when  String 
466+         append_flow_fragment  res ,  convert_string ( item ) 
467+       when  RDoc ::Markup ::AttrChanger 
468+         off_tags  res ,  item 
469+         on_tags   res ,  item 
470+       when  RDoc ::Markup ::RegexpHandling 
471+         append_flow_fragment  res ,  convert_regexp_handling ( item ) 
472+       else 
473+         raise  "Unknown flow element: #{ item . inspect }  " 
474+       end 
475+     end 
476+ 
477+     res . join 
478+   end 
479+ 
480+   def  append_flow_fragment ( res ,  fragment ) 
481+     return  if  fragment . nil?  || fragment . empty? 
482+ 
483+     emit_tidy_link_fragment ( res ,  fragment ) 
484+   end 
485+ 
486+   def  append_to_tidy_label ( fragment ) 
487+     @tidy_link_buffer  << fragment 
488+   end 
489+ 
490+   ## 
491+   # Matches an entire tidy link with a braced label "{label}[url]". 
492+   # 
493+   # Capture 1: label contents. 
494+   # Capture 2: URL text. 
495+   # Capture 3: trailing content. 
496+   TIDY_LINK_WITH_BRACES  =  /\A \{ (.*?)\} \[ (.*?)\] (.*)\z / 
497+ 
498+   ## 
499+   # Matches the tail of a braced tidy link when the opening brace was 
500+   # consumed earlier while accumulating the label text. 
501+   # 
502+   # Capture 1: remaining label content. 
503+   # Capture 2: URL text. 
504+   # Capture 3: trailing content. 
505+   TIDY_LINK_WITH_BRACES_TAIL  =  /\A (.*?)\} \[ (.*?)\] (.*)\z / 
506+ 
507+   ## 
508+   # Matches a tidy link with a single-word label "label[url]". 
509+   # 
510+   # Capture 1: the single-word label (no whitespace). 
511+   # Capture 2: URL text between the brackets. 
512+   TIDY_LINK_SINGLE_WORD  =  /\A (\S +)\[ (.*?)\] (.*)\z / 
513+ 
514+   def  convert_complete_tidy_link ( text ) 
515+     return  text  unless 
516+       text  =~ TIDY_LINK_WITH_BRACES  or  text  =~ TIDY_LINK_SINGLE_WORD 
517+ 
518+     label  =  $1
519+     url    =  CGI . escapeHTML ( $2) 
520+ 
521+     label_html  =  if  /^rdoc-image:/  =~ label 
522+                    handle_RDOCLINK ( label ) 
523+                  else 
524+                    render_tidy_link_label ( label ) 
525+                  end 
526+ 
527+     gen_url  url ,  label_html 
528+   end 
529+ 
530+   def  emit_tidy_link_fragment ( res ,  fragment ) 
531+     if  tidy_link_capturing? 
532+       append_to_tidy_label  fragment 
533+     else 
534+       res  << fragment 
535+     end 
536+   end 
537+ 
538+   def  finish_tidy_link ( text ) 
539+     label_tail ,  url ,  trailing  =  extract_tidy_link_parts ( text ) 
540+     append_to_tidy_label  CGI . escapeHTML ( label_tail )  unless  label_tail . empty? 
541+ 
542+     return  ''  unless  url 
543+ 
544+     label_html  =  @tidy_link_buffer 
545+     @tidy_link_buffer  =  nil 
546+     link  =  gen_url ( url ,  label_html ) 
547+ 
548+     return  link  if  trailing . empty? 
549+ 
550+     link  + CGI . escapeHTML ( trailing ) 
551+   end 
552+ 
553+   def  extract_tidy_link_parts ( text ) 
554+     if  text  =~ TIDY_LINK_WITH_BRACES 
555+       [ $1,  CGI . escapeHTML ( $2) ,  $3] 
556+     elsif  text  =~ TIDY_LINK_WITH_BRACES_TAIL 
557+       [ $1,  CGI . escapeHTML ( $2) ,  $3] 
558+     elsif  text  =~ TIDY_LINK_SINGLE_WORD 
559+       [ $1,  CGI . escapeHTML ( $2) ,  $3] 
560+     else 
561+       [ text ,  nil ,  '' ] 
562+     end 
563+   end 
564+ 
565+   def  on_tags ( res ,  item ) 
566+     each_attr_tag ( item . turn_on )  do  |tag |
567+       emit_tidy_link_fragment ( res ,  annotate ( tag . on ) ) 
568+       @in_tt  += 1  if  tt?  tag 
569+     end 
570+   end 
571+ 
572+   def  off_tags ( res ,  item ) 
573+     each_attr_tag ( item . turn_off ,  true )  do  |tag |
574+       emit_tidy_link_fragment ( res ,  annotate ( tag . off ) ) 
575+       @in_tt  -= 1  if  tt?  tag 
576+     end 
577+   end 
578+ 
579+   def  start_tidy_link ( text ) 
580+     @tidy_link_buffer  =  String . new 
581+     append_to_tidy_label  CGI . escapeHTML ( text . delete_prefix ( '{' ) ) 
582+   end 
583+ 
584+   def  tidy_link_capturing? 
585+     !!@tidy_link_buffer 
586+   end 
587+ 
588+   def  render_tidy_link_label ( label ) 
589+     RDoc ::Markup ::LinkLabelToHtml . render ( label ,  @options ,  @from_path ) 
590+   end 
591+ end 
592+ 
593+ ## 
594+ # Formatter dedicated to rendering tidy link labels without mutating the 
595+ # calling formatter's state. 
596+ 
597+ class  RDoc ::Markup ::LinkLabelToHtml  < RDoc ::Markup ::ToHtml 
598+   def  self . render ( label ,  options ,  from_path ) 
599+     new ( options ,  from_path ) . to_html ( label ) 
600+   end 
601+ 
602+   def  initialize ( options ,  from_path  =  nil ) 
603+     super ( options ) 
604+ 
605+     self . from_path  =  from_path  if  from_path 
606+   end 
461607end 
0 commit comments