| blib/lib/Pod/WinHtml.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 24 | 628 | 3.8 |
| branch | 0 | 384 | 0.0 |
| condition | 0 | 75 | 0.0 |
| subroutine | 8 | 42 | 19.0 |
| pod | 0 | 34 | 0.0 |
| total | 32 | 1163 | 2.7 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | # $File: //member/autrijus/Pod-HtmlHelp/WinHtml.pm $ $Author: autrijus $ | ||||||
| 2 | # $Revision: #1 $ $Change: 1 $ $DateTime: 2002/06/11 08:35:12 $ | ||||||
| 3 | |||||||
| 4 | package Pod::WinHtml; | ||||||
| 5 | |||||||
| 6 | 1 | 1 | 1685 | use Pod::Functions; | |||
| 1 | 3903 | ||||||
| 1 | 179 | ||||||
| 7 | 1 | 1 | 1254 | use Getopt::Long; # package for handling command-line parameters | |||
| 1 | 13539 | ||||||
| 1 | 6 | ||||||
| 8 | require Exporter; | ||||||
| 9 | 1 | 1 | 246 | use vars qw($VERSION); | |||
| 1 | 2 | ||||||
| 1 | 70 | ||||||
| 10 | |||||||
| 11 | $VERSION = 1.01; | ||||||
| 12 | @ISA = Exporter; | ||||||
| 13 | @EXPORT = qw(pod2html htmlify); | ||||||
| 14 | |||||||
| 15 | 1 | 1 | 5 | use Cwd; | |||
| 1 | 2 | ||||||
| 1 | 65 | ||||||
| 16 | 1 | 1 | 6 | use Carp; | |||
| 1 | 1 | ||||||
| 1 | 63 | ||||||
| 17 | 1 | 1 | 7 | use strict; | |||
| 1 | 2 | ||||||
| 1 | 32 | ||||||
| 18 | 1 | 1 | 1488 | use locale; # make \w work right in non-ASCII lands | |||
| 1 | 228 | ||||||
| 1 | 5 | ||||||
| 19 | 1 | 1 | 27 | use Config; | |||
| 1 | 2 | ||||||
| 1 | 12653 | ||||||
| 20 | |||||||
| 21 | my $dircache = "pod2html-dircache"; | ||||||
| 22 | my $itemcache = "pod2html-itemcache"; | ||||||
| 23 | |||||||
| 24 | my @begin_stack = (); # begin/end stack | ||||||
| 25 | |||||||
| 26 | my @libpods = (); # files to search for links from C<> directives | ||||||
| 27 | my $htmlroot = "/"; # http-server base directory from which all | ||||||
| 28 | # relative paths in $podpath stem. | ||||||
| 29 | my $htmlfile = ""; # write to stdout by default | ||||||
| 30 | my $podfile = ""; # read from stdin by default | ||||||
| 31 | my @podpath = (); # list of directories containing library pods. | ||||||
| 32 | my $podroot = "."; # filesystem base directory from which all | ||||||
| 33 | # relative paths in $podpath stem. | ||||||
| 34 | my $css = ''; | ||||||
| 35 | |||||||
| 36 | my $csslink = ""; | ||||||
| 37 | $csslink =~ s{\\}{/}g; | ||||||
| 38 | $csslink =~ s{(/.):}{$1|}; | ||||||
| 39 | my $recurse = 1; # recurse on subdirectories in $podpath. | ||||||
| 40 | my $verbose = 0; # not verbose by default | ||||||
| 41 | my $doindex = 1; # non-zero if we should generate an index | ||||||
| 42 | my $listlevel = 0; # current list depth | ||||||
| 43 | my @listitem = (); # stack of HTML commands to use when a =item is | ||||||
| 44 | # encountered. the top of the stack is the | ||||||
| 45 | # current list. | ||||||
| 46 | my @listdata = (); # similar to @listitem, but for the text after | ||||||
| 47 | # an =item | ||||||
| 48 | my @listend = (); # similar to @listitem, but the text to use to | ||||||
| 49 | # end the list. | ||||||
| 50 | my $ignore = 1; # whether or not to format text. we don't | ||||||
| 51 | # format text until we hit our first pod | ||||||
| 52 | # directive. | ||||||
| 53 | |||||||
| 54 | my %items_named = (); # for the multiples of the same item in perlfunc | ||||||
| 55 | my @items_seen = (); | ||||||
| 56 | my $netscape = 0; # whether or not to use netscape directives. | ||||||
| 57 | my $title; # title to give the pod(s) | ||||||
| 58 | my $top = 1; # true if we are at the top of the doc. used | ||||||
| 59 | # to prevent the first directive. |
||||||
| 60 | my $paragraph; # which paragraph we're processing (used | ||||||
| 61 | # for error messages) | ||||||
| 62 | my %pages = (); # associative array used to find the location | ||||||
| 63 | # of pages referenced by L<> links. | ||||||
| 64 | my %sections = (); # sections within this page | ||||||
| 65 | my %items = (); # associative array used to find the location | ||||||
| 66 | # of =item directives referenced by C<> links | ||||||
| 67 | my $Is83; # is dos with short filenames (8.3) | ||||||
| 68 | |||||||
| 69 | sub init_globals { | ||||||
| 70 | 0 | 0 | 0 | $dircache = "pod2html.dir"; | |||
| 71 | 0 | $itemcache = "pod2html.itm"; | |||||
| 72 | |||||||
| 73 | 0 | @begin_stack = (); # begin/end stack | |||||
| 74 | |||||||
| 75 | 0 | @libpods = (); # files to search for links from C<> directives | |||||
| 76 | 0 | $htmlroot = "/"; # http-server base directory from which all | |||||
| 77 | # relative paths in $podpath stem. | ||||||
| 78 | 0 | $htmlfile = ""; # write to stdout by default | |||||
| 79 | 0 | $podfile = ""; # read from stdin by default | |||||
| 80 | 0 | @podpath = (); # list of directories containing library pods. | |||||
| 81 | 0 | $podroot = "."; # filesystem base directory from which all | |||||
| 82 | # relative paths in $podpath stem. | ||||||
| 83 | 0 | $recurse = 1; # recurse on subdirectories in $podpath. | |||||
| 84 | 0 | $verbose = 0; # not verbose by default | |||||
| 85 | 0 | $doindex = 1; # non-zero if we should generate an index | |||||
| 86 | 0 | $listlevel = 0; # current list depth | |||||
| 87 | 0 | @listitem = (); # stack of HTML commands to use when a =item is | |||||
| 88 | # encountered. the top of the stack is the | ||||||
| 89 | # current list. | ||||||
| 90 | 0 | @listdata = (); # similar to @listitem, but for the text after | |||||
| 91 | # an =item | ||||||
| 92 | 0 | @listend = (); # similar to @listitem, but the text to use to | |||||
| 93 | # end the list. | ||||||
| 94 | 0 | $ignore = 1; # whether or not to format text. we don't | |||||
| 95 | # format text until we hit our first pod | ||||||
| 96 | # directive. | ||||||
| 97 | |||||||
| 98 | 0 | @items_seen = (); | |||||
| 99 | 0 | %items_named = (); | |||||
| 100 | 0 | $netscape = 0; # whether or not to use netscape directives. | |||||
| 101 | 0 | $title = ''; # title to give the pod(s) | |||||
| 102 | 0 | $top = 1; # true if we are at the top of the doc. used | |||||
| 103 | # to prevent the first directive. |
||||||
| 104 | 0 | $paragraph = ''; # which paragraph we're processing (used | |||||
| 105 | # for error messages) | ||||||
| 106 | 0 | %sections = (); # sections within this page | |||||
| 107 | |||||||
| 108 | # These are not reinitialised here but are kept as a cache. | ||||||
| 109 | # See get_cache and related cache management code. | ||||||
| 110 | #%pages = (); # associative array used to find the location | ||||||
| 111 | # of pages referenced by L<> links. | ||||||
| 112 | #%items = (); # associative array used to find the location | ||||||
| 113 | # of =item directives referenced by C<> links | ||||||
| 114 | 0 | $Is83=$^O eq 'dos'; | |||||
| 115 | } | ||||||
| 116 | |||||||
| 117 | my $hashead; | ||||||
| 118 | |||||||
| 119 | sub pod2html { | ||||||
| 120 | 0 | 0 | 0 | local(@ARGV) = @_; | |||
| 121 | 0 | local($/); | |||||
| 122 | 0 | local $_; | |||||
| 123 | |||||||
| 124 | 0 | init_globals(); | |||||
| 125 | |||||||
| 126 | 0 | 0 | 0 | $Is83 = 0 if (defined (&Dos::UseLFN) && Dos::UseLFN()); | |||
| 127 | |||||||
| 128 | # cache of %pages and %items from last time we ran pod2html | ||||||
| 129 | |||||||
| 130 | #undef $opt_help if defined $opt_help; | ||||||
| 131 | |||||||
| 132 | # parse the command-line parameters | ||||||
| 133 | 0 | parse_command_line(); | |||||
| 134 | |||||||
| 135 | # Setup the stylsheet link if one was provided | ||||||
| 136 | 0 | 0 | $csslink = qq() | ||||
| 137 | if $css; | ||||||
| 138 | |||||||
| 139 | # set some variables to their default values if necessary | ||||||
| 140 | 0 | local *POD; | |||||
| 141 | 0 | 0 | 0 | unless (@ARGV && $ARGV[0]) { | |||
| 142 | 0 | 0 | $podfile = "-" unless $podfile; # stdin | ||||
| 143 | 0 | 0 | open(POD, "<$podfile") | ||||
| 144 | || die "$0: cannot open $podfile file for input: $!\n"; | ||||||
| 145 | } else { | ||||||
| 146 | 0 | $podfile = $ARGV[0]; # XXX: might be more filenames | |||||
| 147 | 0 | *POD = *ARGV; | |||||
| 148 | } | ||||||
| 149 | 0 | 0 | $htmlfile = "-" unless $htmlfile; # stdout | ||||
| 150 | 0 | 0 | $htmlroot = "" if $htmlroot eq "/"; # so we don't get a // | ||||
| 151 | |||||||
| 152 | # read the pod a paragraph at a time | ||||||
| 153 | 0 | 0 | warn "Scanning for sections in input file(s)\n" if $verbose; | ||||
| 154 | 0 | $/ = ""; | |||||
| 155 | 0 | my @poddata = |
|||||
| 156 | 0 | close(POD); | |||||
| 157 | |||||||
| 158 | # scan the pod for =head[1-6] directives and build an index | ||||||
| 159 | 0 | my $index = scan_headings(\%sections, @poddata); | |||||
| 160 | |||||||
| 161 | 0 | 0 | unless($index) { | ||||
| 162 | 0 | 0 | warn "No pod in $podfile\n" if $verbose; | ||||
| 163 | 0 | return; | |||||
| 164 | } | ||||||
| 165 | |||||||
| 166 | # open the output file | ||||||
| 167 | 0 | 0 | open(HTML, ">$htmlfile") | ||||
| 168 | || die "$0: cannot open $htmlfile file for output: $!\n"; | ||||||
| 169 | |||||||
| 170 | # put a title in the HTML file if one wasn't specified | ||||||
| 171 | 0 | 0 | if ($title eq '') { | ||||
| 172 | TITLE_SEARCH: { | ||||||
| 173 | 0 | for (my $i = 0; $i < @poddata; $i++) { | |||||
| 0 | |||||||
| 174 | 0 | 0 | if ($poddata[$i] =~ /^=head1\s*(NAME|\Q¦WºÙ\E)/m) { | ||||
| 175 | 0 | for my $para ( @poddata[$i, $i+1] ) { | |||||
| 176 | last TITLE_SEARCH | ||||||
| 177 | 0 | 0 | if ($title) = $para =~ /(\S+\s+-+.*\S)/s; | ||||
| 178 | } | ||||||
| 179 | } | ||||||
| 180 | |||||||
| 181 | } | ||||||
| 182 | } | ||||||
| 183 | } | ||||||
| 184 | 0 | 0 | 0 | if (!$title and $podfile =~ /\.pod$/) { | |||
| 185 | 0 | $doindex = 0; # XXX autrijus | |||||
| 186 | # probably a split pod so take first =head[12] as title | ||||||
| 187 | # for (my $i = 0; $i < @poddata; $i++) { | ||||||
| 188 | # last if ($title) = $poddata[$i] =~ /^=head[12]\s*(.*)/; | ||||||
| 189 | # } | ||||||
| 190 | # warn "adopted '$title' as title for $podfile\n" | ||||||
| 191 | # if $verbose and $title; | ||||||
| 192 | } | ||||||
| 193 | 0 | 0 | if ($title) { | ||||
| 194 | 0 | $title =~ s/\s*\(.*\)//; | |||||
| 195 | } else { | ||||||
| 196 | 0 | $hashead = grep { /^=head1\s/ } @poddata; | |||||
| 0 | |||||||
| 197 | # warn "$0: no title for $podfile"; | ||||||
| 198 | # $podfile =~ /^(.*)(\.[^.\/]+)?$/; | ||||||
| 199 | # $title = ($podfile eq "-" ? 'No Title' : $1); | ||||||
| 200 | # warn "using $title" if $verbose; | ||||||
| 201 | } | ||||||
| 202 | 0 | 0 | my $charset = qq( | ||||
| 203 | |||||||
| 204 | ) if $htmlfile =~ /zh[-_]tw/; | ||||||
| 205 | |||||||
| 206 | 0 | 0 | my $h1 = $title ? "$title" : ''; |
||||
| 207 | 0 | print HTML < | |||||
| 208 | |||||||
| 209 | |||||||
| 210 | |
||||||
| 211 | |||||||
| 212 | $charset | ||||||
| 213 | $csslink | ||||||
| 214 | |||||||
| 215 | |||||||
| 216 | |||||||
| 217 | $h1 | ||||||
| 218 | |||||||
| 219 | END_OF_HEAD | ||||||
| 220 | |||||||
| 221 | # load/reload/validate/cache %pages and %items | ||||||
| 222 | 0 | get_cache($dircache, $itemcache, \@podpath, $podroot, $recurse); | |||||
| 223 | |||||||
| 224 | # scan the pod for =item directives | ||||||
| 225 | 0 | scan_items("", \%items, @poddata); | |||||
| 226 | |||||||
| 227 | # put an index at the top of the file. note, if $doindex is 0 we | ||||||
| 228 | # still generate an index, but surround it with an html comment. | ||||||
| 229 | # that way some other program can extract it if desired. | ||||||
| 230 | 0 | $index =~ s/--+/-/g; | |||||
| 231 | 0 | print HTML "\n"; | |||||
| 232 | 0 | 0 | print HTML "\n" unless $doindex; | ||||
| 235 | 0 | print HTML "\n\n"; | |||||
| 236 | 0 | 0 | print HTML " \n" if $doindex; |
||||
| 237 | |||||||
| 238 | # now convert this file | ||||||
| 239 | 0 | 0 | warn "Converting input file\n" if $verbose; | ||||
| 240 | 0 | foreach my $i (0..$#poddata) { | |||||
| 241 | 0 | $_ = $poddata[$i]; | |||||
| 242 | 0 | $paragraph = $i+1; | |||||
| 243 | 0 | 0 | if (/^(=.*)/s) { # is it a pod directive? | ||||
| 244 | 0 | $ignore = 0; | |||||
| 245 | 0 | $_ = $1; | |||||
| 246 | 0 | 0 | if (/^=begin\s+(\S+)\s*(.*)/si) {# =begin | ||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 247 | 0 | process_begin($1, $2); | |||||
| 248 | } elsif (/^=end\s+(\S+)\s*(.*)/si) {# =end | ||||||
| 249 | 0 | process_end($1, $2); | |||||
| 250 | } elsif (/^=cut/) { # =cut | ||||||
| 251 | 0 | process_cut(); | |||||
| 252 | } elsif (/^=pod/) { # =pod | ||||||
| 253 | 0 | process_pod(); | |||||
| 254 | } else { | ||||||
| 255 | 0 | 0 | 0 | next if @begin_stack && $begin_stack[-1] ne 'html'; | |||
| 256 | |||||||
| 257 | 0 | 0 | if (/^=(head[1-6])\s+(.*\S)/s) { # =head[1-6] heading | ||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 258 | 0 | process_head($1, $2); | |||||
| 259 | } elsif (/^=item\s*(.*\S)/sm) { # =item text | ||||||
| 260 | 0 | process_item($1); | |||||
| 261 | } elsif (/^=over\s*(.*)/) { # =over N | ||||||
| 262 | 0 | process_over(); | |||||
| 263 | } elsif (/^=back/) { # =back | ||||||
| 264 | 0 | process_back(); | |||||
| 265 | } elsif (/^=for\s+(\S+)\s+(.*)/si) {# =for | ||||||
| 266 | 0 | process_for($1,$2); | |||||
| 267 | } else { | ||||||
| 268 | 0 | /^=(\S*)\s*/; | |||||
| 269 | 0 | warn "$0: $podfile: unknown pod directive '$1' in " | |||||
| 270 | . "paragraph $paragraph. ignoring.\n"; | ||||||
| 271 | } | ||||||
| 272 | } | ||||||
| 273 | 0 | $top = 0; | |||||
| 274 | } | ||||||
| 275 | else { | ||||||
| 276 | 0 | 0 | next if $ignore; | ||||
| 277 | 0 | 0 | 0 | next if @begin_stack && $begin_stack[-1] ne 'html'; | |||
| 278 | 0 | my $text = $_; | |||||
| 279 | 0 | process_text(\$text, 1); | |||||
| 280 | 0 | print HTML " \n$text \n"; |
|||||
| 281 | } | ||||||
| 282 | } | ||||||
| 283 | |||||||
| 284 | # finish off any pending directives | ||||||
| 285 | 0 | finish_list(); | |||||
| 286 | 0 | print HTML <<"END_OF_TAIL"; | |||||
| 287 | |||||||
| 288 | |||||||
| 289 | |||||||
| 290 | END_OF_TAIL | ||||||
| 291 | |||||||
| 292 | # close the html file | ||||||
| 293 | 0 | close(HTML); | |||||
| 294 | |||||||
| 295 | 0 | 0 | warn "Finished\n" if $verbose; | ||||
| 296 | } | ||||||
| 297 | |||||||
| 298 | ############################################################################## | ||||||
| 299 | |||||||
| 300 | my $usage; # see below | ||||||
| 301 | sub usage { | ||||||
| 302 | 0 | 0 | 0 | my $podfile = shift; | |||
| 303 | 0 | 0 | warn "$0: $podfile: @_\n" if @_; | ||||
| 304 | 0 | die $usage; | |||||
| 305 | } | ||||||
| 306 | |||||||
| 307 | $usage =< | ||||||
| 308 | Usage: $0 --help --htmlroot= |
||||||
| 309 | --podpath= |
||||||
| 310 | --libpods= |
||||||
| 311 | --netscape --norecurse --noindex | ||||||
| 312 | |||||||
| 313 | --flush - flushes the item and directory caches. | ||||||
| 314 | --help - prints this message. | ||||||
| 315 | --htmlroot - http-server base directory from which all relative paths | ||||||
| 316 | in podpath stem (default is /). | ||||||
| 317 | --index - generate an index at the top of the resulting html | ||||||
| 318 | (default). | ||||||
| 319 | --infile - filename for the pod to convert (input taken from stdin | ||||||
| 320 | by default). | ||||||
| 321 | --libpods - colon-separated list of pages to search for =item pod | ||||||
| 322 | directives in as targets of C<> and implicit links (empty | ||||||
| 323 | by default). note, these are not filenames, but rather | ||||||
| 324 | page names like those that appear in L<> links. | ||||||
| 325 | --netscape - will use netscape html directives when applicable. | ||||||
| 326 | --nonetscape - will not use netscape directives (default). | ||||||
| 327 | --outfile - filename for the resulting html file (output sent to | ||||||
| 328 | stdout by default). | ||||||
| 329 | --podpath - colon-separated list of directories containing library | ||||||
| 330 | pods. empty by default. | ||||||
| 331 | --podroot - filesystem base directory from which all relative paths | ||||||
| 332 | in podpath stem (default is .). | ||||||
| 333 | --noindex - don't generate an index at the top of the resulting html. | ||||||
| 334 | --norecurse - don't recurse on those subdirectories listed in podpath. | ||||||
| 335 | --recurse - recurse on those subdirectories listed in podpath | ||||||
| 336 | (default behavior). | ||||||
| 337 | --title - title that will appear in resulting html file. | ||||||
| 338 | --verbose - self-explanatory | ||||||
| 339 | |||||||
| 340 | END_OF_USAGE | ||||||
| 341 | |||||||
| 342 | sub parse_command_line { | ||||||
| 343 | 0 | 0 | 0 | my ($opt_flush,$opt_help,$opt_htmlroot,$opt_index,$opt_infile,$opt_libpods,$opt_netscape,$opt_outfile,$opt_podpath,$opt_podroot,$opt_norecurse,$opt_recurse,$opt_title,$opt_verbose,$opt_css,$opt_embedcss); | |||
| 344 | 0 | my $result = GetOptions( | |||||
| 345 | 'flush' => \$opt_flush, | ||||||
| 346 | 'help' => \$opt_help, | ||||||
| 347 | 'htmlroot=s' => \$opt_htmlroot, | ||||||
| 348 | 'index!' => \$opt_index, | ||||||
| 349 | 'infile=s' => \$opt_infile, | ||||||
| 350 | 'libpods=s' => \$opt_libpods, | ||||||
| 351 | 'netscape!' => \$opt_netscape, | ||||||
| 352 | 'outfile=s' => \$opt_outfile, | ||||||
| 353 | 'podpath=s' => \$opt_podpath, | ||||||
| 354 | 'podroot=s' => \$opt_podroot, | ||||||
| 355 | 'norecurse' => \$opt_norecurse, | ||||||
| 356 | 'recurse!' => \$opt_recurse, | ||||||
| 357 | 'title=s' => \$opt_title, | ||||||
| 358 | 'verbose' => \$opt_verbose, | ||||||
| 359 | 'css=s' => \$opt_css | ||||||
| 360 | ); | ||||||
| 361 | 0 | 0 | usage("-", "invalid parameters") if not $result; | ||||
| 362 | |||||||
| 363 | 0 | 0 | usage("-") if defined $opt_help; # see if the user asked for help | ||||
| 364 | 0 | $opt_help = ""; # just to make -w shut-up. | |||||
| 365 | |||||||
| 366 | 0 | 0 | $podfile = $opt_infile if defined $opt_infile; | ||||
| 367 | 0 | 0 | $htmlfile = $opt_outfile if defined $opt_outfile; | ||||
| 368 | |||||||
| 369 | 0 | 0 | @podpath = split(":", $opt_podpath) if defined $opt_podpath; | ||||
| 370 | 0 | 0 | @libpods = split(":", $opt_libpods) if defined $opt_libpods; | ||||
| 371 | |||||||
| 372 | 0 | 0 | 0 | warn "Flushing item and directory caches\n" | |||
| 373 | if $opt_verbose && defined $opt_flush; | ||||||
| 374 | 0 | 0 | unlink($dircache, $itemcache) if defined $opt_flush; | ||||
| 375 | |||||||
| 376 | 0 | 0 | $htmlroot = $opt_htmlroot if defined $opt_htmlroot; | ||||
| 377 | 0 | 0 | $podroot = $opt_podroot if defined $opt_podroot; | ||||
| 378 | |||||||
| 379 | 0 | 0 | $doindex = $opt_index if defined $opt_index; | ||||
| 380 | 0 | 0 | $recurse = $opt_recurse if defined $opt_recurse; | ||||
| 381 | 0 | 0 | $title = $opt_title if defined $opt_title; | ||||
| 382 | 0 | 0 | $verbose = defined $opt_verbose ? 1 : 0; | ||||
| 383 | 0 | 0 | $netscape = $opt_netscape if defined $opt_netscape; | ||||
| 384 | |||||||
| 385 | 0 | 0 | $css = $opt_css if defined $opt_css; | ||||
| 386 | } | ||||||
| 387 | |||||||
| 388 | |||||||
| 389 | my $saved_cache_key; | ||||||
| 390 | |||||||
| 391 | sub get_cache { | ||||||
| 392 | 0 | 0 | 0 | my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_; | |||
| 393 | 0 | my @cache_key_args = @_; | |||||
| 394 | |||||||
| 395 | # A first-level cache: | ||||||
| 396 | # Don't bother reading the cache files if they still apply | ||||||
| 397 | # and haven't changed since we last read them. | ||||||
| 398 | |||||||
| 399 | 0 | my $this_cache_key = cache_key(@cache_key_args); | |||||
| 400 | |||||||
| 401 | 0 | 0 | 0 | return if $saved_cache_key and $this_cache_key eq $saved_cache_key; | |||
| 402 | |||||||
| 403 | # load the cache of %pages and %items if possible. $tests will be | ||||||
| 404 | # non-zero if successful. | ||||||
| 405 | 0 | my $tests = 0; | |||||
| 406 | 0 | 0 | 0 | if (-f $dircache && -f $itemcache) { | |||
| 407 | 0 | 0 | warn "scanning for item cache\n" if $verbose; | ||||
| 408 | 0 | $tests = load_cache($dircache, $itemcache, $podpath, $podroot); | |||||
| 409 | } | ||||||
| 410 | |||||||
| 411 | # if we didn't succeed in loading the cache then we must (re)build | ||||||
| 412 | # %pages and %items. | ||||||
| 413 | 0 | 0 | if (!$tests) { | ||||
| 414 | 0 | 0 | warn "scanning directories in pod-path\n" if $verbose; | ||||
| 415 | 0 | scan_podpath($podroot, $recurse, 0); | |||||
| 416 | } | ||||||
| 417 | 0 | $saved_cache_key = cache_key(@cache_key_args); | |||||
| 418 | } | ||||||
| 419 | |||||||
| 420 | sub cache_key { | ||||||
| 421 | 0 | 0 | 0 | my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_; | |||
| 422 | 0 | return join('!', $dircache, $itemcache, $recurse, | |||||
| 423 | @$podpath, $podroot, stat($dircache), stat($itemcache)); | ||||||
| 424 | } | ||||||
| 425 | |||||||
| 426 | # | ||||||
| 427 | # load_cache - tries to find if the caches stored in $dircache and $itemcache | ||||||
| 428 | # are valid caches of %pages and %items. if they are valid then it loads | ||||||
| 429 | # them and returns a non-zero value. | ||||||
| 430 | # | ||||||
| 431 | |||||||
| 432 | sub load_cache { | ||||||
| 433 | 0 | 0 | 0 | my($dircache, $itemcache, $podpath, $podroot) = @_; | |||
| 434 | 0 | my($tests); | |||||
| 435 | 0 | local $_; | |||||
| 436 | |||||||
| 437 | 0 | $tests = 0; | |||||
| 438 | |||||||
| 439 | 0 | 0 | open(CACHE, "<$itemcache") || | ||||
| 440 | die "$0: error opening $itemcache for reading: $!\n"; | ||||||
| 441 | 0 | $/ = "\n"; | |||||
| 442 | |||||||
| 443 | # is it the same podpath? | ||||||
| 444 | 0 | $_ = |
|||||
| 445 | 0 | chomp($_); | |||||
| 446 | 0 | 0 | $tests++ if (join(":", @$podpath) eq $_); | ||||
| 447 | |||||||
| 448 | # is it the same podroot? | ||||||
| 449 | 0 | $_ = |
|||||
| 450 | 0 | chomp($_); | |||||
| 451 | 0 | 0 | $tests++ if ($podroot eq $_); | ||||
| 452 | |||||||
| 453 | # load the cache if its good | ||||||
| 454 | 0 | 0 | if ($tests != 2) { | ||||
| 455 | 0 | close(CACHE); | |||||
| 456 | 0 | return 0; | |||||
| 457 | } | ||||||
| 458 | |||||||
| 459 | 0 | 0 | warn "loading item cache\n" if $verbose; | ||||
| 460 | 0 | while ( |
|||||
| 461 | 0 | /(.*?) (.*)$/; | |||||
| 462 | 0 | $items{$1} = $2; | |||||
| 463 | } | ||||||
| 464 | 0 | close(CACHE); | |||||
| 465 | |||||||
| 466 | 0 | 0 | warn "scanning for directory cache\n" if $verbose; | ||||
| 467 | 0 | 0 | open(CACHE, "<$dircache") || | ||||
| 468 | die "$0: error opening $dircache for reading: $!\n"; | ||||||
| 469 | 0 | $/ = "\n"; | |||||
| 470 | 0 | $tests = 0; | |||||
| 471 | |||||||
| 472 | # is it the same podpath? | ||||||
| 473 | 0 | $_ = |
|||||
| 474 | 0 | chomp($_); | |||||
| 475 | 0 | 0 | $tests++ if (join(":", @$podpath) eq $_); | ||||
| 476 | |||||||
| 477 | # is it the same podroot? | ||||||
| 478 | 0 | $_ = |
|||||
| 479 | 0 | chomp($_); | |||||
| 480 | 0 | 0 | $tests++ if ($podroot eq $_); | ||||
| 481 | |||||||
| 482 | # load the cache if its good | ||||||
| 483 | 0 | 0 | if ($tests != 2) { | ||||
| 484 | 0 | close(CACHE); | |||||
| 485 | 0 | return 0; | |||||
| 486 | } | ||||||
| 487 | |||||||
| 488 | 0 | 0 | warn "loading directory cache\n" if $verbose; | ||||
| 489 | 0 | while ( |
|||||
| 490 | 0 | /(.*?) (.*)$/; | |||||
| 491 | 0 | $pages{$1} = $2; | |||||
| 492 | } | ||||||
| 493 | |||||||
| 494 | 0 | close(CACHE); | |||||
| 495 | |||||||
| 496 | 0 | return 1; | |||||
| 497 | } | ||||||
| 498 | |||||||
| 499 | # | ||||||
| 500 | # scan_podpath - scans the directories specified in @podpath for directories, | ||||||
| 501 | # .pod files, and .pm files. it also scans the pod files specified in | ||||||
| 502 | # @libpods for =item directives. | ||||||
| 503 | # | ||||||
| 504 | sub scan_podpath { | ||||||
| 505 | 0 | 0 | 0 | my($podroot, $recurse, $append) = @_; | |||
| 506 | 0 | my($pwd, $dir); | |||||
| 507 | 0 | my($libpod, $dirname, $pod, @files, @poddata); | |||||
| 508 | |||||||
| 509 | 0 | 0 | unless($append) { | ||||
| 510 | 0 | %items = (); | |||||
| 511 | 0 | %pages = (); | |||||
| 512 | } | ||||||
| 513 | |||||||
| 514 | # scan each directory listed in @podpath | ||||||
| 515 | 0 | $pwd = getcwd(); | |||||
| 516 | 0 | 0 | chdir($podroot) | ||||
| 517 | || die "$0: error changing to directory $podroot: $!\n"; | ||||||
| 518 | 0 | foreach $dir (@podpath) { | |||||
| 519 | 0 | scan_dir($dir, $recurse); | |||||
| 520 | } | ||||||
| 521 | |||||||
| 522 | # scan the pods listed in @libpods for =item directives | ||||||
| 523 | 0 | foreach $libpod (@libpods) { | |||||
| 524 | # if the page isn't defined then we won't know where to find it | ||||||
| 525 | # on the system. | ||||||
| 526 | 0 | 0 | 0 | next unless defined $pages{$libpod} && $pages{$libpod}; | |||
| 527 | |||||||
| 528 | # if there is a directory then use the .pod and .pm files within it. | ||||||
| 529 | 0 | 0 | 0 | if ($pages{$libpod} =~ /([^:]*[^(\.pod|\.pm)]):/) { | |||
| 0 | |||||||
| 530 | # find all the .pod and .pm files within the directory | ||||||
| 531 | 0 | $dirname = $1; | |||||
| 532 | 0 | 0 | opendir(DIR, $dirname) || | ||||
| 533 | die "$0: error opening directory $dirname: $!\n"; | ||||||
| 534 | 0 | 0 | @files = grep(/(\.pod|\.pm)$/ && ! -d $_, readdir(DIR)); | ||||
| 535 | 0 | closedir(DIR); | |||||
| 536 | |||||||
| 537 | # scan each .pod and .pm file for =item directives | ||||||
| 538 | 0 | foreach $pod (@files) { | |||||
| 539 | 0 | 0 | open(POD, "<$dirname/$pod") || | ||||
| 540 | die "$0: error opening $dirname/$pod for input: $!\n"; | ||||||
| 541 | 0 | @poddata = |
|||||
| 542 | 0 | close(POD); | |||||
| 543 | |||||||
| 544 | 0 | scan_items("$dirname/$pod", @poddata); | |||||
| 545 | } | ||||||
| 546 | |||||||
| 547 | # use the names of files as =item directives too. | ||||||
| 548 | 0 | foreach $pod (@files) { | |||||
| 549 | 0 | $pod =~ /^(.*)(\.pod|\.pm)$/; | |||||
| 550 | 0 | 0 | $items{$1} = "$dirname/$1.html" if $1; | ||||
| 551 | } | ||||||
| 552 | } elsif ($pages{$libpod} =~ /([^:]*\.pod):/ || | ||||||
| 553 | $pages{$libpod} =~ /([^:]*\.pm):/) { | ||||||
| 554 | # scan the .pod or .pm file for =item directives | ||||||
| 555 | 0 | $pod = $1; | |||||
| 556 | 0 | 0 | open(POD, "<$pod") || | ||||
| 557 | die "$0: error opening $pod for input: $!\n"; | ||||||
| 558 | 0 | @poddata = |
|||||
| 559 | 0 | close(POD); | |||||
| 560 | |||||||
| 561 | 0 | scan_items("$pod", @poddata); | |||||
| 562 | } else { | ||||||
| 563 | 0 | warn "$0: shouldn't be here (line ".__LINE__."\n"; | |||||
| 564 | } | ||||||
| 565 | } | ||||||
| 566 | 0 | @poddata = (); # clean-up a bit | |||||
| 567 | |||||||
| 568 | 0 | 0 | chdir($pwd) | ||||
| 569 | || die "$0: error changing to directory $pwd: $!\n"; | ||||||
| 570 | |||||||
| 571 | # cache the item list for later use | ||||||
| 572 | 0 | 0 | warn "caching items for later use\n" if $verbose; | ||||
| 573 | 0 | 0 | open(CACHE, ">$itemcache") || | ||||
| 574 | die "$0: error open $itemcache for writing: $!\n"; | ||||||
| 575 | |||||||
| 576 | 0 | print CACHE join(":", @podpath) . "\n$podroot\n"; | |||||
| 577 | 0 | foreach my $key (keys %items) { | |||||
| 578 | 0 | print CACHE "$key $items{$key}\n"; | |||||
| 579 | } | ||||||
| 580 | |||||||
| 581 | 0 | close(CACHE); | |||||
| 582 | |||||||
| 583 | # cache the directory list for later use | ||||||
| 584 | 0 | 0 | warn "caching directories for later use\n" if $verbose; | ||||
| 585 | 0 | 0 | open(CACHE, ">$dircache") || | ||||
| 586 | die "$0: error open $dircache for writing: $!\n"; | ||||||
| 587 | |||||||
| 588 | 0 | print CACHE join(":", @podpath) . "\n$podroot\n"; | |||||
| 589 | 0 | foreach my $key (keys %pages) { | |||||
| 590 | 0 | print CACHE "$key $pages{$key}\n"; | |||||
| 591 | } | ||||||
| 592 | |||||||
| 593 | 0 | close(CACHE); | |||||
| 594 | } | ||||||
| 595 | |||||||
| 596 | # | ||||||
| 597 | # scan_dir - scans the directory specified in $dir for subdirectories, .pod | ||||||
| 598 | # files, and .pm files. notes those that it finds. this information will | ||||||
| 599 | # be used later in order to figure out where the pages specified in L<> | ||||||
| 600 | # links are on the filesystem. | ||||||
| 601 | # | ||||||
| 602 | sub scan_dir { | ||||||
| 603 | 0 | 0 | 0 | my($dir, $recurse) = @_; | |||
| 604 | 0 | my($t, @subdirs, @pods, $pod, $dirname, @dirs); | |||||
| 605 | 0 | local $_; | |||||
| 606 | |||||||
| 607 | 0 | @subdirs = (); | |||||
| 608 | 0 | @pods = (); | |||||
| 609 | |||||||
| 610 | 0 | 0 | opendir(DIR, $dir) || | ||||
| 611 | die "$0: error opening directory $dir: $!\n"; | ||||||
| 612 | 0 | while (defined($_ = readdir(DIR))) { | |||||
| 613 | 0 | 0 | 0 | if (-d "$dir/$_" && $_ ne "." && $_ ne "..") { # directory | |||
| 0 | 0 | ||||||
| 0 | |||||||
| 614 | 0 | 0 | $pages{$_} = "" unless defined $pages{$_}; | ||||
| 615 | 0 | $pages{$_} .= "$dir/$_:"; | |||||
| 616 | 0 | push(@subdirs, $_); | |||||
| 617 | } elsif (/\.pod$/) { # .pod | ||||||
| 618 | 0 | s/\.pod$//; | |||||
| 619 | 0 | 0 | $pages{$_} = "" unless defined $pages{$_}; | ||||
| 620 | 0 | $pages{$_} .= "$dir/$_.pod:"; | |||||
| 621 | 0 | push(@pods, "$dir/$_.pod"); | |||||
| 622 | } elsif (/\.pm$/) { # .pm | ||||||
| 623 | 0 | s/\.pm$//; | |||||
| 624 | 0 | 0 | $pages{$_} = "" unless defined $pages{$_}; | ||||
| 625 | 0 | $pages{$_} .= "$dir/$_.pm:"; | |||||
| 626 | 0 | push(@pods, "$dir/$_.pm"); | |||||
| 627 | } | ||||||
| 628 | } | ||||||
| 629 | 0 | closedir(DIR); | |||||
| 630 | |||||||
| 631 | # recurse on the subdirectories if necessary | ||||||
| 632 | 0 | 0 | if ($recurse) { | ||||
| 633 | 0 | foreach my $subdir (@subdirs) { | |||||
| 634 | 0 | scan_dir("$dir/$subdir", $recurse); | |||||
| 635 | } | ||||||
| 636 | } | ||||||
| 637 | } | ||||||
| 638 | |||||||
| 639 | # | ||||||
| 640 | # scan_headings - scan a pod file for head[1-6] tags, note the tags, and | ||||||
| 641 | # build an index. | ||||||
| 642 | # | ||||||
| 643 | sub scan_headings { | ||||||
| 644 | 0 | 0 | 0 | my($sections, @data) = @_; | |||
| 645 | 0 | my($tag, $which_head, $title, $listdepth, $index); | |||||
| 646 | |||||||
| 647 | # here we need local $ignore = 0; | ||||||
| 648 | # unfortunately, we can't have it, because $ignore is lexical | ||||||
| 649 | 0 | $ignore = 0; | |||||
| 650 | |||||||
| 651 | 0 | $listdepth = 0; | |||||
| 652 | 0 | $index = ""; | |||||
| 653 | |||||||
| 654 | # scan for =head directives, note their name, and build an index | ||||||
| 655 | # pointing to each of them. | ||||||
| 656 | 0 | foreach my $line (@data) { | |||||
| 657 | 0 | 0 | if ($line =~ /^=(head)([1-6])\s+(.*)/) { | ||||
| 658 | 0 | ($tag,$which_head, $title) = ($1,$2,$3); | |||||
| 659 | 0 | chomp($title); | |||||
| 660 | 0 | $$sections{htmlify(0,$title)} = 1; | |||||
| 661 | |||||||
| 662 | 0 | while ($which_head != $listdepth) { | |||||
| 663 | 0 | 0 | if ($which_head > $listdepth) { | ||||
| 0 | |||||||
| 664 | 0 | $index .= "\n" . ("\t" x $listdepth) . "
|
|||||
| 665 | 0 | $listdepth++; | |||||
| 666 | } elsif ($which_head < $listdepth) { | ||||||
| 667 | 0 | $listdepth--; | |||||
| 668 | 0 | $index .= "\n" . ("\t" x $listdepth) . "\n"; | |||||
| 669 | } | ||||||
| 670 | } | ||||||
| 671 | |||||||
| 672 | # DTG *** Added after the to close the list item | ||||||
| 673 | 0 | $index .= "\n" . ("\t" x $listdepth) . " |
|||||
| 674 | "" . | ||||||
| 675 | html_escape(process_text(\$title, 0)) . ""; | ||||||
| 676 | } | ||||||
| 677 | } | ||||||
| 678 | |||||||
| 679 | # finish off the lists | ||||||
| 680 | 0 | while ($listdepth--) { | |||||
| 681 | 0 | $index .= "\n" . ("\t" x $listdepth) . "\n"; | |||||
| 682 | } | ||||||
| 683 | |||||||
| 684 | # get rid of bogus lists | ||||||
| 685 | 0 | $index =~ s,\t*
|
|||||
| 686 | |||||||
| 687 | 0 | $ignore = 1; # restore old value; | |||||
| 688 | |||||||
| 689 | 0 | return $index; | |||||
| 690 | } | ||||||
| 691 | |||||||
| 692 | # | ||||||
| 693 | # scan_items - scans the pod specified by $pod for =item directives. we | ||||||
| 694 | # will use this information later on in resolving C<> links. | ||||||
| 695 | # | ||||||
| 696 | sub scan_items { | ||||||
| 697 | 0 | 0 | 0 | my($pod, @poddata) = @_; | |||
| 698 | 0 | my($i, $item); | |||||
| 699 | 0 | local $_; | |||||
| 700 | |||||||
| 701 | 0 | $pod =~ s/\.pod$//; | |||||
| 702 | 0 | 0 | $pod .= ".html" if $pod; | ||||
| 703 | |||||||
| 704 | 0 | foreach $i (0..$#poddata) { | |||||
| 705 | 0 | $_ = $poddata[$i]; | |||||
| 706 | |||||||
| 707 | # remove any formatting instructions | ||||||
| 708 | 0 | s,[A-Z]<([^<>]*)>,$1,g; | |||||
| 709 | |||||||
| 710 | # figure out what kind of item it is and get the first word of | ||||||
| 711 | # it's name. | ||||||
| 712 | 0 | 0 | if (/^=item\s+(\w*)\s*.*$/s) { | ||||
| 713 | 0 | 0 | if ($1 eq "*") { # bullet list | ||||
| 0 | |||||||
| 714 | 0 | /\A=item\s+\*\s*(.*?)\s*\Z/s; | |||||
| 715 | 0 | $item = $1; | |||||
| 716 | } elsif ($1 =~ /^\d+/) { # numbered list | ||||||
| 717 | 0 | /\A=item\s+\d+\.?(.*?)\s*\Z/s; | |||||
| 718 | 0 | $item = $1; | |||||
| 719 | } else { | ||||||
| 720 | # /\A=item\s+(.*?)\s*\Z/s; | ||||||
| 721 | 0 | /\A=item\s+(\w*)/s; | |||||
| 722 | 0 | $item = $1; | |||||
| 723 | } | ||||||
| 724 | |||||||
| 725 | 0 | 0 | $items{$item} = "$pod" if $item; | ||||
| 726 | } | ||||||
| 727 | } | ||||||
| 728 | } | ||||||
| 729 | |||||||
| 730 | # | ||||||
| 731 | # process_head - convert a pod head[1-6] tag and convert it to HTML format. | ||||||
| 732 | # | ||||||
| 733 | sub process_head { | ||||||
| 734 | 0 | 0 | 0 | my($tag, $heading) = @_; | |||
| 735 | 0 | my $firstword; | |||||
| 736 | |||||||
| 737 | # figure out the level of the =head | ||||||
| 738 | 0 | $tag =~ /head([1-6])/; | |||||
| 739 | 0 | my $level = $1 + 1; | |||||
| 740 | |||||||
| 741 | # can't have a heading full of spaces and speechmarks and so on | ||||||
| 742 | 0 | $firstword = $heading; $firstword =~ s/\s*(\w+)\s.*/$1/; | |||||
| 0 | |||||||
| 743 | |||||||
| 744 | #print HTML " \n" unless $listlevel; |
||||||
| 745 | 0 | 0 | 0 | print HTML " \n" unless $listlevel || $top; |
|||
| 746 | 0 | print HTML " |
|||||
| 747 | #print HTML " |
||||||
| 748 | 0 | my $convert = $heading; process_text(\$convert, 0); | |||||
| 0 | |||||||
| 749 | 0 | $convert = html_escape($convert); | |||||
| 750 | 0 | print HTML '$convert"; | |||||
| 751 | 0 | print HTML ""; # unless $listlevel; | |||||
| 752 | 0 | print HTML "\n"; | |||||
| 753 | } | ||||||
| 754 | |||||||
| 755 | # | ||||||
| 756 | # process_item - convert a pod item tag and convert it to HTML format. | ||||||
| 757 | # | ||||||
| 758 | sub process_item { | ||||||
| 759 | 0 | 0 | 0 | my $text = $_[0]; | |||
| 760 | 0 | my($i, $quote, $name); | |||||
| 761 | |||||||
| 762 | 0 | my $need_preamble = 0; | |||||
| 763 | 0 | my $this_entry; | |||||
| 764 | |||||||
| 765 | |||||||
| 766 | # lots of documents start a list without doing an =over. this is | ||||||
| 767 | # bad! but, the proper thing to do seems to be to just assume | ||||||
| 768 | # they did do an =over. so warn them once and then continue. | ||||||
| 769 | 0 | 0 | warn "$0: $podfile: unexpected =item directive in paragraph $paragraph. ignoring.\n" | ||||
| 770 | unless $listlevel; | ||||||
| 771 | 0 | 0 | process_over() unless $listlevel; | ||||
| 772 | |||||||
| 773 | 0 | 0 | return unless $listlevel; | ||||
| 774 | |||||||
| 775 | # remove formatting instructions from the text | ||||||
| 776 | 0 | 1 while $text =~ s/[A-Z]<([^<>]*)>/$1/g; | |||||
| 777 | 0 | pre_escape(\$text); | |||||
| 778 | |||||||
| 779 | 0 | $need_preamble = $items_seen[$listlevel]++ == 0; | |||||
| 780 | |||||||
| 781 | # check if this is the first =item after an =over | ||||||
| 782 | 0 | $i = $listlevel - 1; | |||||
| 783 | 0 | my $need_new = $listlevel >= @listitem; | |||||
| 784 | |||||||
| 785 | 0 | 0 | if ($text =~ /\A\*/) { # bullet | ||||
| 0 | |||||||
| 786 | |||||||
| 787 | 0 | 0 | if ($need_preamble) { | ||||
| 788 | 0 | push(@listend, ""); | |||||
| 789 | 0 | print HTML "
|
|||||
| 790 | } | ||||||
| 791 | |||||||
| 792 | 0 | print HTML ' |
|||||
| 793 | 0 | 0 | if ($text =~ /\A\*\s*(.+)\Z/s) { | ||||
| 794 | 0 | print HTML ''; | |||||
| 795 | 0 | 0 | if ($items_named{$1}++) { | ||||
| 796 | 0 | print HTML html_escape($1); | |||||
| 797 | } else { | ||||||
| 798 | 0 | my $name = 'item_' . htmlify(1,$1); | |||||
| 799 | 0 | print HTML qq(), html_escape($1), ''; | |||||
| 800 | } | ||||||
| 801 | 0 | print HTML ''; | |||||
| 802 | } | ||||||
| 803 | |||||||
| 804 | } elsif ($text =~ /\A[\d#]+/) { # numbered list | ||||||
| 805 | |||||||
| 806 | 0 | 0 | if ($need_preamble) { | ||||
| 807 | 0 | push(@listend, ""); | |||||
| 808 | 0 | print HTML "
|
|||||
| 809 | } | ||||||
| 810 | |||||||
| 811 | 0 | print HTML ' |
|||||
| 812 | 0 | 0 | if ($text =~ /\A\d+\.?\s*(.+)\Z/s) { | ||||
| 813 | 0 | print HTML ''; | |||||
| 814 | 0 | 0 | if ($items_named{$1}++) { | ||||
| 815 | 0 | print HTML html_escape($1); | |||||
| 816 | } else { | ||||||
| 817 | 0 | my $name = 'item_' . htmlify(0,$1); | |||||
| 818 | 0 | print HTML qq(), html_escape($1), ''; | |||||
| 819 | } | ||||||
| 820 | 0 | print HTML ''; | |||||
| 821 | } | ||||||
| 822 | |||||||
| 823 | } else { # all others | ||||||
| 824 | |||||||
| 825 | 0 | 0 | if ($need_preamble) { | ||||
| 826 | 0 | push(@listend, ''); | |||||
| 827 | 0 | print HTML "
|
|||||
| 828 | } | ||||||
| 829 | |||||||
| 830 | 0 | print HTML ' |
|||||
| 831 | 0 | 0 | if ($text =~ /(\S+)/) { | ||||
| 832 | 0 | print HTML ''; | |||||
| 833 | 0 | 0 | if ($items_named{$1}++) { | ||||
| 834 | 0 | print HTML html_escape($text); | |||||
| 835 | } else { | ||||||
| 836 | 0 | my $name = 'item_' . htmlify(1,$text); | |||||
| 837 | 0 | print HTML qq(), html_escape($text), ''; | |||||
| 838 | } | ||||||
| 839 | 0 | print HTML ''; | |||||
| 840 | } | ||||||
| 841 | 0 | print HTML ' |
|||||
| 842 | } | ||||||
| 843 | |||||||
| 844 | 0 | print HTML "\n"; | |||||
| 845 | } | ||||||
| 846 | |||||||
| 847 | # | ||||||
| 848 | # process_over - process a pod over tag and start a corresponding HTML | ||||||
| 849 | # list. | ||||||
| 850 | # | ||||||
| 851 | sub process_over { | ||||||
| 852 | # start a new list | ||||||
| 853 | 0 | 0 | 0 | $listlevel++; | |||
| 854 | } | ||||||
| 855 | |||||||
| 856 | # | ||||||
| 857 | # process_back - process a pod back tag and convert it to HTML format. | ||||||
| 858 | # | ||||||
| 859 | sub process_back { | ||||||
| 860 | 0 | 0 | 0 | 0 | warn "$0: $podfile: unexpected =back directive in paragraph $paragraph. ignoring.\n" | ||
| 861 | unless $listlevel; | ||||||
| 862 | 0 | 0 | return unless $listlevel; | ||||
| 863 | |||||||
| 864 | # close off the list. note, I check to see if $listend[$listlevel] is | ||||||
| 865 | # defined because an =item directive may have never appeared and thus | ||||||
| 866 | # $listend[$listlevel] may have never been initialized. | ||||||
| 867 | 0 | $listlevel--; | |||||
| 868 | 0 | 0 | print HTML $listend[$listlevel] if defined $listend[$listlevel]; | ||||
| 869 | 0 | print HTML "\n"; | |||||
| 870 | |||||||
| 871 | # don't need the corresponding perl code anymore | ||||||
| 872 | 0 | pop(@listitem); | |||||
| 873 | 0 | pop(@listdata); | |||||
| 874 | 0 | pop(@listend); | |||||
| 875 | |||||||
| 876 | 0 | pop(@items_seen); | |||||
| 877 | } | ||||||
| 878 | |||||||
| 879 | # | ||||||
| 880 | # process_cut - process a pod cut tag, thus stop ignoring pod directives. | ||||||
| 881 | # | ||||||
| 882 | sub process_cut { | ||||||
| 883 | 0 | 0 | 0 | $ignore = 1; | |||
| 884 | } | ||||||
| 885 | |||||||
| 886 | # | ||||||
| 887 | # process_pod - process a pod pod tag, thus ignore pod directives until we see a | ||||||
| 888 | # corresponding cut. | ||||||
| 889 | # | ||||||
| 890 | 0 | 0 | 0 | sub process_pod { | |||
| 891 | # no need to set $ignore to 0 cause the main loop did it | ||||||
| 892 | } | ||||||
| 893 | |||||||
| 894 | # | ||||||
| 895 | # process_for - process a =for pod tag. if it's for html, split | ||||||
| 896 | # it out verbatim, if illustration, center it, otherwise ignore it. | ||||||
| 897 | # | ||||||
| 898 | sub process_for { | ||||||
| 899 | 0 | 0 | 0 | my($whom, $text) = @_; | |||
| 900 | 0 | 0 | if ( $whom =~ /^(pod2)?html$/i) { | ||||
| 0 | |||||||
| 901 | 0 | print HTML $text; | |||||
| 902 | } elsif ($whom =~ /^illustration$/i) { | ||||||
| 903 | 0 | 1 while chomp $text; | |||||
| 904 | 0 | for my $ext (qw[.png .gif .jpeg .jpg .tga .pcl .bmp]) { | |||||
| 905 | 0 | 0 | $text .= $ext, last if -r "$text$ext"; | ||||
| 906 | } | ||||||
| 907 | 0 | print HTML qq{ |
|||||
| 908 | } | ||||||
| 909 | } | ||||||
| 910 | |||||||
| 911 | # | ||||||
| 912 | # process_begin - process a =begin pod tag. this pushes | ||||||
| 913 | # whom we're beginning on the begin stack. if there's a | ||||||
| 914 | # begin stack, we only print if it us. | ||||||
| 915 | # | ||||||
| 916 | sub process_begin { | ||||||
| 917 | 0 | 0 | 0 | my($whom, $text) = @_; | |||
| 918 | 0 | $whom = lc($whom); | |||||
| 919 | 0 | push (@begin_stack, $whom); | |||||
| 920 | 0 | 0 | if ( $whom =~ /^(pod2)?html$/) { | ||||
| 921 | 0 | 0 | print HTML $text if $text; | ||||
| 922 | } | ||||||
| 923 | } | ||||||
| 924 | |||||||
| 925 | # | ||||||
| 926 | # process_end - process a =end pod tag. pop the | ||||||
| 927 | # begin stack. die if we're mismatched. | ||||||
| 928 | # | ||||||
| 929 | sub process_end { | ||||||
| 930 | 0 | 0 | 0 | my($whom, $text) = @_; | |||
| 931 | 0 | $whom = lc($whom); | |||||
| 932 | 0 | 0 | if ($begin_stack[-1] ne $whom ) { | ||||
| 933 | 0 | die "$0: $podfile: Unmatched begin/end at chunk $paragraph\n" | |||||
| 934 | } | ||||||
| 935 | 0 | pop @begin_stack; | |||||
| 936 | } | ||||||
| 937 | |||||||
| 938 | # | ||||||
| 939 | # process_text - handles plaintext that appears in the input pod file. | ||||||
| 940 | # there may be pod commands embedded within the text so those must be | ||||||
| 941 | # converted to html commands. | ||||||
| 942 | # | ||||||
| 943 | sub process_text { | ||||||
| 944 | 0 | 0 | 0 | my($text, $escapeQuotes) = @_; | |||
| 945 | 0 | my($result, $rest, $s1, $s2, $s3, $s4, $match, $bf); | |||||
| 946 | 0 | my($podcommand, $params, $tag, $quote); | |||||
| 947 | 0 | $htmlroot =~ s|/$||; | |||||
| 948 | |||||||
| 949 | 0 | 0 | return if $ignore; | ||||
| 950 | |||||||
| 951 | 0 | $quote = 0; # status of double-quote conversion | |||||
| 952 | 0 | $result = ""; | |||||
| 953 | 0 | $rest = $$text; | |||||
| 954 | |||||||
| 955 | 0 | 0 | if ($rest =~ /^\s+/) { # preformatted text, no pod directives | ||||
| 956 | 0 | $rest =~ s/\n+\Z//; | |||||
| 957 | 0 | $rest =~ s#.*# | |||||
| 958 | 0 | my $line = $&; | |||||
| 959 | 0 | 1 while $line =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; | |||||
| 0 | |||||||
| 960 | 0 | $line; | |||||
| 961 | #eg; | ||||||
| 962 | |||||||
| 963 | 0 | $rest =~ s/&/&/g; | |||||
| 964 | 0 | $rest =~ s/</g; | |||||
| 965 | 0 | $rest =~ s/>/>/g; | |||||
| 966 | 0 | $rest =~ s/"/"/g; | |||||
| 967 | |||||||
| 968 | # try and create links for all occurrences of perl.* within | ||||||
| 969 | # the preformatted text. | ||||||
| 970 | 0 | $rest =~ s{ | |||||
| 971 | (\s*)(perl\w+) | ||||||
| 972 | }{ | ||||||
| 973 | 0 | 0 | if (defined $pages{$2}) { # is a link | ||||
| 0 | |||||||
| 974 | 0 | qq($1$2); | |||||
| 975 | } elsif (defined $pages{dosify($2)}) { # is a link | ||||||
| 976 | 0 | qq($1$2); | |||||
| 977 | } else { | ||||||
| 978 | 0 | "$1$2"; | |||||
| 979 | } | ||||||
| 980 | }xeg; | ||||||
| 981 | 0 | $rest =~ s/(:]*:)?([^>:]*)\.pod:([^>:]*:)?/$1$3.html/g; | |||||
| 982 | |||||||
| 983 | 0 | my $urls = '(' . join ('|', qw{ | |||||
| 984 | http | ||||||
| 985 | telnet | ||||||
| 986 | mailto | ||||||
| 987 | news | ||||||
| 988 | gopher | ||||||
| 989 | file | ||||||
| 990 | wais | ||||||
| 991 | ftp | ||||||
| 992 | } ) | ||||||
| 993 | . ')'; | ||||||
| 994 | |||||||
| 995 | 0 | my $ltrs = '\w'; | |||||
| 996 | 0 | my $gunk = '/#~:.?+=&%@!\-'; | |||||
| 997 | 0 | my $punc = '.:?\-'; | |||||
| 998 | 0 | my $any = "${ltrs}${gunk}${punc}"; | |||||
| 999 | |||||||
| 1000 | 0 | $rest =~ s{ | |||||
| 1001 | \b # start at word boundary | ||||||
| 1002 | ( # begin $1 { | ||||||
| 1003 | $urls : # need resource and a colon | ||||||
| 1004 | [$any] +? # followed by on or more | ||||||
| 1005 | # of any valid character, but | ||||||
| 1006 | # be conservative and take only | ||||||
| 1007 | # what you need to.... | ||||||
| 1008 | ) # end $1 } | ||||||
| 1009 | (?= # look-ahead non-consumptive assertion | ||||||
| 1010 | [$punc]* # either 0 or more puntuation | ||||||
| 1011 | [^$any] # followed by a non-url char | ||||||
| 1012 | | # or else | ||||||
| 1013 | $ # then end of the string | ||||||
| 1014 | ) | ||||||
| 1015 | }{$1}igox; | ||||||
| 1016 | |||||||
| 1017 | 0 | $result = "" # text should be as it is (verbatim) |
|||||
| 1018 | . "$rest\n" | ||||||
| 1019 | . "\n"; | ||||||
| 1020 | } else { # formatted text | ||||||
| 1021 | # parse through the string, stopping each time we find a | ||||||
| 1022 | # pod-escape. once the string has been throughly processed | ||||||
| 1023 | # we can output it. | ||||||
| 1024 | |||||||
| 1025 | 0 | while (length $rest) { | |||||
| 1026 | # check to see if there are any possible pod directives in | ||||||
| 1027 | # the remaining part of the text. | ||||||
| 1028 | |||||||
| 1029 | 0 | 0 | if ($rest =~ m/[BCEIFLSZ]) { | ||||
| 1030 | 0 | 0 | warn "\$rest\t= $rest\n" unless | ||||
| 1031 | $rest =~ /\A | ||||||
| 1032 | ([^<]*?) | ||||||
| 1033 | ([BCEIFLSZ]?) | ||||||
| 1034 | < | ||||||
| 1035 | (.*)\Z/xs; | ||||||
| 1036 | |||||||
| 1037 | 0 | $s1 = $1; # pure text | |||||
| 1038 | 0 | $s2 = $2; # the type of pod-escape that follows | |||||
| 1039 | 0 | $s3 = '<'; # '<' | |||||
| 1040 | 0 | $s4 = $3; # the rest of the string | |||||
| 1041 | } else { | ||||||
| 1042 | 0 | $s1 = $rest; | |||||
| 1043 | 0 | $s2 = ""; | |||||
| 1044 | 0 | $s3 = ""; | |||||
| 1045 | 0 | $s4 = ""; | |||||
| 1046 | } | ||||||
| 1047 | |||||||
| 1048 | 0 | 0 | 0 | if ($s3 eq '<' && $s2) { # a pod-escape | |||
| 1049 | 0 | 0 | $result .= ($escapeQuotes ? process_puretext($s1, \$quote) : $s1); | ||||
| 1050 | 0 | $podcommand = "$s2<"; | |||||
| 1051 | 0 | $rest = $s4; | |||||
| 1052 | |||||||
| 1053 | # find the matching '>' | ||||||
| 1054 | 0 | $match = 1; | |||||
| 1055 | 0 | $bf = 0; | |||||
| 1056 | 0 | 0 | while ($match && !$bf) { | ||||
| 1057 | 0 | $bf = 1; | |||||
| 1058 | 0 | 0 | if ($rest =~ /\A([^<>]*[BCEIFLSZ]<)(.*)\Z/s) { | ||||
| 0 | |||||||
| 1059 | 0 | $bf = 0; | |||||
| 1060 | 0 | $match++; | |||||
| 1061 | 0 | $podcommand .= $1; | |||||
| 1062 | 0 | $rest = $2; | |||||
| 1063 | } elsif ($rest =~ /\A([^>]*>)(.*)\Z/s) { | ||||||
| 1064 | 0 | $bf = 0; | |||||
| 1065 | 0 | $match--; | |||||
| 1066 | 0 | $podcommand .= $1; | |||||
| 1067 | 0 | $rest = $2; | |||||
| 1068 | } | ||||||
| 1069 | } | ||||||
| 1070 | |||||||
| 1071 | 0 | 0 | if ($match != 0) { | ||||
| 1072 | 0 | warn < | |||||
| 1073 | $0: $podfile: cannot find matching > for $s2 in paragraph $paragraph. | ||||||
| 1074 | WARN | ||||||
| 1075 | 0 | $result .= substr $podcommand, 0, 2; | |||||
| 1076 | 0 | $rest = substr($podcommand, 2) . $rest; | |||||
| 1077 | 0 | next; | |||||
| 1078 | } | ||||||
| 1079 | |||||||
| 1080 | # pull out the parameters to the pod-escape | ||||||
| 1081 | 0 | $podcommand =~ /^([BCFEILSZ]?)<(.*)>$/s; | |||||
| 1082 | 0 | $tag = $1; | |||||
| 1083 | 0 | $params = $2; | |||||
| 1084 | |||||||
| 1085 | # process the text within the pod-escape so that any escapes | ||||||
| 1086 | # which must occur do. | ||||||
| 1087 | 0 | 0 | process_text(\$params, 0) unless $tag eq 'L'; | ||||
| 1088 | |||||||
| 1089 | 0 | $s1 = $params; | |||||
| 1090 | 0 | 0 | 0 | if (!$tag || $tag eq " ") { # <> : no tag | |||
| 0 | 0 | ||||||
| 0 | 0 | ||||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 1091 | 0 | $s1 = "<$params>"; | |||||
| 1092 | } elsif ($tag eq "L") { # L<> : link | ||||||
| 1093 | 0 | $s1 = process_L($params); | |||||
| 1094 | } elsif ($tag eq "I" || # I<> : italicize text | ||||||
| 1095 | $tag eq "B" || # B<> : bold text | ||||||
| 1096 | $tag eq "F") { # F<> : file specification | ||||||
| 1097 | 0 | $s1 = process_BFI($tag, $params); | |||||
| 1098 | } elsif ($tag eq "C") { # C<> : literal code | ||||||
| 1099 | 0 | $s1 = process_C($params, 1); | |||||
| 1100 | } elsif ($tag eq "E") { # E<> : escape | ||||||
| 1101 | 0 | $s1 = process_E($params); | |||||
| 1102 | } elsif ($tag eq "Z") { # Z<> : zero-width character | ||||||
| 1103 | 0 | $s1 = process_Z($params); | |||||
| 1104 | } elsif ($tag eq "S") { # S<> : non-breaking space | ||||||
| 1105 | 0 | $s1 = process_S($params); | |||||
| 1106 | } elsif ($tag eq "X") { # S<> : non-breaking space | ||||||
| 1107 | 0 | $s1 = process_X($params); | |||||
| 1108 | } else { | ||||||
| 1109 | 0 | warn "$0: $podfile: unhandled tag '$tag' in paragraph $paragraph\n"; | |||||
| 1110 | } | ||||||
| 1111 | |||||||
| 1112 | 0 | $result .= "$s1"; | |||||
| 1113 | } else { | ||||||
| 1114 | # for pure text we must deal with implicit links and | ||||||
| 1115 | # double-quotes among other things. | ||||||
| 1116 | 0 | 0 | $result .= ( | ||||
| 1117 | $escapeQuotes ? process_puretext("$s1$s2$s3", \$quote) : "$s1$s2$s3" | ||||||
| 1118 | ); | ||||||
| 1119 | 0 | $rest = $s4; | |||||
| 1120 | } | ||||||
| 1121 | } | ||||||
| 1122 | } | ||||||
| 1123 | 0 | $$text = $result; | |||||
| 1124 | } | ||||||
| 1125 | |||||||
| 1126 | sub html_escape { | ||||||
| 1127 | 0 | 0 | 0 | my $rest = $_[0]; | |||
| 1128 | 0 | $rest =~ s/&/&/g; | |||||
| 1129 | 0 | $rest =~ s/</g; | |||||
| 1130 | 0 | $rest =~ s/>/>/g; | |||||
| 1131 | 0 | $rest =~ s/"/"/g; | |||||
| 1132 | 0 | return $rest; | |||||
| 1133 | } | ||||||
| 1134 | |||||||
| 1135 | # | ||||||
| 1136 | # process_puretext - process pure text (without pod-escapes) converting | ||||||
| 1137 | # double-quotes and handling implicit C<> links. | ||||||
| 1138 | # | ||||||
| 1139 | sub process_puretext { | ||||||
| 1140 | 0 | 0 | 0 | my($text, $quote) = @_; | |||
| 1141 | 0 | my(@words, $result, $rest, $lead, $trail); | |||||
| 1142 | |||||||
| 1143 | # convert double-quotes to single-quotes | ||||||
| 1144 | 0 | 0 | $text =~ s/\A([^"]*)"/$1''/s if $$quote; | ||||
| 1145 | 0 | while ($text =~ s/\A([^"]*)["]([^"]*)["]/$1``$2''/sg) {} | |||||
| 1146 | |||||||
| 1147 | 0 | 0 | $$quote = ($text =~ m/"/ ? 1 : 0); | ||||
| 1148 | 0 | 0 | $text =~ s/\A([^"]*)"/$1``/s if $$quote; | ||||
| 1149 | |||||||
| 1150 | # keep track of leading and trailing white-space | ||||||
| 1151 | 0 | 0 | $lead = ($text =~ /\A(\s*)/s ? $1 : ""); | ||||
| 1152 | 0 | 0 | $trail = ($text =~ /(\s*)\Z/s ? $1 : ""); | ||||
| 1153 | |||||||
| 1154 | # collapse all white space into a single space | ||||||
| 1155 | 0 | $text =~ s/\s+/ /g; | |||||
| 1156 | 0 | @words = split(" ", $text); | |||||
| 1157 | |||||||
| 1158 | # process each word individually | ||||||
| 1159 | 0 | foreach my $word (@words) { | |||||
| 1160 | # see if we can infer a link | ||||||
| 1161 | |||||||
| 1162 | 0 | 0 | 0 | if ($word =~ /^\w+\(/) { | |||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 1163 | # has parenthesis so should have been a C<> ref | ||||||
| 1164 | |||||||
| 1165 | 0 | $word = process_C($word); | |||||
| 1166 | |||||||
| 1167 | # $word =~ /^[^()]*]\(/; | ||||||
| 1168 | # if (defined $items{$1} && $items{$1}) { | ||||||
| 1169 | # $word = "\n
| ||||||
| 1170 | # . htmlify(0,$word) | ||||||
| 1171 | # . "\">$word"; | ||||||
| 1172 | # } elsif (defined $items{$word} && $items{$word}) { | ||||||
| 1173 | # $word = "\n
| ||||||
| 1174 | # . htmlify(0,$word) | ||||||
| 1175 | # . "\">$word"; | ||||||
| 1176 | # } else { | ||||||
| 1177 | # $word = "\n
| ||||||
| 1178 | # . htmlify(0,$word) | ||||||
| 1179 | # . "\">$word"; | ||||||
| 1180 | # } | ||||||
| 1181 | } elsif ($word =~ /^[\$\@%&*]+\w+$/) { | ||||||
| 1182 | # perl variables, should be a C<> ref | ||||||
| 1183 | 0 | $word = process_C($word, 1); | |||||
| 1184 | } elsif ($word =~ m,^\w+://\w,) { | ||||||
| 1185 | # looks like a URL | ||||||
| 1186 | 0 | $word = qq($word); | |||||
| 1187 | } elsif ($word =~ /[\w.-]+\@[\w-]+\.\w/) { | ||||||
| 1188 | # looks like an e-mail address | ||||||
| 1189 | |||||||
| 1190 | 0 | my ($w1, $w2, $w3) = ("", $word, ""); | |||||
| 1191 | 0 | 0 | ($w1, $w2, $w3) = ("(", $1, ")$2") if $word =~ /^\((.*?)\)(,?)/; | ||||
| 1192 | 0 | 0 | ($w1, $w2, $w3) = ("<", $1, ">$2") if $word =~ /^<(.*?)>(,?)/; | ||||
| 1193 | 0 | $word = qq($w1$w2$w3); | |||||
| 1194 | } elsif ($word !~ /[a-z]/ && $word =~ /[A-Z]/) { # all uppercase? | ||||||
| 1195 | 0 | 0 | $word = html_escape($word) if $word =~ /["&<>]/; | ||||
| 1196 | 0 | 0 | $word = "\n$word" if $netscape; | ||||
| 1197 | } else { | ||||||
| 1198 | 0 | 0 | $word = html_escape($word) if $word =~ /["&<>]/; | ||||
| 1199 | } | ||||||
| 1200 | } | ||||||
| 1201 | |||||||
| 1202 | # build a new string based upon our conversion | ||||||
| 1203 | 0 | $result = ""; | |||||
| 1204 | 0 | $rest = join(" ", @words); | |||||
| 1205 | 0 | while (length($rest) > 75) { | |||||
| 1206 | 0 | 0 | 0 | if ( $rest =~ m/^(.{0,75})\s(.*?)$/o || | |||
| 1207 | $rest =~ m/^(\S*)\s(.*?)$/o) { | ||||||
| 1208 | |||||||
| 1209 | 0 | $result .= "$1\n"; | |||||
| 1210 | 0 | $rest = $2; | |||||
| 1211 | } else { | ||||||
| 1212 | 0 | $result .= "$rest\n"; | |||||
| 1213 | 0 | $rest = ""; | |||||
| 1214 | } | ||||||
| 1215 | } | ||||||
| 1216 | 0 | 0 | $result .= $rest if $rest; | ||||
| 1217 | |||||||
| 1218 | # restore the leading and trailing white-space | ||||||
| 1219 | 0 | $result = "$lead$result$trail"; | |||||
| 1220 | |||||||
| 1221 | 0 | return $result; | |||||
| 1222 | } | ||||||
| 1223 | |||||||
| 1224 | # | ||||||
| 1225 | # pre_escape - convert & in text to $amp; | ||||||
| 1226 | # | ||||||
| 1227 | sub pre_escape { | ||||||
| 1228 | 0 | 0 | 0 | my($str) = @_; | |||
| 1229 | |||||||
| 1230 | 0 | $$str =~ s,&,&,g; | |||||
| 1231 | } | ||||||
| 1232 | |||||||
| 1233 | # | ||||||
| 1234 | # dosify - convert filenames to 8.3 | ||||||
| 1235 | # | ||||||
| 1236 | sub dosify { | ||||||
| 1237 | 0 | 0 | 0 | my($str) = @_; | |||
| 1238 | 0 | 0 | if ($Is83) { | ||||
| 1239 | 0 | $str = lc $str; | |||||
| 1240 | 0 | $str =~ s/(\.\w+)/substr ($1,0,4)/ge; | |||||
| 0 | |||||||
| 1241 | 0 | $str =~ s/(\w+)/substr ($1,0,8)/ge; | |||||
| 0 | |||||||
| 1242 | } | ||||||
| 1243 | 0 | return $str; | |||||
| 1244 | } | ||||||
| 1245 | |||||||
| 1246 | # | ||||||
| 1247 | # process_L - convert a pod L<> directive to a corresponding HTML link. | ||||||
| 1248 | # most of the links made are inferred rather than known about directly | ||||||
| 1249 | # (i.e it's not known whether the =head\d section exists in the target file, | ||||||
| 1250 | # or whether a .pod file exists in the case of split files). however, the | ||||||
| 1251 | # guessing usually works. | ||||||
| 1252 | # | ||||||
| 1253 | # Unlike the other directives, this should be called with an unprocessed | ||||||
| 1254 | # string, else tags in the link won't be matched. | ||||||
| 1255 | # | ||||||
| 1256 | sub process_L { | ||||||
| 1257 | 0 | 0 | 0 | my($str) = @_; | |||
| 1258 | 0 | my($s1, $s2, $linktext, $page, $page83, $section, $link); # work strings | |||||
| 1259 | 0 | my $alternate; | |||||
| 1260 | 0 | my $hyperlink = 0; | |||||
| 1261 | |||||||
| 1262 | 0 | $str =~ s/\n/ /g; # undo word-wrapped tags | |||||
| 1263 | 0 | $s1 = $str; | |||||
| 1264 | 0 | for ($s1) { | |||||
| 1265 | # LREF: a la HREF L |
||||||
| 1266 | 0 | 0 | $linktext = $1 if s:^([^|]+[^\xa0-\xff])\|::; | ||||
| 1267 | 0 | $alternate = ($1 eq $linktext); | |||||
| 1268 | |||||||
| 1269 | # make sure sections start with a / | ||||||
| 1270 | 0 | s,^",/",g; | |||||
| 1271 | 0 | 0 | 0 | s,^,/,g if (!m,/, && / /); | |||
| 1272 | |||||||
| 1273 | # check if there's a section specified | ||||||
| 1274 | 0 | 0 | if (m,^(.*?)/"?(.*?)"?$,) { # yes | ||||
| 1275 | 0 | ($page, $section) = ($1, $2); | |||||
| 1276 | } else { # no | ||||||
| 1277 | 0 | $str =~ s:^[^|]+[^\xa0-\xff]\|::; | |||||
| 1278 | 0 | ($page, $section) = ($str, ""); | |||||
| 1279 | } | ||||||
| 1280 | |||||||
| 1281 | # check if we know that this is a section in this page | ||||||
| 1282 | #if (!defined $pages{$page} && defined $sections{$page}) { | ||||||
| 1283 | # $section = $page; | ||||||
| 1284 | # $page = ""; | ||||||
| 1285 | #} | ||||||
| 1286 | } | ||||||
| 1287 | |||||||
| 1288 | 0 | $page83=dosify($page); | |||||
| 1289 | 0 | 0 | $page=$page83 if (defined $pages{$page83}); | ||||
| 1290 | 0 | 0 | 0 | if ($page eq "") { | |||
| 0 | |||||||
| 0 | |||||||
| 0 | |||||||
| 1291 | 0 | $link = "#" . htmlify(0,$section); | |||||
| 1292 | 0 | 0 | $linktext = $section unless defined($linktext); | ||||
| 1293 | } elsif ( $page =~ /::/ or $page =~ /^\w+$/) { | ||||||
| 1294 | 0 | 0 | $linktext = ($section ? "$section" : "$page") unless $alternate; | ||||
| 0 | |||||||
| 1295 | 0 | $page =~ s,::,/,g; | |||||
| 1296 | 0 | $link = "$htmlroot/$page.html"; | |||||
| 1297 | 0 | 0 | if ($section) { | ||||
| 1298 | # XXX: autrijus | ||||||
| 1299 | 0 | 0 | if ($doindex) { | ||||
| 0 | |||||||
| 1300 | 0 | $link .= "#" . htmlify(0,$section); | |||||
| 1301 | } | ||||||
| 1302 | elsif ($hashead) { | ||||||
| 1303 | 0 | $link = "$page/".htmlify(0, $section).".html"; | |||||
| 1304 | } | ||||||
| 1305 | else { | ||||||
| 1306 | 0 | $link = "../../../$page/".htmlify(0, $section).".html"; | |||||
| 1307 | } | ||||||
| 1308 | } | ||||||
| 1309 | } elsif ($str =~ m{(?:http|ftp|news|telnet|mailto)://}) { | ||||||
| 1310 | 0 | $linktext = $link = $str; | |||||
| 1311 | 0 | 0 | $hyperlink = 1 if $str =~ m{(?:http|ftp)://}; | ||||
| 1312 | } elsif (!defined $pages{$page}) { | ||||||
| 1313 | 0 | warn "$0: $podfile: cannot resolve L<$str> in paragraph $paragraph: no such page '$page'\n"; | |||||
| 1314 | 0 | $link = ""; | |||||
| 1315 | 0 | 0 | $linktext = $page unless defined($linktext); | ||||
| 1316 | } else { | ||||||
| 1317 | 0 | 0 | $linktext = ($section ? "$section" : "the $page manpage") unless defined($linktext); | ||||
| 0 | |||||||
| 1318 | 0 | 0 | $section = htmlify(0,$section) if $section ne ""; | ||||
| 1319 | |||||||
| 1320 | # if there is a directory by the name of the page, then assume that an | ||||||
| 1321 | # appropriate section will exist in the subdirectory | ||||||
| 1322 | 0 | 0 | 0 | if ($section ne "" && $pages{$page} =~ /([^:]*[^(\.pod|\.pm)]):/) { | |||
| 1323 | 0 | $link = "$htmlroot/$1/$section.html"; | |||||
| 1324 | |||||||
| 1325 | # since there is no directory by the name of the page, the section will | ||||||
| 1326 | # have to exist within a .html of the same name. thus, make sure there | ||||||
| 1327 | # is a .pod or .pm that might become that .html | ||||||
| 1328 | } else { | ||||||
| 1329 | 0 | $section = "#$section"; | |||||
| 1330 | # check if there is a .pod with the page name | ||||||
| 1331 | 0 | 0 | if ($pages{$page} =~ /([^:]*)\.pod:/) { | ||||
| 0 | |||||||
| 1332 | 0 | $link = "$htmlroot/$1.html$section"; | |||||
| 1333 | } elsif ($pages{$page} =~ /([^:]*)\.pm:/) { | ||||||
| 1334 | 0 | $link = "$htmlroot/$1.html$section"; | |||||
| 1335 | } else { | ||||||
| 1336 | 0 | warn "$0: $podfile: cannot resolve L$str in paragraph $paragraph: ". | |||||
| 1337 | "no .pod or .pm found\n"; | ||||||
| 1338 | 0 | $link = ""; | |||||
| 1339 | 0 | 0 | $linktext = $section unless defined($linktext); | ||||
| 1340 | } | ||||||
| 1341 | } | ||||||
| 1342 | } | ||||||
| 1343 | |||||||
| 1344 | 0 | $link =~ s|^(?:\./)?(?:\.\./)?\.\./||; # XXX: autrijus | |||||
| 1345 | 0 | 0 | $link = "../$link" if $link =~ m|pod/|; | ||||
| 1346 | |||||||
| 1347 | 0 | process_text(\$linktext, 0); | |||||
| 1348 | 0 | 0 | if ($link) { | ||||
| 1349 | 0 | 0 | if ($hyperlink) { | ||||
| 1350 | 0 | $s1 = "$linktext"; | |||||
| 1351 | } | ||||||
| 1352 | else { | ||||||
| 1353 | 0 | $s1 = "$linktext"; | |||||
| 1354 | } | ||||||
| 1355 | } else { | ||||||
| 1356 | 0 | $s1 = "$linktext"; | |||||
| 1357 | } | ||||||
| 1358 | 0 | return $s1; | |||||
| 1359 | } | ||||||
| 1360 | |||||||
| 1361 | # | ||||||
| 1362 | # process_BFI - process any of the B<>, F<>, or I<> pod-escapes and | ||||||
| 1363 | # convert them to corresponding HTML directives. | ||||||
| 1364 | # | ||||||
| 1365 | sub process_BFI { | ||||||
| 1366 | 0 | 0 | 0 | my($tag, $str) = @_; | |||
| 1367 | 0 | my($s1); # work string | |||||
| 1368 | 0 | my(%repltext) = ( 'B' => 'STRONG', | |||||
| 1369 | 'F' => 'EM', | ||||||
| 1370 | 'I' => 'EM'); | ||||||
| 1371 | |||||||
| 1372 | # extract the modified text and convert to HTML | ||||||
| 1373 | 0 | $s1 = "<$repltext{$tag}>$str$repltext{$tag}>"; | |||||
| 1374 | 0 | return $s1; | |||||
| 1375 | } | ||||||
| 1376 | |||||||
| 1377 | # | ||||||
| 1378 | # process_C - process the C<> pod-escape. | ||||||
| 1379 | # | ||||||
| 1380 | sub process_C { | ||||||
| 1381 | 0 | 0 | 0 | my($str, $doref) = @_; | |||
| 1382 | 0 | my($s1, $s2); | |||||
| 1383 | |||||||
| 1384 | 0 | $s1 = $str; | |||||
| 1385 | 0 | $s1 =~ s/\([^()]*\)//g; # delete parentheses | |||||
| 1386 | 0 | $s2 = $s1; | |||||
| 1387 | 0 | $s1 =~ s/\W//g; # delete bogus characters | |||||
| 1388 | 0 | $str = html_escape($str); | |||||
| 1389 | |||||||
| 1390 | # if there was a pod file that we found earlier with an appropriate | ||||||
| 1391 | # =item directive, then create a link to that page. | ||||||
| 1392 | 0 | 0 | 0 | if ($doref && defined $items{$s1}) { | |||
| 1393 | 0 | 0 | $s1 = ($items{$s1} ? | ||||
| 1394 | "$str" : | ||||||
| 1395 | "$str"); | ||||||
| 1396 | 0 | $s1 =~ s,(perl\w+/(\S+)\.html)#item_\2\b,$1,; | |||||
| 1397 | 0 | 0 | confess "s1 has space: $s1" if $s1 =~ /HREF="[^"]*\s[^"]*"/; | ||||
| 1398 | } else { | ||||||
| 1399 | 0 | $s1 = "$str"; |
|||||
| 1400 | # warn "$0: $podfile: cannot resolve C<$str> in paragraph $paragraph\n" if $verbose | ||||||
| 1401 | } | ||||||
| 1402 | |||||||
| 1403 | |||||||
| 1404 | 0 | return $s1; | |||||
| 1405 | } | ||||||
| 1406 | |||||||
| 1407 | # | ||||||
| 1408 | # process_E - process the E<> pod directive which seems to escape a character. | ||||||
| 1409 | # | ||||||
| 1410 | sub process_E { | ||||||
| 1411 | 0 | 0 | 0 | my($str) = @_; | |||
| 1412 | |||||||
| 1413 | 0 | for ($str) { | |||||
| 1414 | 0 | s,([^/].*),\&$1\;,g; | |||||
| 1415 | } | ||||||
| 1416 | |||||||
| 1417 | 0 | return $str; | |||||
| 1418 | } | ||||||
| 1419 | |||||||
| 1420 | # | ||||||
| 1421 | # process_Z - process the Z<> pod directive which really just amounts to | ||||||
| 1422 | # ignoring it. this allows someone to start a paragraph with an = | ||||||
| 1423 | # | ||||||
| 1424 | sub process_Z { | ||||||
| 1425 | 0 | 0 | 0 | my($str) = @_; | |||
| 1426 | |||||||
| 1427 | # there is no equivalent in HTML for this so just ignore it. | ||||||
| 1428 | 0 | $str = ""; | |||||
| 1429 | 0 | return $str; | |||||
| 1430 | } | ||||||
| 1431 | |||||||
| 1432 | # | ||||||
| 1433 | # process_S - process the S<> pod directive which means to convert all | ||||||
| 1434 | # spaces in the string to non-breaking spaces (in HTML-eze). | ||||||
| 1435 | # | ||||||
| 1436 | sub process_S { | ||||||
| 1437 | 0 | 0 | 0 | my($str) = @_; | |||
| 1438 | |||||||
| 1439 | # convert all spaces in the text to non-breaking spaces in HTML. | ||||||
| 1440 | 0 | return " |
|||||
| 1441 | } | ||||||
| 1442 | |||||||
| 1443 | # | ||||||
| 1444 | # process_X - this is supposed to make an index entry. we'll just | ||||||
| 1445 | # ignore it. | ||||||
| 1446 | # | ||||||
| 1447 | sub process_X { | ||||||
| 1448 | 0 | 0 | 0 | return ''; | |||
| 1449 | } | ||||||
| 1450 | |||||||
| 1451 | |||||||
| 1452 | # | ||||||
| 1453 | # finish_list - finish off any pending HTML lists. this should be called | ||||||
| 1454 | # after the entire pod file has been read and converted. | ||||||
| 1455 | # | ||||||
| 1456 | sub finish_list { | ||||||
| 1457 | 0 | 0 | 0 | while ($listlevel > 0) { | |||
| 1458 | 0 | print HTML "\n"; | |||||
| 1459 | 0 | $listlevel--; | |||||
| 1460 | } | ||||||
| 1461 | } | ||||||
| 1462 | |||||||
| 1463 | # | ||||||
| 1464 | # htmlify - converts a pod section specification to a suitable section | ||||||
| 1465 | # specification for HTML. if first arg is 1, only takes 1st word. | ||||||
| 1466 | # | ||||||
| 1467 | sub htmlify { | ||||||
| 1468 | 0 | 0 | 0 | my($compact, $heading) = @_; | |||
| 1469 | |||||||
| 1470 | 0 | 0 | if ($compact) { | ||||
| 1471 | 0 | $heading =~ /^(\w+)/; | |||||
| 1472 | 0 | $heading = $1; | |||||
| 1473 | } | ||||||
| 1474 | |||||||
| 1475 | # $heading = lc($heading); | ||||||
| 1476 | # $heading =~ s/[^\w\s]/_/g; | ||||||
| 1477 | 0 | $heading =~ s/(\s+)/ /g; | |||||
| 1478 | 0 | $heading =~ s/^\s*(.*?)\s*$/$1/s; | |||||
| 1479 | 0 | $heading =~ s/ /_/g; | |||||
| 1480 | 0 | $heading =~ s/\s+\Z//; | |||||
| 1481 | 0 | $heading =~ s/_{2,}/_/g; | |||||
| 1482 | |||||||
| 1483 | 0 | return $heading; | |||||
| 1484 | } | ||||||
| 1485 | |||||||
| 1486 | 1; |