tagsbefore and after C is invoked, so you might want to override thesetogether with C if this wrapping isn't suitable.Note that the code might be broken into multiple segments if there arenested formatting codes inside a C<< CE...> >> sequence. In between thecalls to C other markup tags might have been emitted in thatcase. The same is true for verbatim sections if the Coption is turned on.=head2 accept_targets_as_htmlThis method behaves like C, but also marks the regionas one whose content should be emitted literally, without HTML entity escapingor wrapping in a C element.=cutsub __in_literal_xhtml_region { return unless @{ $_[0]{__region_targets} }; my $target = $_[0]{__region_targets}[-1]; return $_[0]{__literal_targets}{ $target };}sub accept_targets_as_html { my ($self, @targets) = @_; $self->accept_targets(@targets); $self->{__literal_targets}{$_} = 1 for @targets;}sub handle_text { # escape special characters in HTML (<, >, &, etc) my $text = $_[1]; my $html; if ($_[0]->__in_literal_xhtml_region) { $html = $text; $text =~ s{<[^>]+?>}{}g; $text = $_[0]->decode_entities($text); } else { $html = $_[0]->encode_entities($text); } if ($_[0]{'in_code'} && @{$_[0]{'in_code'}}) { # Intentionally use the raw text in $_[1], even if we're not in a # literal xhtml region, since handle_code calls encode_entities. $_[0]->handle_code( $_[1], $_[0]{'in_code'}[-1] ); } else { if ($_[0]->{in_for}) { my $newlines = $_[0]->__in_literal_xhtml_region ? "\n\n" : ''; if ($_[0]->{started_for}) { if ($html =~ /\S/) { delete $_[0]->{started_for}; $_[0]{'scratch'} .= $html . $newlines; } # Otherwise, append nothing until we have something to append. } else { # The parser sometimes preserves newlines and sometimes doesn't! $html =~ s/\n\z//; $_[0]{'scratch'} .= $html . $newlines; } } else { # Just plain text. $_[0]{'scratch'} .= $html; } } $_[0]{hhtml} .= $html if $_[0]{'in_head'}; $_[0]{htext} .= $text if $_[0]{'in_head'}; $_[0]{itext} .= $text if $_[0]{'in_item_text'};}sub start_code { $_[0]{'scratch'} .= '';}sub end_code { $_[0]{'scratch'} .= '
';}sub handle_code { $_[0]{'scratch'} .= $_[0]->encode_entities( $_[1] );}sub start_Para { $_[0]{'scratch'} .= '';}sub start_Verbatim { $_[0]{'scratch'} = '
'; push(@{$_[0]{'in_code'}}, 'Verbatim'); $_[0]->start_code($_[0]{'in_code'}[-1]);}sub start_head1 { $_[0]{'in_head'} = 1; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_head2 { $_[0]{'in_head'} = 2; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_head3 { $_[0]{'in_head'} = 3; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_head4 { $_[0]{'in_head'} = 4; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_head5 { $_[0]{'in_head'} = 5; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_head6 { $_[0]{'in_head'} = 6; $_[0]{htext} = $_[0]{hhtml} = ''; }sub start_item_number { $_[0]{'scratch'} = "\n" if ($_[0]{'in_li'}->[-1] && pop @{$_[0]{'in_li'}}); $_[0]{'scratch'} .= '
'; push @{$_[0]{'in_li'}}, 1;}sub start_item_bullet { $_[0]{'scratch'} = "
\n" if ($_[0]{'in_li'}->[-1] && pop @{$_[0]{'in_li'}}); $_[0]{'scratch'} .= ''; push @{$_[0]{'in_li'}}, 1;}sub start_item_text { $_[0]{'in_item_text'} = 1; $_[0]{itext} = ''; # see end_item_text}sub start_over_bullet { $_[0]{'scratch'} = '
'; push @{$_[0]{'in_li'}}, 0; $_[0]->emit }sub start_over_block { $_[0]{'scratch'} = ''; $_[0]->emit }sub start_over_number { $_[0]{'scratch'} = ''; push @{$_[0]{'in_li'}}, 0; $_[0]->emit }sub start_over_text { $_[0]{'scratch'} = ''; $_[0]{'dl_level'}++; $_[0]{'in_dd'} ||= []; $_[0]->emit}sub end_over_block { $_[0]{'scratch'} .= '
'; $_[0]->emit }sub end_over_number { $_[0]{'scratch'} = "
\n" if ( pop @{$_[0]{'in_li'}} ); $_[0]{'scratch'} .= ''; pop @{$_[0]{'in_li'}}; $_[0]->emit;}sub end_over_bullet { $_[0]{'scratch'} = "\n" if ( pop @{$_[0]{'in_li'}} ); $_[0]{'scratch'} .= ''; pop @{$_[0]{'in_li'}}; $_[0]->emit;}sub end_over_text { if ($_[0]{'in_dd'}[ $_[0]{'dl_level'} ]) { $_[0]{'scratch'} = "\n"; $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] = 0; } $_[0]{'scratch'} .= ''; $_[0]{'dl_level'}--; $_[0]->emit;}# . . . . . Now the actual formatters:sub end_Para { $_[0]{'scratch'} .= ''; $_[0]->emit }sub end_Verbatim { $_[0]->end_code(pop(@{$_[0]->{'in_code'}})); $_[0]{'scratch'} .= ''; $_[0]->emit;}sub _end_head { my $h = delete $_[0]{in_head}; my $add = $_[0]->html_h_level; $add = 1 unless defined $add; $h += $add - 1; my $id = $_[0]->idify(delete $_[0]{htext}); my $text = $_[0]{scratch}; my $head = qq{$text }; $_[0]{'scratch'} = $_[0]->backlink && ($h - $add == 0) # backlinks enabled && =head1 ? qq{$head} : $head; $_[0]->emit; push @{ $_[0]{'to_index'} }, [$h, $id, delete $_[0]{'hhtml'}];}sub end_head1 { shift->_end_head(@_); }sub end_head2 { shift->_end_head(@_); }sub end_head3 { shift->_end_head(@_); }sub end_head4 { shift->_end_head(@_); }sub end_head5 { shift->_end_head(@_); }sub end_head6 { shift->_end_head(@_); }sub end_item_bullet { $_[0]{'scratch'} .= ''; $_[0]->emit }sub end_item_number { $_[0]{'scratch'} .= ''; $_[0]->emit }sub end_item_text { # idify and anchor =item content if wanted my $dt_id = $_[0]{'anchor_items'} ? ' id="'. $_[0]->encode_entities($_[0]->idify($_[0]{'itext'})) .'"' : ''; # reset scratch my $text = $_[0]{scratch}; $_[0]{'scratch'} = ''; if ($_[0]{'in_dd'}[ $_[0]{'dl_level'} ]) { $_[0]{'scratch'} = "\n"; $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] = 0; } $_[0]{'scratch'} .= qq{$text \n}; $_[0]{'in_dd'}[ $_[0]{'dl_level'} ] = 1; $_[0]->emit;}# This handles =begin and =for blocks of all kinds.sub start_for { my ($self, $flags) = @_; push @{ $self->{__region_targets} }, $flags->{target_matching}; $self->{started_for} = 1; $self->{in_for} = 1; unless ($self->__in_literal_xhtml_region) { $self->{scratch} .= '{scratch} .= qq( class="$flags->{target}") if $flags->{target}; $self->{scratch} .= ">\n\n"; }}sub end_for { my ($self) = @_; delete $self->{started_for}; delete $self->{in_for}; if ($self->__in_literal_xhtml_region) { # Remove trailine newlines. $self->{'scratch'} =~ s/\s+\z//s; } else { $self->{'scratch'} .= ''; } pop @{ $self->{__region_targets} }; $self->emit;}sub start_Document { my ($self) = @_; if (defined $self->html_header) { $self->{'scratch'} .= $self->html_header; $self->emit unless $self->html_header eq ""; } else { my ($doctype, $title, $metatags, $bodyid); $doctype = $self->html_doctype || ''; $title = $self->force_title || $self->title || $self->default_title || ''; $metatags = $self->html_header_tags || ''; if (my $css = $self->html_css) { if ($css !~ /encode_entities($css) . '" type="text/css" />'; } else { $metatags .= $css; } } if ($self->html_javascript) { $metatags .= qq{\n'; } $bodyid = $self->backlink ? ' id="_podtop_"' : ''; $self->{'scratch'} .= <<"HTML";$doctype$title $metatagsHTML $self->emit; }}sub build_index { my ($self, $to_index) = @_; my @out; my $level = 0; my $indent = -1; my $space = ''; my $id = ' id="index"'; for my $h (@{ $to_index }, [0]) { my $target_level = $h->[0]; # Get to target_level by opening or closing ULs if ($level == $target_level) { $out[-1] .= ''; } elsif ($level > $target_level) { $out[-1] .= '' if $out[-1] =~ /^\s+/; while ($level > $target_level) { --$level; push @out, (' ' x --$indent) . ' ' if @out && $out[-1] =~ m{^\s+<\/ul}; push @out, (' ' x --$indent) . ''; } push @out, (' ' x --$indent) . '' if $level; } else { while ($level < $target_level) { ++$level; push @out, (' ' x ++$indent) . '' if @out && $out[-1]=~ /^\s*"; $id = ''; } ++$indent; } next unless $level; $space = ' ' x $indent; my $fragment = $self->encode_entities($self->encode_url($h->[1])); push @out, sprintf '%s- %s', $space, $fragment, $h->[2]; } return join "\n", @out;}sub end_Document { my ($self) = @_; my $to_index = $self->{'to_index'}; if ($self->index && @{ $to_index } ) { my $index = $self->build_index($to_index); # Splice the index in between the HTML headers and the first element. my $offset = defined $self->html_header ? $self->html_header eq '' ? 0 : 1 : 1; splice @{ $self->{'output'} }, $offset, 0, $index; } if (defined $self->html_footer) { $self->{'scratch'} .= $self->html_footer; $self->emit unless $self->html_footer eq ""; } else { $self->{'scratch'} .= "\n"; $self->emit; } if ($self->index) { print {$self->{'output_fh'}} join ("\n\n", @{ $self->{'output'} }), "\n\n"; @{$self->{'output'}} = (); }}# Handling code tagssub start_B { $_[0]{'scratch'} .= '' }sub end_B { $_[0]{'scratch'} .= '' }sub start_C { push(@{$_[0]{'in_code'}}, 'C'); $_[0]->start_code($_[0]{'in_code'}[-1]); }sub end_C { $_[0]->end_code(pop(@{$_[0]{'in_code'}})); }sub start_F { $_[0]{'scratch'} .= '' }sub end_F { $_[0]{'scratch'} .= '' }sub start_I { $_[0]{'scratch'} .= '' }sub end_I { $_[0]{'scratch'} .= '' }sub start_L { my ($self, $flags) = @_; my ($type, $to, $section) = @{$flags}{'type', 'to', 'section'}; my $url = $self->encode_entities( $type eq 'url' ? $to : $type eq 'pod' ? $self->resolve_pod_page_link($to, $section) : $type eq 'man' ? $self->resolve_man_page_link($to, $section) : undef ); # If it's an unknown type, use an attribute-less like HTML.pm. $self->{'scratch'} .= '' : '>');}sub end_L { $_[0]{'scratch'} .= '' }sub start_S { $_[0]{'scratch'} .= '' }sub end_S { $_[0]{'scratch'} .= '' }sub emit { my($self) = @_; if ($self->index) { push @{ $self->{'output'} }, $self->{'scratch'}; } else { print {$self->{'output_fh'}} $self->{'scratch'}, "\n\n"; } $self->{'scratch'} = ''; return;}=head2 resolve_pod_page_link my $url = $pod->resolve_pod_page_link('Net::Ping', 'INSTALL'); my $url = $pod->resolve_pod_page_link('perlpodspec'); my $url = $pod->resolve_pod_page_link(undef, 'SYNOPSIS');Resolves a POD link target (typically a module or POD file name) and sectionname to a URL. The resulting link will be returned for the above examples as: https://metacpan.org/pod/Net::Ping#INSTALL https://metacpan.org/pod/perlpodspec #SYNOPSISNote that when there is only a section argument the URL will simply be a linkto a section in the current document.=cutsub resolve_pod_page_link { my ($self, $to, $section) = @_; return undef unless defined $to || defined $section; if (defined $section) { my $id = $self->idify($section, 1); $section = '#' . $self->encode_url($id); return $section unless defined $to; } else { $section = '' } return ($self->perldoc_url_prefix || '') . $to . $section . ($self->perldoc_url_postfix || '');}=head2 resolve_man_page_link my $url = $pod->resolve_man_page_link('crontab(5)', 'EXAMPLE CRON FILE'); my $url = $pod->resolve_man_page_link('crontab');Resolves a man page link target and numeric section to a URL. The resultinglink will be returned for the above examples as: http://man.he.net/man5/crontab http://man.he.net/man1/crontabNote that the first argument is required. The section number will be parsedfrom it, and if it's missing will default to 1. The second argument iscurrently ignored, as L
does not currentlyinclude linkable IDs or anchor names in its pages. Subclass to link to adifferent man page HTTP server.=cutsub resolve_man_page_link { my ($self, $to, $section) = @_; return undef unless defined $to; my ($page, $part) = $to =~ /^([^(]+)(?:[(](\d+)[)])?$/; return undef unless $page; return ($self->man_url_prefix || '') . ($part || 1) . "/" . $self->encode_entities($page) . ($self->man_url_postfix || '');}=head2 idify my $id = $pod->idify($text); my $hash = $pod->idify($text, 1);This method turns an arbitrary string into a valid XHTML ID attribute value.The rules enforced, followingL, are:=over=item *The id must start with a letter (a-z or A-Z)=item *All subsequent characters can be letters, numbers (0-9), hyphens (-),underscores (_), colons (:), and periods (.).=item *The final character can't be a hyphen, colon, or period. URLs ending with thesecharacters, while allowed by XHTML, can be awkward to extract from plain text.=item *Each id must be unique within the document.=backIn addition, the returned value will be unique within the context of thePod::Simple::XHTML object unless a second argument is passed a true value. IDattributes should always be unique within a single XHTML document, but passthe true value if you are creating not an ID but a URL hash to point toan ID (i.e., if you need to put the "#foo" in C<< foo >>.=cutsub idify { my ($self, $t, $not_unique) = @_; for ($t) { s/[<>&'"]//g; # Strip HTML special characters s/^\s+//; s/\s+$//; # Strip white space. s/^([^a-zA-Z]+)$/pod$1/; # Prepend "pod" if no valid chars. s/^[^a-zA-Z]+//; # First char must be a letter. s/[^-a-zA-Z0-9_:.]+/-/g; # All other chars must be valid. s/[-:.]+$//; # Strip trailing punctuation. } return $t if $not_unique; my $i = ''; $i++ while $self->{ids}{"$t$i"}++; return "$t$i";}=head2 batch_mode_page_object_init $pod->batch_mode_page_object_init($batchconvobj, $module, $infile, $outfile, $depth);Called by L so that the class has a chance toinitialize the converter. Internally it sets the C property totrue and sets C, but Pod::Simple::XHTML does notcurrently use those features. Subclasses might, though.=cutsub batch_mode_page_object_init { my ($self, $batchconvobj, $module, $infile, $outfile, $depth) = @_; $self->batch_mode(1); $self->batch_mode_current_level($depth); return $self;}sub html_header_after_title {}1;__END__=head1 SEE ALSOL, L, L=head1 SUPPORTQuestions or discussion about POD and Pod::Simple should be sent to thepod-people@perl.org mail list. Send an empty email topod-people-subscribe@perl.org to subscribe.This module is managed in an open GitHub repository,L . Feel free to fork and contribute, orto clone L and send patches!Patches against Pod::Simple are welcome. Please send bug reports to.=head1 COPYRIGHT AND DISCLAIMERSCopyright (c) 2003-2005 Allison Randal.This library is free software; you can redistribute it and/or modify itunder the same terms as Perl itself.This program is distributed in the hope that it will be useful, butwithout any warranty; without even the implied warranty ofmerchantability or fitness for a particular purpose.=head1 ACKNOWLEDGEMENTSThanks to L for permission to use itsL site for man page links.Thanks to L for permission to use thesite for Perl module links.=head1 AUTHORPod::Simpele::XHTML was created by Allison Randal .Pod::Simple was created by Sean M. Burke .But don't bother him, he's retired.Pod::Simple is maintained by:=over=item * Allison Randal C=item * Hans Dieter Pearcey C=item * David E. Wheeler C=back=cut