[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/pod/Simple/ -> HTML.pm (source)

   1  
   2  require 5;
   3  package Pod::Simple::HTML;
   4  use strict;
   5  use Pod::Simple::PullParser ();
   6  use vars qw(
   7    @ISA %Tagmap $Computerese $LamePad $Linearization_Limit $VERSION
   8    $Perldoc_URL_Prefix $Perldoc_URL_Postfix
   9    $Title_Prefix $Title_Postfix $HTML_EXTENSION %ToIndex
  10    $Doctype_decl  $Content_decl
  11  );
  12  @ISA = ('Pod::Simple::PullParser');
  13  $VERSION = '3.03';
  14  
  15  use UNIVERSAL ();
  16  BEGIN {
  17    if(defined &DEBUG) { } # no-op
  18    elsif( defined &Pod::Simple::DEBUG ) { *DEBUG = \&Pod::Simple::DEBUG }
  19    else { *DEBUG = sub () {0}; }
  20  }
  21  
  22  $Doctype_decl ||= '';  # No.  Just No.  Don't even ask me for it.
  23   # qq{<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  24   #    "http://www.w3.org/TR/html4/loose.dtd">\n};
  25  
  26  $Content_decl ||=
  27   q{<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >};
  28  
  29  $HTML_EXTENSION = '.html' unless defined $HTML_EXTENSION;
  30  $Computerese =  "" unless defined $Computerese;
  31  $LamePad = '' unless defined $LamePad;
  32  
  33  $Linearization_Limit = 120 unless defined $Linearization_Limit;
  34   # headings/items longer than that won't get an <a name="...">
  35  $Perldoc_URL_Prefix  = 'http://search.cpan.org/perldoc?'
  36   unless defined $Perldoc_URL_Prefix;
  37  $Perldoc_URL_Postfix = ''
  38   unless defined $Perldoc_URL_Postfix;
  39  
  40  $Title_Prefix  = '' unless defined $Title_Prefix;
  41  $Title_Postfix = '' unless defined $Title_Postfix;
  42  %ToIndex = map {; $_ => 1 } qw(head1 head2 head3 head4 ); # item-text
  43    # 'item-text' stuff in the index doesn't quite work, and may
  44    # not be a good idea anyhow.
  45  
  46  
  47  __PACKAGE__->_accessorize(
  48   'perldoc_url_prefix',
  49     # In turning L<Foo::Bar> into http://whatever/Foo%3a%3aBar, what
  50     #  to put before the "Foo%3a%3aBar".
  51     # (for singleton mode only?)
  52   'perldoc_url_postfix',
  53     # what to put after "Foo%3a%3aBar" in the URL.  Normally "".
  54  
  55   'batch_mode', # whether we're in batch mode
  56   'batch_mode_current_level',
  57      # When in batch mode, how deep the current module is: 1 for "LWP",
  58      #  2 for "LWP::Procotol", 3 for "LWP::Protocol::GHTTP", etc
  59      
  60   'title_prefix',  'title_postfix',
  61    # What to put before and after the title in the head.
  62    # Should already be &-escaped
  63    
  64   'html_header_before_title',
  65   'html_header_after_title',
  66   'html_footer',
  67  
  68   'index', # whether to add an index at the top of each page
  69      # (actually it's a table-of-contents, but we'll call it an index,
  70      #  out of apparently longstanding habit)
  71  
  72   'html_css', # URL of CSS file to point to
  73   'html_javascript', # URL of CSS file to point to
  74  
  75   'force_title',   # should already be &-escaped
  76   'default_title', # should already be &-escaped
  77  );
  78  
  79  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  80  my @_to_accept;
  81  
  82  %Tagmap = (
  83    'Verbatim'  => "\n<pre$Computerese>",
  84    '/Verbatim' => "</pre>\n",
  85    'VerbatimFormatted'  => "\n<pre$Computerese>",
  86    '/VerbatimFormatted' => "</pre>\n",
  87    'VerbatimB'  => "<b>",
  88    '/VerbatimB' => "</b>",
  89    'VerbatimI'  => "<i>",
  90    '/VerbatimI' => "</i>",
  91    'VerbatimBI'  => "<b><i>",
  92    '/VerbatimBI' => "</i></b>",
  93  
  94  
  95    'Data'  => "\n",
  96    '/Data' => "\n",
  97    
  98    'head1' => "\n<h1>",  # And also stick in an <a name="...">
  99    'head2' => "\n<h2>",  #  ''
 100    'head3' => "\n<h3>",  #  ''
 101    'head4' => "\n<h4>",  #  ''
 102    '/head1' => "</a></h1>\n",
 103    '/head2' => "</a></h2>\n",
 104    '/head3' => "</a></h3>\n",
 105    '/head4' => "</a></h4>\n",
 106  
 107    'X'  => "<!--\n\tINDEX: ",
 108    '/X' => "\n-->",
 109  
 110    changes(qw(
 111      Para=p
 112      B=b I=i
 113      over-bullet=ul
 114      over-number=ol
 115      over-text=dl
 116      over-block=blockquote
 117      item-bullet=li
 118      item-number=li
 119      item-text=dt
 120    )),
 121    changes2(
 122      map {; m/^([-a-z]+)/s && push @_to_accept, $1; $_ }
 123      qw[
 124        sample=samp
 125        definition=dfn
 126        kbd=keyboard
 127        variable=var
 128        citation=cite
 129        abbreviation=abbr
 130        acronym=acronym
 131        subscript=sub
 132        superscript=sup
 133        big=big
 134        small=small
 135        underline=u
 136        strikethrough=s
 137      ]  # no point in providing a way to get <q>...</q>, I think
 138    ),
 139    
 140    '/item-bullet' => "</li>$LamePad\n",
 141    '/item-number' => "</li>$LamePad\n",
 142    '/item-text'   => "</a></dt>$LamePad\n",
 143    'item-body'    => "\n<dd>",
 144    '/item-body'   => "</dd>\n",
 145  
 146  
 147    'B'      =>  "<b>",                  '/B'     =>  "</b>",
 148    'I'      =>  "<i>",                  '/I'     =>  "</i>",
 149    'F'      =>  "<em$Computerese>",     '/F'     =>  "</em>",
 150    'C'      =>  "<code$Computerese>",   '/C'     =>  "</code>",
 151    'L'  =>  "<a href='YOU_SHOULD_NEVER_SEE_THIS'>", # ideally never used!
 152    '/L' =>  "</a>",
 153  );
 154  
 155  sub changes {
 156    return map {; m/^([-_:0-9a-zA-Z]+)=([-_:0-9a-zA-Z]+)$/s
 157       ? ( $1, => "\n<$2>", "/$1", => "</$2>\n" ) : die "Funky $_"
 158    } @_;
 159  }
 160  sub changes2 {
 161    return map {; m/^([-_:0-9a-zA-Z]+)=([-_:0-9a-zA-Z]+)$/s
 162       ? ( $1, => "<$2>", "/$1", => "</$2>" ) : die "Funky $_"
 163    } @_;
 164  }
 165  
 166  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 167  sub go { exit Pod::Simple::HTML->parse_from_file(@ARGV) }
 168   # Just so we can run from the command line.  No options.
 169   #  For that, use perldoc!
 170  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 171  
 172  sub new {
 173    my $new = shift->SUPER::new(@_);
 174    #$new->nix_X_codes(1);
 175    $new->nbsp_for_S(1);
 176    $new->accept_targets( 'html', 'HTML' );
 177    $new->accept_codes('VerbatimFormatted');
 178    $new->accept_codes(@_to_accept);
 179    DEBUG > 2 and print "To accept: ", join(' ',@_to_accept), "\n";
 180  
 181    $new->perldoc_url_prefix(  $Perldoc_URL_Prefix  );
 182    $new->perldoc_url_postfix( $Perldoc_URL_Postfix );
 183    $new->title_prefix(  $Title_Prefix  );
 184    $new->title_postfix( $Title_Postfix );
 185  
 186    $new->html_header_before_title(
 187     qq[$Doctype_decl<html><head><title>]
 188    );
 189    $new->html_header_after_title( join "\n" =>
 190      "</title>",
 191      $Content_decl,
 192      "</head>\n<body class='pod'>",
 193      $new->version_tag_comment,
 194      "<!-- start doc -->\n",
 195    );
 196    $new->html_footer( qq[\n<!-- end doc -->\n\n</body></html>\n] );
 197  
 198    $new->{'Tagmap'} = {%Tagmap};
 199    return $new;
 200  }
 201  
 202  sub batch_mode_page_object_init {
 203    my($self, $batchconvobj, $module, $infile, $outfile, $depth) = @_;
 204    DEBUG and print "Initting $self\n  for $module\n",
 205      "  in $infile\n  out $outfile\n  depth $depth\n";
 206    $self->batch_mode(1);
 207    $self->batch_mode_current_level($depth);
 208    return $self;
 209  }
 210  
 211  sub run {
 212    my $self = $_[0];
 213    return $self->do_middle if $self->bare_output;
 214    return
 215     $self->do_beginning && $self->do_middle && $self->do_end;
 216  }
 217  
 218  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 219  
 220  sub do_beginning {
 221    my $self = $_[0];
 222  
 223    my $title;
 224    
 225    if(defined $self->force_title) {
 226      $title = $self->force_title;
 227      DEBUG and print "Forcing title to be $title\n";
 228    } else {
 229      # Actually try looking for the title in the document:
 230      $title = $self->get_short_title();
 231      unless($self->content_seen) {
 232        DEBUG and print "No content seen in search for title.\n";
 233        return;
 234      }
 235      $self->{'Title'} = $title;
 236  
 237      if(defined $title and $title =~ m/\S/) {
 238        $title = $self->title_prefix . esc($title) . $self->title_postfix;
 239      } else {
 240        $title = $self->default_title;    
 241        $title = '' unless defined $title;
 242        DEBUG and print "Title defaults to $title\n";
 243      }
 244    }
 245  
 246    
 247    my $after = $self->html_header_after_title  || '';
 248    if($self->html_css) {
 249      my $link =
 250      $self->html_css =~ m/</
 251       ? $self->html_css # It's a big blob of markup, let's drop it in
 252       : sprintf(        # It's just a URL, so let's wrap it up
 253        qq[<link rel="stylesheet" type="text/css" title="pod_stylesheet" href="%s">\n],
 254        $self->html_css,
 255      );
 256      $after =~ s{(</head>)}{$link\n$1}i;  # otherwise nevermind
 257    }
 258    $self->_add_top_anchor(\$after);
 259  
 260    if($self->html_javascript) {
 261      my $link =
 262      $self->html_javascript =~ m/</
 263       ? $self->html_javascript # It's a big blob of markup, let's drop it in
 264       : sprintf(        # It's just a URL, so let's wrap it up
 265        qq[<script type="text/javascript" src="%s"></script>\n],
 266        $self->html_javascript,
 267      );
 268      $after =~ s{(</head>)}{$link\n$1}i;  # otherwise nevermind
 269    }
 270  
 271    print {$self->{'output_fh'}}
 272      $self->html_header_before_title || '',
 273      $title, # already escaped
 274      $after,
 275    ;
 276  
 277    DEBUG and print "Returning from do_beginning...\n";
 278    return 1;
 279  }
 280  
 281  sub _add_top_anchor {
 282    my($self, $text_r) = @_;
 283    unless($$text_r and $$text_r =~ m/name=['"]___top['"]/) { # a hack
 284      $$text_r .= "<a name='___top' class='dummyTopAnchor' ></a>\n";
 285    }
 286    return;
 287  }
 288  
 289  sub version_tag_comment {
 290    my $self = shift;
 291    return sprintf
 292     "<!--\n  generated by %s v%s,\n  using %s v%s,\n  under Perl v%s at %s GMT.\n\n %s\n\n-->\n",
 293     esc(
 294      ref($self), $self->VERSION(), $ISA[0], $ISA[0]->VERSION(),
 295      $], scalar(gmtime),
 296     ), $self->_modnote(),
 297    ;
 298  }
 299  
 300  sub _modnote {
 301    my $class = ref($_[0]) || $_[0];
 302    return join "\n   " => grep m/\S/, split "\n",
 303  
 304  qq{
 305  If you want to change this HTML document, you probably shouldn't do that
 306  by changing it directly.  Instead, see about changing the calling options
 307  to $class, and/or subclassing $class,
 308  then reconverting this document from the Pod source.
 309  When in doubt, email the author of $class for advice.
 310  See 'perldoc $class' for more info.
 311  };
 312  
 313  }
 314  
 315  sub do_end {
 316    my $self = $_[0];
 317    print {$self->{'output_fh'}}  $self->html_footer || '';
 318    return 1;
 319  }
 320  
 321  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 322  # Normally this would just be a call to _do_middle_main_loop -- but we
 323  #  have to do some elaborate things to emit all the content and then
 324  #  summarize it and output it /before/ the content that it's a summary of.
 325  
 326  sub do_middle {
 327    my $self = $_[0];
 328    return $self->_do_middle_main_loop unless $self->index;
 329  
 330    if( $self->output_string ) {
 331      # An efficiency hack
 332      my $out = $self->output_string; #it's a reference to it
 333      my $sneakytag = "\f\f\e\e\b\bIndex Here\e\e\b\b\f\f\n";
 334      $$out .= $sneakytag;
 335      $self->_do_middle_main_loop;
 336      $sneakytag = quotemeta($sneakytag);
 337      my $index = $self->index_as_html();
 338      if( $$out =~ s/$sneakytag/$index/s ) {
 339        # Expected case
 340        DEBUG and print "Inserted ", length($index), " bytes of index HTML into $out.\n";
 341      } else {
 342        DEBUG and print "Odd, couldn't find where to insert the index in the output!\n";
 343        # I don't think this should ever happen.
 344      }
 345      return 1;
 346    }
 347  
 348    unless( $self->output_fh ) {
 349      require Carp;
 350      Carp::confess("Parser object \$p doesn't seem to have any output object!  I don't know how to deal with that.");
 351    }
 352  
 353    # If we get here, we're outputting to a FH.  So we need to do some magic.
 354    # Namely, divert all content to a string, which we output after the index.
 355    my $fh = $self->output_fh;
 356    my $content = '';
 357    {
 358      # Our horrible bait and switch:
 359      $self->output_string( \$content );
 360      $self->_do_middle_main_loop;
 361      $self->abandon_output_string();
 362      $self->output_fh($fh);
 363    }
 364    print $fh $self->index_as_html();
 365    print $fh $content;
 366  
 367    return 1;
 368  }
 369  
 370  ###########################################################################
 371  
 372  sub index_as_html {
 373    my $self = $_[0];
 374    # This is meant to be called AFTER the input document has been parsed!
 375  
 376    my $points = $self->{'PSHTML_index_points'} || [];
 377    
 378    @$points > 1 or return qq[<div class='indexgroupEmpty'></div>\n];
 379     # There's no point in having a 0-item or 1-item index, I dare say.
 380    
 381    my(@out) = qq{\n<div class='indexgroup'>};
 382    my $level = 0;
 383  
 384    my( $target_level, $previous_tagname, $tagname, $text, $anchorname, $indent);
 385    foreach my $p (@$points, ['head0', '(end)']) {
 386      ($tagname, $text) = @$p;
 387      $anchorname = $self->section_escape($text);
 388      if( $tagname =~ m{^head(\d+)$} ) {
 389        $target_level = 0 + $1;
 390      } else {  # must be some kinda list item
 391        if($previous_tagname =~ m{^head\d+$} ) {
 392          $target_level = $level + 1;
 393        } else {
 394          $target_level = $level;  # no change needed
 395        }
 396      }
 397      
 398      # Get to target_level by opening or closing ULs
 399      while($level > $target_level)
 400       { --$level; push @out, ("  " x $level) . "</ul>"; }
 401      while($level < $target_level)
 402       { ++$level; push @out, ("  " x ($level-1))
 403         . "<ul   class='indexList indexList$level'>"; }
 404  
 405      $previous_tagname = $tagname;
 406      next unless $level;
 407      
 408      $indent = '  '  x $level;
 409      push @out, sprintf
 410        "%s<li class='indexItem indexItem%s'><a href='#%s'>%s</a>",
 411        $indent, $level, $anchorname, esc($text)
 412      ;
 413    }
 414    push @out, "</div>\n";
 415    return join "\n", @out;
 416  }
 417  
 418  ###########################################################################
 419  
 420  sub _do_middle_main_loop {
 421    my $self = $_[0];
 422    my $fh = $self->{'output_fh'};
 423    my $tagmap = $self->{'Tagmap'};
 424    
 425    my($token, $type, $tagname, $linkto, $linktype);
 426    my @stack;
 427    my $dont_wrap = 0;
 428  
 429    while($token = $self->get_token) {
 430  
 431      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 432      if( ($type = $token->type) eq 'start' ) {
 433        if(($tagname = $token->tagname) eq 'L') {
 434          $linktype = $token->attr('type') || 'insane';
 435          
 436          $linkto = $self->do_link($token);
 437  
 438          if(defined $linkto and length $linkto) {
 439            esc($linkto);
 440              #   (Yes, SGML-escaping applies on top of %-escaping!
 441              #   But it's rarely noticeable in practice.)
 442            print $fh qq{<a href="$linkto" class="podlink$linktype"\n>};
 443          } else {
 444            print $fh "<a>"; # Yes, an 'a' element with no attributes!
 445          }
 446  
 447        } elsif ($tagname eq 'item-text' or $tagname =~ m/^head\d$/s) {
 448          print $fh $tagmap->{$tagname} || next;
 449  
 450          my @to_unget;
 451          while(1) {
 452            push @to_unget, $self->get_token;
 453            last if $to_unget[-1]->is_end
 454                and $to_unget[-1]->tagname eq $tagname;
 455            
 456            # TODO: support for X<...>'s found in here?  (maybe hack into linearize_tokens)
 457          }
 458  
 459          my $name = $self->linearize_tokens(@to_unget);
 460          
 461          print $fh "<a ";
 462          print $fh "class='u' href='#___top' title='click to go to top of document'\n"
 463           if $tagname =~ m/^head\d$/s;
 464          
 465          if(defined $name) {
 466            my $esc = esc(  $self->section_name_tidy( $name ) );
 467            print $fh qq[name="$esc"];
 468            DEBUG and print "Linearized ", scalar(@to_unget),
 469             " tokens as \"$name\".\n";
 470            push @{ $self->{'PSHTML_index_points'} }, [$tagname, $name]
 471             if $ToIndex{ $tagname };
 472              # Obviously, this discards all formatting codes (saving
 473              #  just their content), but ahwell.
 474             
 475          } else {  # ludicrously long, so nevermind
 476            DEBUG and print "Linearized ", scalar(@to_unget),
 477             " tokens, but it was too long, so nevermind.\n";
 478          }
 479          print $fh "\n>";
 480          $self->unget_token(@to_unget);
 481  
 482        } elsif ($tagname eq 'Data') {
 483          my $next = $self->get_token;
 484          next unless defined $next;
 485          unless( $next->type eq 'text' ) {
 486            $self->unget_token($next);
 487            next;
 488          }
 489          DEBUG and print "    raw text ", $next->text, "\n";
 490          printf $fh "\n" . $next->text . "\n";
 491          next;
 492         
 493        } else {
 494          if( $tagname =~ m/^over-/s ) {
 495            push @stack, '';
 496          } elsif( $tagname =~ m/^item-/s and @stack and $stack[-1] ) {
 497            print $fh $stack[-1];
 498            $stack[-1] = '';
 499          }
 500          print $fh $tagmap->{$tagname} || next;
 501          ++$dont_wrap if $tagname eq 'Verbatim' or $tagname eq "VerbatimFormatted"
 502            or $tagname eq 'X';
 503        }
 504  
 505      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 506      } elsif( $type eq 'end' ) {
 507        if( ($tagname = $token->tagname) =~ m/^over-/s ) {
 508          if( my $end = pop @stack ) {
 509            print $fh $end;
 510          }
 511        } elsif( $tagname =~ m/^item-/s and @stack) {
 512          $stack[-1] = $tagmap->{"/$tagname"};
 513          if( $tagname eq 'item-text' and defined(my $next = $self->get_token) ) {
 514            $self->unget_token($next);
 515            if( $next->type eq 'start' and $next->tagname !~ m/^item-/s ) {
 516              print $fh $tagmap->{"/item-text"},$tagmap->{"item-body"};
 517              $stack[-1] = $tagmap->{"/item-body"};
 518            }
 519          }
 520          next;
 521        }
 522        print $fh $tagmap->{"/$tagname"} || next;
 523        --$dont_wrap if $tagname eq 'Verbatim' or $tagname eq 'X';
 524  
 525      # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 526      } elsif( $type eq 'text' ) {
 527        esc($type = $token->text);  # reuse $type, why not
 528        $type =~ s/([\?\!\"\'\.\,]) /$1\n/g unless $dont_wrap;
 529        print $fh $type;
 530      }
 531  
 532    }
 533    return 1;
 534  }
 535  
 536  ###########################################################################
 537  #
 538  
 539  sub do_link {
 540    my($self, $token) = @_;
 541    my $type = $token->attr('type');
 542    if(!defined $type) {
 543      $self->whine("Typeless L!?", $token->attr('start_line'));
 544    } elsif( $type eq 'pod') { return $self->do_pod_link($token);
 545    } elsif( $type eq 'url') { return $self->do_url_link($token);
 546    } elsif( $type eq 'man') { return $self->do_man_link($token);
 547    } else {
 548      $self->whine("L of unknown type $type!?", $token->attr('start_line'));
 549    }
 550    return 'FNORG'; # should never get called
 551  }
 552  
 553  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 554  
 555  sub do_url_link { return $_[1]->attr('to') }
 556  
 557  sub do_man_link { return undef }
 558   # But subclasses are welcome to override this if they have man
 559   #  pages somewhere URL-accessible.
 560  
 561  
 562  sub do_pod_link {
 563    # And now things get really messy...
 564    my($self, $link) = @_;
 565    my $to = $link->attr('to');
 566    my $section = $link->attr('section');
 567    return undef unless(  # should never happen
 568      (defined $to and length $to) or
 569      (defined $section and length $section)
 570    );
 571  
 572    $section = $self->section_escape($section)
 573     if defined $section and length($section .= ''); # (stringify)
 574  
 575    DEBUG and printf "Resolving \"%s\" \"%s\"...\n",
 576     $to || "(nil)",  $section || "(nil)";
 577     
 578    {
 579      # An early hack:
 580      my $complete_url = $self->resolve_pod_link_by_table($to, $section);
 581      if( $complete_url ) {
 582        DEBUG > 1 and print "resolve_pod_link_by_table(T,S) gives ",
 583          $complete_url, "\n  (Returning that.)\n";
 584        return $complete_url;
 585      } else {
 586        DEBUG > 4 and print " resolve_pod_link_by_table(T,S)", 
 587         " didn't return anything interesting.\n";
 588      }
 589    }
 590  
 591    if(defined $to and length $to) {
 592      # Give this routine first hack again
 593      my $there = $self->resolve_pod_link_by_table($to);
 594      if(defined $there and length $there) {
 595        DEBUG > 1
 596         and print "resolve_pod_link_by_table(T) gives $there\n";
 597      } else {
 598        $there = 
 599          $self->resolve_pod_page_link($to, $section);
 600           # (I pass it the section value, but I don't see a
 601           #  particular reason it'd use it.)
 602        DEBUG > 1 and print "resolve_pod_page_link gives ", $to || "(nil)", "\n";
 603        unless( defined $there and length $there ) {
 604          DEBUG and print "Can't resolve $to\n";
 605          return undef;
 606        }
 607        # resolve_pod_page_link returning undef is how it
 608        #  can signal that it gives up on making a link
 609      }
 610      $to = $there;
 611    }
 612  
 613    #DEBUG and print "So far [", $to||'nil', "] [", $section||'nil', "]\n";
 614  
 615    my $out = (defined $to and length $to) ? $to : '';
 616    $out .= "#" . $section if defined $section and length $section;
 617    
 618    unless(length $out) { # sanity check
 619      DEBUG and printf "Oddly, couldn't resolve \"%s\" \"%s\"...\n",
 620       $to || "(nil)",  $section || "(nil)";
 621      return undef;
 622    }
 623  
 624    DEBUG and print "Resolved to $out\n";
 625    return $out;  
 626  }
 627  
 628  
 629  # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 630  
 631  sub section_escape {
 632    my($self, $section) = @_;
 633    return $self->section_url_escape(
 634      $self->section_name_tidy($section)
 635    );
 636  }
 637  
 638  sub section_name_tidy {
 639    my($self, $section) = @_;
 640    $section =~ tr/ /_/;
 641    $section =~ tr/\x00-\x1F\x80-\x9F//d if 'A' eq chr(65); # drop crazy characters
 642    $section = $self->unicode_escape_url($section);
 643    $section = '_' unless length $section;
 644    return $section;
 645  }
 646  
 647  sub section_url_escape  { shift->general_url_escape(@_) }
 648  sub pagepath_url_escape { shift->general_url_escape(@_) }
 649  
 650  sub general_url_escape {
 651    my($self, $string) = @_;
 652   
 653    $string =~ s/([^\x00-\xFF])/join '', map sprintf('%%%02X',$_), unpack 'C*', $1/eg;
 654       # express Unicode things as urlencode(utf(orig)).
 655    
 656    # A pretty conservative escaping, behoovey even for query components
 657    #  of a URL (see RFC 2396)
 658    
 659    $string =~ s/([^-_\.!~*()abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/sprintf('%%%02X',ord($1))/eg;
 660     # Yes, stipulate the list without a range, so that this can work right on
 661     #  all charsets that this module happens to run under.
 662     # Altho, hmm, what about that ord?  Presumably that won't work right
 663     #  under non-ASCII charsets.  Something should be done
 664     #  about that, I guess?
 665    
 666    return $string;
 667  }
 668  
 669  #--------------------------------------------------------------------------
 670  #
 671  # Oh look, a yawning portal to Hell!  Let's play touch football right by it!
 672  #
 673  
 674  sub resolve_pod_page_link {
 675    # resolve_pod_page_link must return a properly escaped URL
 676    my $self = shift;
 677    return $self->batch_mode()
 678     ? $self->resolve_pod_page_link_batch_mode(@_)
 679     : $self->resolve_pod_page_link_singleton_mode(@_)
 680    ;
 681  }
 682  
 683  sub resolve_pod_page_link_singleton_mode {
 684    my($self, $it) = @_;
 685    return undef unless defined $it and length $it;
 686    my $url = $self->pagepath_url_escape($it);
 687    
 688    $url =~ s{::$}{}s; # probably never comes up anyway
 689    $url =~ s{::}{/}g unless $self->perldoc_url_prefix =~ m/\?/s; # sane DWIM?
 690    
 691    return undef unless length $url;
 692    return $self->perldoc_url_prefix . $url . $self->perldoc_url_postfix;
 693  }
 694  
 695  sub resolve_pod_page_link_batch_mode {
 696    my($self, $to) = @_;
 697    DEBUG > 1 and print " During batch mode, resolving $to ...\n";
 698    my @path = grep length($_), split m/::/s, $to, -1;
 699    unless( @path ) { # sanity
 700      DEBUG and print "Very odd!  Splitting $to gives (nil)!\n";
 701      return undef;
 702    }
 703    $self->batch_mode_rectify_path(\@path);
 704    my $out = join('/', map $self->pagepath_url_escape($_), @path)
 705      . $HTML_EXTENSION;
 706    DEBUG > 1 and print " => $out\n";
 707    return $out;
 708  }
 709  
 710  sub batch_mode_rectify_path {
 711    my($self, $pathbits) = @_;
 712    my $level = $self->batch_mode_current_level;
 713    $level--; # how many levels up to go to get to the root
 714    if($level < 1) {
 715      unshift @$pathbits, '.'; # just to be pretty
 716    } else {
 717      unshift @$pathbits, ('..') x $level;
 718    }
 719    return;
 720  }
 721  
 722  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 723  
 724  sub resolve_pod_link_by_table {
 725    # A crazy hack to allow specifying custom L<foo> => URL mappings
 726  
 727    return unless $_[0]->{'podhtml_LOT'};  # An optimizy shortcut
 728  
 729    my($self, $to, $section) = @_;
 730  
 731    # TODO: add a method that actually populates podhtml_LOT from a file?
 732  
 733    if(defined $section) {
 734      $to = '' unless defined $to and length $to;
 735      return $self->{'podhtml_LOT'}{"$to#$section"}; # quite possibly undef!
 736    } else {
 737      return $self->{'podhtml_LOT'}{$to};            # quite possibly undef!
 738    }
 739    return;
 740  }
 741  
 742  ###########################################################################
 743  
 744  sub linearize_tokens {  # self, tokens
 745    my $self = shift;
 746    my $out = '';
 747    
 748    my $t;
 749    while($t = shift @_) {
 750      if(!ref $t or !UNIVERSAL::can($t, 'is_text')) {
 751        $out .= $t; # a string, or some insane thing
 752      } elsif($t->is_text) {
 753        $out .= $t->text;
 754      } elsif($t->is_start and $t->tag eq 'X') {
 755        # Ignore until the end of this X<...> sequence:
 756        my $x_open = 1;
 757        while($x_open) {
 758          next if( ($t = shift @_)->is_text );
 759          if(   $t->is_start and $t->tag eq 'X') { ++$x_open }
 760          elsif($t->is_end   and $t->tag eq 'X') { --$x_open }
 761        }
 762      }
 763    }
 764    return undef if length $out > $Linearization_Limit;
 765    return $out;
 766  }
 767  
 768  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 769  
 770  sub unicode_escape_url {
 771    my($self, $string) = @_;
 772    $string =~ s/([^\x00-\xFF])/'('.ord($1).')'/eg;
 773      #  Turn char 1234 into "(1234)"
 774    return $string;
 775  }
 776  
 777  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 778  sub esc { # a function.
 779    if(defined wantarray) {
 780      if(wantarray) {
 781        @_ = splice @_; # break aliasing
 782      } else {
 783        my $x = shift;
 784        $x =~ s/([^-\n\t !\#\$\%\(\)\*\+,\.\~\/\:\;=\?\@\[\\\]\^_\`\{\|\}abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/'&#'.(ord($1)).';'/eg;
 785        return $x;
 786      }
 787    }
 788    foreach my $x (@_) {
 789      # Escape things very cautiously:
 790      $x =~ s/([^-\n\t !\#\$\%\(\)\*\+,\.\~\/\:\;=\?\@\[\\\]\^_\`\{\|\}abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789])/'&#'.(ord($1)).';'/eg
 791       if defined $x;
 792      # Leave out "- so that "--" won't make it thru in X-generated comments
 793      #  with text in them.
 794  
 795      # Yes, stipulate the list without a range, so that this can work right on
 796      #  all charsets that this module happens to run under.
 797      # Altho, hmm, what about that ord?  Presumably that won't work right
 798      #  under non-ASCII charsets.  Something should be done about that.
 799    }
 800    return @_;
 801  }
 802  
 803  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 804  
 805  1;
 806  __END__
 807  
 808  =head1 NAME
 809  
 810  Pod::Simple::HTML - convert Pod to HTML
 811  
 812  =head1 SYNOPSIS
 813  
 814    perl -MPod::Simple::HTML -e Pod::Simple::HTML::go thingy.pod
 815  
 816  
 817  =head1 DESCRIPTION
 818  
 819  This class is for making an HTML rendering of a Pod document.
 820  
 821  This is a subclass of L<Pod::Simple::PullParser> and inherits all its
 822  methods (and options).
 823  
 824  Note that if you want to do a batch conversion of a lot of Pod
 825  documents to HTML, you should see the module L<Pod::Simple::HTMLBatch>.
 826  
 827  
 828  
 829  =head1 CALLING FROM THE COMMAND LINE
 830  
 831  TODO
 832  
 833    perl -MPod::Simple::HTML -e Pod::Simple::HTML::go Thing.pod Thing.html
 834  
 835  
 836  
 837  =head1 CALLING FROM PERL
 838  
 839  TODO   make a new object, set any options, and use parse_from_file
 840  
 841  
 842  =head1 METHODS
 843  
 844  TODO
 845  all (most?) accessorized methods
 846  
 847  
 848  =head1 SUBCLASSING
 849  
 850  TODO
 851  
 852   can just set any of:  html_css html_javascript title_prefix
 853    'html_header_before_title',
 854    'html_header_after_title',
 855    'html_footer',
 856  
 857  maybe override do_pod_link
 858  
 859  maybe override do_beginning do_end
 860  
 861  
 862  
 863  =head1 SEE ALSO
 864  
 865  L<Pod::Simple>, L<Pod::Simple::HTMLBatch>
 866  
 867  
 868  TODO: a corpus of sample Pod input and HTML output?  Or common
 869  idioms?
 870  
 871  
 872  
 873  =head1 COPYRIGHT AND DISCLAIMERS
 874  
 875  Copyright (c) 2002-2004 Sean M. Burke.  All rights reserved.
 876  
 877  This library is free software; you can redistribute it and/or modify it
 878  under the same terms as Perl itself.
 879  
 880  This program is distributed in the hope that it will be useful, but
 881  without any warranty; without even the implied warranty of
 882  merchantability or fitness for a particular purpose.
 883  
 884  =head1 AUTHOR
 885  
 886  Sean M. Burke C<sburke@cpan.org>
 887  
 888  =cut
 889  


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1