$#array should be accepted as a lvalue sub return value.
[p5sagit/p5-mst-13.2.git] / cpan / Pod-Simple / lib / Pod / Simple / XHTML.pm
CommitLineData
69473a20 1=pod
2
3=head1 NAME
4
5Pod::Simple::XHTML -- format Pod as validating XHTML
6
7=head1 SYNOPSIS
8
9 use Pod::Simple::XHTML;
10
11 my $parser = Pod::Simple::XHTML->new();
12
13 ...
14
15 $parser->parse_file('path/to/file.pod');
16
17=head1 DESCRIPTION
18
19This class is a formatter that takes Pod and renders it as XHTML
20validating HTML.
21
22This is a subclass of L<Pod::Simple::Methody> and inherits all its
23methods. The implementation is entirely different than
24L<Pod::Simple::HTML>, but it largely preserves the same interface.
25
26=cut
27
28package Pod::Simple::XHTML;
29use strict;
8737ae4d 30use vars qw( $VERSION @ISA $HAS_HTML_ENTITIES );
69473a20 31$VERSION = '3.04';
32use Carp ();
33use Pod::Simple::Methody ();
34@ISA = ('Pod::Simple::Methody');
35
8737ae4d 36BEGIN {
37 $HAS_HTML_ENTITIES = eval "require HTML::Entities; 1";
38}
39
40my %entities = (
41 q{>} => 'gt',
42 q{<} => 'lt',
43 q{'} => '#39',
44 q{"} => 'quot',
45 q{&} => 'amp',
46);
47
48sub encode_entities {
49 return HTML::Entities::encode_entities( $_[0] ) if $HAS_HTML_ENTITIES;
50 my $str = $_[0];
51 my $ents = join '', keys %entities;
52 $str =~ s/([$ents])/'&' . $entities{$1} . ';'/ge;
53 return $str;
54}
69473a20 55
56#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57
58=head1 METHODS
59
60Pod::Simple::XHTML offers a number of methods that modify the format of
61the HTML output. Call these after creating the parser object, but before
62the call to C<parse_file>:
63
64 my $parser = Pod::PseudoPod::HTML->new();
65 $parser->set_optional_param("value");
66 $parser->parse_file($file);
67
68=head2 perldoc_url_prefix
69
70In turning L<Foo::Bar> into http://whatever/Foo%3a%3aBar, what
71to put before the "Foo%3a%3aBar". The default value is
72"http://search.cpan.org/perldoc?".
73
74=head2 perldoc_url_postfix
75
76What to put after "Foo%3a%3aBar" in the URL. This option is not set by
77default.
78
79=head2 title_prefix, title_postfix
80
81What to put before and after the title in the head. The values should
82already be &-escaped.
83
84=head2 html_css
85
86 $parser->html_css('path/to/style.css');
87
88The URL or relative path of a CSS file to include. This option is not
89set by default.
90
91=head2 html_javascript
92
93The URL or relative path of a JavaScript file to pull in. This option is
94not set by default.
95
96=head2 html_doctype
97
98A document type tag for the file. This option is not set by default.
99
100=head2 html_header_tags
101
102Additional arbitrary HTML tags for the header of the document. The
103default value is just a content type header tag:
104
105 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
106
107Add additional meta tags here, or blocks of inline CSS or JavaScript
108(wrapped in the appropriate tags).
109
110=head2 default_title
111
112Set a default title for the page if no title can be determined from the
113content. The value of this string should already be &-escaped.
114
115=head2 force_title
116
117Force a title for the page (don't try to determine it from the content).
118The value of this string should already be &-escaped.
119
120=head2 html_header, html_footer
121
122Set the HTML output at the beginning and end of each file. The default
123header includes a title, a doctype tag (if C<html_doctype> is set), a
124content tag (customized by C<html_header_tags>), a tag for a CSS file
125(if C<html_css> is set), and a tag for a Javascript file (if
126C<html_javascript> is set). The default footer simply closes the C<html>
127and C<body> tags.
128
129The options listed above customize parts of the default header, but
130setting C<html_header> or C<html_footer> completely overrides the
131built-in header or footer. These may be useful if you want to use
132template tags instead of literal HTML headers and footers or are
133integrating converted POD pages in a larger website.
134
135If you want no headers or footers output in the HTML, set these options
136to the empty string.
137
138=head2 index
139
140TODO -- Not implemented.
141
142Whether to add a table-of-contents at the top of each page (called an
143index for the sake of tradition).
144
145
146=cut
147
148__PACKAGE__->_accessorize(
149 'perldoc_url_prefix',
150 'perldoc_url_postfix',
151 'title_prefix', 'title_postfix',
152 'html_css',
153 'html_javascript',
154 'html_doctype',
155 'html_header_tags',
156 'title', # Used internally for the title extracted from the content
157 'default_title',
158 'force_title',
159 'html_header',
160 'html_footer',
161 'index',
162 'batch_mode', # whether we're in batch mode
163 'batch_mode_current_level',
164 # When in batch mode, how deep the current module is: 1 for "LWP",
165 # 2 for "LWP::Procotol", 3 for "LWP::Protocol::GHTTP", etc
166);
167
168#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169
170=head1 SUBCLASSING
171
172If the standard options aren't enough, you may want to subclass
173Pod::Simple::XHMTL. These are the most likely candidates for methods
174you'll want to override when subclassing.
175
176=cut
177
178sub new {
179 my $self = shift;
180 my $new = $self->SUPER::new(@_);
181 $new->{'output_fh'} ||= *STDOUT{IO};
182 $new->accept_targets( 'html', 'HTML' );
183 $new->perldoc_url_prefix('http://search.cpan.org/perldoc?');
184 $new->html_header_tags('<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">');
185 $new->nix_X_codes(1);
186 $new->codes_in_verbatim(1);
187 $new->{'scratch'} = '';
188 return $new;
189}
190
191#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192
193=head2 handle_text
194
195This method handles the body of text within any element: it's the body
196of a paragraph, or everything between a "=begin" tag and the
197corresponding "=end" tag, or the text within an L entity, etc. You would
198want to override this if you are adding a custom element type that does
199more than just display formatted text. Perhaps adding a way to generate
200HTML tables from an extended version of POD.
201
202So, let's say you want add a custom element called 'foo'. In your
203subclass's C<new> method, after calling C<SUPER::new> you'd call:
204
205 $new->accept_targets_as_text( 'foo' );
206
207Then override the C<start_for> method in the subclass to check for when
208"$flags->{'target'}" is equal to 'foo' and set a flag that marks that
209you're in a foo block (maybe "$self->{'in_foo'} = 1"). Then override the
210C<handle_text> method to check for the flag, and pass $text to your
211custom subroutine to construct the HTML output for 'foo' elements,
212something like:
213
214 sub handle_text {
215 my ($self, $text) = @_;
216 if ($self->{'in_foo'}) {
217 $self->{'scratch'} .= build_foo_html($text);
218 } else {
219 $self->{'scratch'} .= $text;
220 }
221 }
222
223=cut
224
225sub handle_text {
226 # escape special characters in HTML (<, >, &, etc)
227 $_[0]{'scratch'} .= $_[0]{'in_verbatim'} ? encode_entities( $_[1] ) : $_[1]
228}
229
230sub start_Para { $_[0]{'scratch'} = '<p>' }
231sub start_Verbatim { $_[0]{'scratch'} = '<pre><code>'; $_[0]{'in_verbatim'} = 1}
232
233sub start_head1 { $_[0]{'scratch'} = '<h1>' }
234sub start_head2 { $_[0]{'scratch'} = '<h2>' }
235sub start_head3 { $_[0]{'scratch'} = '<h3>' }
236sub start_head4 { $_[0]{'scratch'} = '<h4>' }
237
238sub start_item_bullet { $_[0]{'scratch'} = '<li>' }
239sub start_item_number { $_[0]{'scratch'} = "<li>$_[1]{'number'}. " }
240sub start_item_text { $_[0]{'scratch'} = '<li>' }
241
242sub start_over_bullet { $_[0]{'scratch'} = '<ul>'; $_[0]->emit }
243sub start_over_text { $_[0]{'scratch'} = '<ul>'; $_[0]->emit }
244sub start_over_block { $_[0]{'scratch'} = '<ul>'; $_[0]->emit }
245sub start_over_number { $_[0]{'scratch'} = '<ol>'; $_[0]->emit }
246
247sub end_over_bullet { $_[0]{'scratch'} .= '</ul>'; $_[0]->emit }
248sub end_over_text { $_[0]{'scratch'} .= '</ul>'; $_[0]->emit }
249sub end_over_block { $_[0]{'scratch'} .= '</ul>'; $_[0]->emit }
250sub end_over_number { $_[0]{'scratch'} .= '</ol>'; $_[0]->emit }
251
252# . . . . . Now the actual formatters:
253
254sub end_Para { $_[0]{'scratch'} .= '</p>'; $_[0]->emit }
255sub end_Verbatim {
256 $_[0]{'scratch'} .= '</code></pre>';
257 $_[0]{'in_verbatim'} = 0;
258 $_[0]->emit;
259}
260
261sub end_head1 { $_[0]{'scratch'} .= '</h1>'; $_[0]->emit }
262sub end_head2 { $_[0]{'scratch'} .= '</h2>'; $_[0]->emit }
263sub end_head3 { $_[0]{'scratch'} .= '</h3>'; $_[0]->emit }
264sub end_head4 { $_[0]{'scratch'} .= '</h4>'; $_[0]->emit }
265
266sub end_item_bullet { $_[0]{'scratch'} .= '</li>'; $_[0]->emit }
267sub end_item_number { $_[0]{'scratch'} .= '</li>'; $_[0]->emit }
268sub end_item_text { $_[0]->emit }
269
270# This handles =begin and =for blocks of all kinds.
271sub start_for {
272 my ($self, $flags) = @_;
273 $self->{'scratch'} .= '<div';
274 $self->{'scratch'} .= ' class="'.$flags->{'target'}.'"' if ($flags->{'target'});
275 $self->{'scratch'} .= '>';
276 $self->emit;
277
278}
279sub end_for {
280 my ($self) = @_;
281 $self->{'scratch'} .= '</div>';
282 $self->emit;
283}
284
285sub start_Document {
286 my ($self) = @_;
287 if (defined $self->html_header) {
288 $self->{'scratch'} .= $self->html_header;
289 $self->emit unless $self->html_header eq "";
290 } else {
291 my ($doctype, $title, $metatags);
292 $doctype = $self->html_doctype || '';
293 $title = $self->force_title || $self->title || $self->default_title || '';
294 $metatags = $self->html_header_tags || '';
295 if ($self->html_css) {
296 $metatags .= "\n<link rel='stylesheet' href='" .
297 $self->html_css . "' type='text/css'>";
298 }
299 if ($self->html_javascript) {
300 $metatags .= "\n<script type='text/javascript' src='" .
301 $self->html_javascript . "'></script>";
302 }
303 $self->{'scratch'} .= <<"HTML";
304$doctype
305<html>
306<head>
307<title>$title</title>
308$metatags
309</head>
310<body>
311HTML
312 $self->emit;
313 }
314}
315
316sub end_Document {
317 my ($self) = @_;
318 if (defined $self->html_footer) {
319 $self->{'scratch'} .= $self->html_footer;
320 $self->emit unless $self->html_footer eq "";
321 } else {
322 $self->{'scratch'} .= "</body>\n</html>";
323 $self->emit;
324 }
325}
326
327# Handling code tags
328sub start_B { $_[0]{'scratch'} .= '<b>' }
329sub end_B { $_[0]{'scratch'} .= '</b>' }
330
ac185ebf 331sub start_C { $_[0]{'scratch'} .= '<code>'; $_[0]{'in_verbatim'} = 1; }
332sub end_C { $_[0]{'scratch'} .= '</code>'; $_[0]{'in_verbatim'} = 0; }
69473a20 333
334sub start_E { $_[0]{'scratch'} .= '&' }
335sub end_E { $_[0]{'scratch'} .= ';' }
336
337sub start_F { $_[0]{'scratch'} .= '<i>' }
338sub end_F { $_[0]{'scratch'} .= '</i>' }
339
340sub start_I { $_[0]{'scratch'} .= '<i>' }
341sub end_I { $_[0]{'scratch'} .= '</i>' }
342
343sub start_L {
344 my ($self, $flags) = @_;
345 my $url;
346 if ($flags->{'type'} eq 'url') {
347 $url = $flags->{'to'};
348 } elsif ($flags->{'type'} eq 'pod') {
349 $url .= $self->perldoc_url_prefix || '';
350 $url .= $flags->{'to'} || '';
351 $url .= '/' . $flags->{'section'} if ($flags->{'section'});
352 $url .= $self->perldoc_url_postfix || '';
353# require Data::Dumper;
354# print STDERR Data::Dumper->Dump([$flags]);
355 }
356
357 $self->{'scratch'} .= '<a href="'. $url . '">';
358}
359sub end_L { $_[0]{'scratch'} .= '</a>' }
360
361sub start_S { $_[0]{'scratch'} .= '<nobr>' }
362sub end_S { $_[0]{'scratch'} .= '</nobr>' }
363
364sub emit {
365 my($self) = @_;
366 my $out = $self->{'scratch'} . "\n";
367 print {$self->{'output_fh'}} $out, "\n";
368 $self->{'scratch'} = '';
369 return;
370}
371
372# Bypass built-in E<> handling to preserve entity encoding
373sub _treat_Es {}
374
3751;
376
377__END__
378
379=head1 SEE ALSO
380
381L<Pod::Simple>, L<Pod::Simple::Methody>
382
383=head1 COPYRIGHT
384
385Copyright (c) 2003-2005 Allison Randal.
386
387This library is free software; you can redistribute it and/or modify
388it under the same terms as Perl itself. The full text of the license
389can be found in the LICENSE file included with this module.
390
391This library is distributed in the hope that it will be useful, but
392without any warranty; without even the implied warranty of
393merchantability or fitness for a particular purpose.
394
395=head1 AUTHOR
396
397Allison Randal <allison@perl.org>
398
399=cut
400