File Coverage

blib/lib/Pod/POM/View/HTML/Filter.pm
Criterion Covered Total %
statement 140 143 97.9
branch 57 58 98.2
condition 27 37 72.9
subroutine 21 22 95.4
pod 14 14 100.0
total 259 274 94.5


line stmt bran cond sub pod time code
1             package Pod::POM::View::HTML::Filter;
2 10     10   689405 use Pod::POM::View::HTML;
  10         117596  
  10         613  
3             our @ISA = qw( Pod::POM::View::HTML );
4              
5 10     10   116 use warnings;
  10         24  
  10         543  
6 10     10   62 use strict;
  10         28  
  10         352  
7 10     10   63 use Carp;
  10         19  
  10         32935  
8              
9             our $VERSION = '0.09';
10              
11             my  %filter;
12             our %builtin = (
13                 default => {
14                     code => sub {
15                         my $s = shift;
16                         $s =~ s/&/&/g;
17                         $s =~ s/</&lt;/g;
18                         $s =~ s/>/&gt;/g;
19                         $s;
20                     },
21                     verbatim => 1,
22                 },
23                 perl_tidy => {
24                     code => \&perl_tidy_filter,
25                     requires => [qw( Perl::Tidy )],
26                     verbatim => 1,
27                     alias => [qw( perl )],
28                 },
29                 perl_ppi => {
30                     code => \&perl_ppi_filter,
31                     requires => [qw( PPI PPI::HTML )],
32                     verbatim => 1,
33                     alias => [qw( ppi )],
34                 },
35                 html => {
36                     code => \&html_filter,
37                     requires => [qw( Syntax::Highlight::HTML )],
38                     verbatim => 1,
39                 },
40                 shell => {
41                     code => \&shell_filter,
42                     requires => [qw( Syntax::Highlight::Shell )],
43                     verbatim => 1,
44                 },
45                 kate => {
46                     code => \&kate_filter,
47                     requires => [qw( Syntax::Highlight::Engine::Kate )],
48                     verbatim => 1,
49                 },
50                 wiki => {
51                     code => \&wiki_filter,
52                     requires => [qw( Text::WikiFormat )],
53                     verbatim => 0,
54                 },
55                 wikimedia => {
56                     code => \&wikimedia_filter,
57                     requires => [qw( Text::MediawikiFormat )],
58                     verbatim => 0,
59                 },
60             );
61              
62             # automatically register built-in handlers
63             my $INIT = 1;
64             Pod::POM::View::HTML::Filter->add( %builtin );
65             $INIT = 0;
66              
67             #
68             # Specific methods
69             #
70             sub new {
71 76     76 1 143644     my $class = shift;
72 76         619     return $class->SUPER::new(
73                     auto_unindent => 1,
74                     @_,
75                     filter => {}, # instance filters
76                     FILTER => [], # stack maintaining info for filters
77                 );
78             }
79              
80             sub add {
81 22     22 1 11052     my ($self, %args) = @_;
82 22         90     my $filter = $self->__filter();
83              
84 22         154     for my $lang ( keys %args ) {
85 96         181         my $nok = 0;
86 96 100       382         if( exists $args{$lang}{requires} ) {
87 72         112             for ( @{ $args{$lang}{requires} } ) {
  72         215  
88 82         7095                 eval "require $_;";
89 82 100       4904788                 if ($@) {
90 12         44                     $nok++;
91 12 100       107                     carp "$lang\: pre-requisite $_ could not be loaded"
92                                   unless $INIT; # don't warn for built-ins
93                             }
94                         }
95                     }
96 96 100       1730         croak "$lang: no code parameter given"
97                       unless exists $args{$lang}{code};
98              
99 94 100       335         if ( !$nok ) {
100 82         298             $filter->{$lang} = $args{$lang};
101 82 100       1804             if ( $args{$lang}{alias} ) {
102 20         45                 $filter->{$_} = $args{$lang} for @{ $args{$lang}{alias} };
  20         223  
103                         }
104                     }
105                 }
106             }
107              
108             sub delete {
109 41     41 1 2920     my ( $self, $lang ) = @_;
110 41         120     my $filter = $self->__filter();
111 41         120     my $old = $self->_filter()->{$lang};
112 41         153     $filter->{$lang} = undef;
113 41         141     return $old;
114             }
115              
116             # return a hashref of current filters for the class|instance
117             sub _filter {
118 185     185   313     my ($self) = @_;
119 172         1635     my $filter =
120                     ref $self
121                     && UNIVERSAL::isa( $self, 'Pod::POM::View::HTML::Filter' )
122 185 100 66     1754         ? { %filter, %{ $self->{filter} } }
123                     : \%filter;
124 185   66     3336     $filter->{$_} || delete $filter->{$_} for keys %$filter;
125 185         752     return $filter;
126             }
127              
128             # return the real inner filter list for the class|instance
129             sub __filter {
130 63     63   144     my ($self) = @_;
131                 return
132 63 100 66     723         ref $self
133                     && UNIVERSAL::isa( $self, 'Pod::POM::View::HTML::Filter' )
134                     ? $self->{filter}
135                     : \%filter;
136             }
137              
138             sub know {
139 14     14 1 3863     my ($self, $lang) = @_;
140 14         35     return exists $self->_filter()->{$lang};
141             }
142              
143 8     8 1 6407 sub filters { keys %{ $_[0]->_filter() }; }
  8         30  
144              
145             #
146             # overridden Pod::POM::View::HTML methods
147             #
148             sub view_for {
149 24     24 1 22758     my ($self, $for) = @_;
150 24         148     my $format = $for->format;
151 24         351     my $filter = $self->_filter();
152              
153 24 100       104     return $for->text() . "\n\n" if $format =~ /^html\b/;
154              
155 23 100       148     if ( $format =~ /^filter\b/ ) {
156 22         91         my $args = (split '=', $format, 2)[1];
157 22 100       82         return '' unless defined $args; # silently skip
158              
159 21         121         my $text = $for->text;
160 21         702         my $verbatim = 0;
161              
162             # select the filters and options
163 21         45         my @langs;
164 21         66         for my $lang (split /\|/, $args) {
165 21         73             ( $lang, my $opts ) = ( split( ':', $lang, 2 ), '' );
166 21         43             $opts =~ y/:/ /;
167 21 100       69             $lang = exists $filter->{$lang} ? $lang : 'default';
168 21         56             push @langs, [ $lang, $opts ];
169 21 100       275             $verbatim++ if $filter->{$lang}{verbatim};
170                     }
171              
172             # cancel filtering if one filter is missing
173 21 100       44         @langs = ( grep { $_->[0] eq 'default' } @langs )
  21         123  
174                         ? ( [ 'default', '' ] )
175                         : @langs;
176              
177             # process the text
178 21         110         $text = $filter->{ $_->[0] }{code}->( $text, $_->[1] ) for @langs;
179              
180 21 100       60911         return $verbatim ? "<pre>$text</pre>\n" : "$text\n";
181                 }
182              
183             # fall-through
184 1         3     return '';
185             }
186              
187             sub view_begin {
188 98     98 1 220391     my ($self, $begin) = @_;
189 98         558     my ($format, $args) = split(' ', $begin->format(), 2);
190 98         1740     my $filter = $self->_filter();
191              
192 98 100       438     if ( $format eq 'html' ) {
    100          
193 1         14         return $self->SUPER::view_begin( $begin );
194                 }
195                 elsif( $format eq 'filter' ) {
196 96         462         my @filters = map { s/^\s*|\s*$//g; $_ } split /\|/, $args;
  114         941  
  114         413  
197              
198             # fetch the text and verbatim blocks in the begin section
199             # and remember the type of each block
200 96         203         my $verbatim = 0;
201 96         350         my $prev = '';
202 96         156         my $text = '';
203 96         137         for my $item ( @{ $begin->content } ) {
  96         482  
204 142 100       2724             $text .= ($prev ? "\n\n" :'') . $item->text();
205 142         2039             $prev = 1;
206 142 100       691             $verbatim++ if $item->type eq 'verbatim';
207                     }
208              
209             # a block is verbatim only if all subblocks are verbatim
210 96 100       1586         $verbatim = 0 if $verbatim != @{ $begin->content };
  96         411  
211              
212             # select the filters and options
213 96         1319         my @langs;
214 96         211         for my $f (@filters) {
215 114         308             my ( $lang, $opts ) = split( ' ', $f, 2 );
216 114 100       414             $lang = exists $filter->{$lang} ? $lang : 'default';
217 114         311             push @langs, [ $lang, $opts ];
218 114 100       565             $verbatim++ if $filter->{$lang}{verbatim};
219                     }
220              
221             # cancel filtering if one filter is missing
222 96 100       200         @langs = ( grep { $_->[0] eq 'default' } @langs )
  114         834  
223                         ? ( [ 'default', '' ] )
224                         : @langs;
225              
226             # process the text
227 96 100       419         ( my $indent, $text ) = _unindent($text)
228                         if $self->{auto_unindent};
229 96         547         $text = $filter->{ $_->[0] }{code}->( $text, $_->[1] ) for @langs;
230 96 100       804578         $text =~ s/^(?=.+)/$indent/gm
231                         if $self->{auto_unindent};
232              
233             # the enclosing tags depend on the block and the last filter
234 96 100       1241         return $verbatim ? "<pre>$text</pre>\n" : "$text\n";
235                 }
236              
237             # fall-through
238 1         4     return '';
239             }
240              
241             #
242             # utility functions
243             #
244              
245             # a simple filter output cleanup routine
246             sub _cleanup {
247 37     37   22388     local $_ = shift;
248 37         7181     s!\A<pre>\n?|\n?</pre>\n\z!!gm; # remove <pre></pre>
249 37         185     $_;
250             }
251              
252             sub _unindent {
253 98     98   6753     my $str = shift;
254 98         124     my $indent;
255 98         522     while ( $str =~ /^( *)\S/gmc ) {
256 442 100       2293         $indent =
    100          
257                           !defined $indent ? $1
258                         : length($1) < length($indent) ? $1
259                         : $indent;
260                 }
261 98   100     376     $indent ||= '';
262 98         1338     $str =~ s/^$indent//gm;
263 98         489     return ( $indent, $str );
264             }
265              
266             #
267             # builtin filters
268             #
269              
270             # a cache for multiple parsers with the same options
271             my %filter_parser;
272              
273             # Perl highlighting, thanks to Perl::Tidy
274             sub perl_tidy_filter {
275 13   100 13 1 176     my ($code, $opts) = ( shift, shift || "" );
276 13         25     my $output = "";
277              
278             # Perl::Tidy 20031021 uses Getopt::Long and expects the default config
279             # this is a workaround (a patch was sent to Perl::Tidy's author)
280 13         64     my $glc = Getopt::Long::Configure();
281 13         215     Getopt::Long::ConfigDefaults();
282              
283 13         227     Perl::Tidy::perltidy(
284                     source => \$code,
285                     destination => \$output,
286                     argv => "-html -pre -nopod2html " . $opts,
287                     stderr => '-',
288                     errorfile => '-',
289                 );
290 13         473438     $output = _cleanup( $output ); # remove <pre></pre>
291              
292             # put back Getopt::Long previous configuration, if needed
293 13         88     Getopt::Long::Configure( $glc );
294              
295 13         386     return $output;
296             }
297              
298             # Perl highlighting, thanks to PPI::HTML
299             sub perl_ppi_filter {
300 12   100 12 1 67     my ($code, $opts) = ( shift, shift || '');
301              
302             # PPI::HTML options
303 12 50       40     my %ppi_opt = map { !/=/ && s/$/=1/ ; split /=/, $_, 2 } split / /, $opts;
  2         10  
  2         10  
304              
305             # create PPI::HTML syntax highlighter
306 12   66     76     my $highlighter = $filter_parser{ppi}{$opts} ||= PPI::HTML->new(%ppi_opt);
307              
308             # highlight the code and clean up the resulting HTML
309 12         117     my $pretty = $highlighter->html(\$code);
310 12         44308     $pretty =~ s/<br>$//gsm;
311              
312 12         81     return $pretty;
313             }
314              
315             # HTML highlighting thanks to Syntax::Highlight::HTML
316             sub html_filter {
317 18   100 18 1 132     my ($code, $opts) = ( shift, shift || "" );
318              
319 1         11     my $parser = $filter_parser{html}{$opts}
320 18   66     107       ||= Syntax::Highlight::HTML->new( map { (split /=/) } split ' ', $opts );
321 18         570     return _cleanup( $parser->parse($code) );
322             }
323              
324             # Shell highlighting thanks to Syntax::Highlight::Shell
325             sub shell_filter {
326 6   100 6 1 34     my ($code, $opts) = ( shift, shift || "" );
327              
328 1         8     my $parser = $filter_parser{shell}{$opts}
329 6   66     42       ||= Syntax::Highlight::Shell->new( map { (split /=/) } split ' ', $opts );
330 6         495     return _cleanup( $parser->parse($code) );
331             }
332              
333             # Kate highligthing thanks to Syntax::Highlight::Engine::Kate
334             sub kate_filter {
335 8     8 1 24     my ($code, $opts) = @_;
336 8   50     129     my ($lang) = split ' ', $opts || '';
337              
338 8   66     262     my $parser = $filter_parser{kate}{$lang}
339                   ||= Syntax::Highlight::Engine::Kate->new(
340                     language => $lang,
341                     substitutions => {
342                         '<' => '&lt;',
343                         '>' => '&gt;',
344                         '&' => '&amp;',
345                     },
346                     format_table => {
347                         Alert => [ '<span class="k-alert">', '</span>' ],
348                         BaseN => [ '<span class="k-basen">', '</span>' ],
349                         BString => [ '<span class="k-bstring">', '</span>' ],
350                         Char => [ '<span class="k-char">', '</span>' ],
351                         Comment => [ '<span class="k-comment">', '</span>' ],
352                         DataType => [ '<span class="k-datatype">', '</span>' ],
353                         DecVal => [ '<span class="k-decval">', '</span>' ],
354                         Error => [ '<span class="k-error">', '</span>' ],
355                         Float => [ '<span class="k-float">', '</span>' ],
356                         Function => [ '<span class="k-function">', '</span>' ],
357                         IString => [ '<span class="k-istring">', '</span>' ],
358                         Keyword => [ '<span class="k-keyword">', '</span>' ],
359                         Normal => [ '', '' ],
360                         Operator => [ '<span class="k-operator">', '</span>' ],
361                         Others => [ '<span class="k-others">', '</span>' ],
362                         RegionMarker => [ '<span class="k-regionmarker">', '</span>' ],
363                         Reserved => [ '<span class="k-reserved">', '</span>' ],
364                         String => [ '<span class="k-string">', '</span>' ],
365                         Variable => [ '<span class="k-variable">', '</span>' ],
366                         Warning => [ '<span class="k-warning">', '</span>' ],
367                     },
368                 );
369              
370 8         21064     return $parser->highlightText($code);
371             }
372              
373             sub wiki_filter {
374 6   100 6 1 31     my ($code, $opts) = (shift, shift || '');
375 4         31     return Text::WikiFormat::format( $code , {},
376 6         29         { map { ( split /=/ ) } split ' ', $opts } );
377             }
378              
379             sub wikimedia_filter {
380 0   0 0 1       my ($code, $opts) = (shift, shift || '');
381 0               return Text::MediawikiFormat::format( $code , {},
382 0                   { map { ( split /=/ ) } split ' ', $opts } );
383             }
384              
385             1;
386              
387             __END__
388            
389             =head1 NAME
390            
391             Pod::POM::View::HTML::Filter - Use filters on sections of your pod documents
392            
393             =cut
394            
395             =head1 SYNOPSIS
396            
397             In your POD:
398            
399             Some coloured Perl code:
400            
401             =begin filter perl
402            
403             # now in full colour!
404             $A++;
405            
406             =end filter
407            
408             =for filter=perl $A++; # this works too
409            
410             This should read C<bar bar bar>:
411            
412             =begin filter foo
413            
414             bar foo bar
415            
416             =end filter
417            
418             In your code:
419            
420             my $view = Pod::POM::View::HTML::Filter->new;
421             $view->add(
422             foo => {
423             code => sub { my $s = shift; $s =~ s/foo/bar/gm; $s },
424             # other options are available
425             }
426             );
427            
428             my $pom = Pod::POM->parse_file( '/my/pod/file' );
429             $pom->present($view);
430            
431             =begin html
432            
433             <style type="text/css">
434             <!--
435             /* HTML colouring styles */
436             .h-decl { color: #336699; font-style: italic; } /* doctype declaration */
437             .h-pi { color: #336699; } /* process instruction */
438             .h-com { color: #338833; font-style: italic; } /* comment */
439             .h-ab { color: #000000; font-weight: bold; } /* angles as tag delim. */
440             .h-tag { color: #993399; font-weight: bold; } /* tag name */
441             .h-attr { color: #000000; font-weight: bold; } /* attribute name */
442             .h-attv { color: #333399; } /* attribute value */
443             .h-ent { color: #cc3333; } /* entity */
444             .h-lno { color: #aaaaaa; background: #f7f7f7;} /* line numbers */
445            
446             /* Perl colouring styles */
447             .c { color: #228B22;} /* comment */
448             .cm { color: #000000;} /* comma */
449             .co { color: #000000;} /* colon */
450             .h { color: #CD5555; font-weight:bold;} /* here-doc-target */
451             .hh { color: #CD5555; font-style:italic;} /* here-doc-text */
452             .i { color: #00688B;} /* identifier */
453             .j { color: #CD5555; font-weight:bold;} /* label */
454             .k { color: #8B008B; font-weight:bold;} /* keyword */
455             .m { color: #FF0000; font-weight:bold;} /* subroutine */
456             .n { color: #B452CD;} /* numeric */
457             .p { color: #000000;} /* paren */
458             .pd { color: #228B22; font-style:italic;} /* pod-text */
459             .pu { color: #000000;} /* punctuation */
460             .q { color: #CD5555;} /* quote */
461             .s { color: #000000;} /* structure */
462             .sc { color: #000000;} /* semicolon */
463             .v { color: #B452CD;} /* v-string */
464             .w { color: #000000;} /* bareword */
465             -->
466             </style>
467            
468             <p>The resulting HTML will look like this (modulo the stylesheet):</p>
469            
470             <pre> <span class="c"># now in full colour!</span>
471             <span class="i">$A</span>++<span class="sc">;</span></pre>
472             <pre><span class="i">$A</span>++<span class="sc">;</span> <span class="c"># this works too</span></pre>
473             <p>This should read <code>bar bar bar</code>:</p>
474             <p>bar bar bar</p>
475            
476             =end html
477            
478             =head1 DESCRIPTION
479            
480             This module is a subclass of C<Pod::POM::View::HTML> that support the
481             C<filter> extension. This can be used in C<=begin> / C<=end> and
482             C<=for> pod blocks.
483            
484             Please note that since the view maintains an internal state, only
485             an instance of the view can be used to present the POM object.
486             Either use:
487            
488             my $view = Pod::POM::View::HTML::Filter->new;
489             $pom->present( $view );
490            
491             or
492            
493             $Pod::POM::DEFAULT_VIEW = Pod::POM::View::HTML::Filter->new;
494             $pom->present;
495            
496             Even though the module was specifically designed
497             for use with C<Perl::Tidy>, you can write your own filters quite
498             easily (see L<Writing your own filters>).
499            
500             =head1 FILTERING POD?
501            
502             The whole idea of this module is to take advantage of all the syntax
503             colouring modules that exist (actually, C<Perl::Tidy> was my first target)
504             to produce colourful code examples in a POD document (after conversion
505             to HTML).
506            
507             Filters can be used in two different POD constructs:
508            
509             =over 4
510            
511             =item C<=begin filter I<filter>>
512            
513             The data in the C<=begin filter> ... C<=end filter> region is passed to
514             the filter and the result is output in place in the document.
515            
516             The general form of a C<=begin filter> block is as follow:
517            
518             =begin filter lang optionstring
519            
520             # some text to process with filter "lang"
521            
522             =end filter
523            
524             The optionstring is trimed for whitespace and passed as a single string
525             to the filter routine which must perform its own parsing.
526            
527             =item C<=for filter=I<filter>>
528            
529             C<=for> filters work just like C<=begin>/C=<end> filters, except that
530             a single paragraph is the target.
531            
532             The general form of a C<=for filter> block is as follow:
533            
534             =for filter=lang:option1:option2
535             # some code in language lang
536            
537             The option string sent to the filter C<lang> would be C<option1 option2>
538             (colons are replaced with spaces).
539            
540             =back
541            
542             =head2 Options
543            
544             Some filters may accept options that alter their behaviour.
545             Options are separated by whitespace, and appear after the name of the
546             filter. For example, the following code will be rendered in colour and
547             with line numbers:
548            
549             =begin filter perl -nnn
550            
551             $a = 123;
552             $b = 3;
553             print $a * $b; # prints 369
554             print $a x $b; # prints 123123123
555            
556             =end filter
557            
558             C<=for> filters can also accept options, but the syntax is less clear.
559             (This is because C<=for> expects the I<formatname> to match C<\S+>.)
560            
561             The syntax is the following:
562            
563             =for filter=html:nnn=1
564             <center><img src="camel.png" />
565             A camel</center>
566            
567             In summary, options are separated by space for C<=begin> blocks and by
568             colons for C<=for> paragraphs.
569            
570             The options and their paramater depend on the filter, but they cannot contain
571             the pipe (C<|>) or colon (C<:>) character, for obvious reasons.
572            
573             =head2 Pipes
574            
575             Having filter to modify a block of text is usefule, but what's more useful
576             (and fun) than a filter? Answer: a stack of filters piped together!
577            
578             Take the imaginary filters C<foo> (which does a simple C<s/foo/bar/g>)
579             and C<bang> (which does an even simpler C<tr/r/!/>). The following block
580            
581             =begin filter foo|bar
582            
583             foo bar baz
584            
585             =end
586            
587             will become C<ba! ba! baz>.
588            
589             And naturally,
590            
591             =for filter=bar|foo
592             foo bar baz
593            
594             will return C<bar ba! baz>.
595            
596             =head2 A note on verbatim and text blocks
597            
598             B<Note:> The fact that I mention I<verbatim> and I<paragraph> in
599             this section is due to an old bug in C<Pod::POM>, which parses the
600             content of C<begin>/C<end> sections as the usual POD paragraph
601             and verbatim blocks. This is a bug in C<Pod::POM>, around which
602             C<Pod::POM::View::HTML::Filter> tries to work around.
603            
604             As from version 0.06, C<Pod::POM::View::HTML::Filter> gets to the
605             original text contained in the C<=begin> / C<=end> block (it was
606             easier than I thought, actually) and put that string throught all
607             the filters.
608            
609             If any filter in the stack is defined as C<verbatim>, or if C<Pod::POM>
610             detect any block in the C<=begin> / C<=end> block as verbatim, then
611             the output will be produced between C<< <pre> >> and C<< </pre> >> tags.
612             Otherwise, no special tags will be added (his is left to the formatter).
613            
614             =head2 Examples
615            
616             An example of the power of pipes can be seen in the following example.
617             Take a bit of Perl code to colour:
618            
619             =begin filter perl
620            
621             "hot cross buns" =~ /cross/;
622             print "Matched: <$`> $& <$'>\n"; # Matched: <hot > cross < buns>
623             print "Left: <$`>\n"; # Left: <hot >
624             print "Match: <$&>\n"; # Match: <cross>
625             print "Right: <$'>\n"; # Right: < buns>
626            
627             =end
628            
629             This will produce the following HTML code:
630            
631             <pre> <span class="q">&quot;hot cross buns&quot;</span> =~ <span class="q">/cross/</span><span class="sc">;</span>
632             <span class="k">print</span> <span class="q">&quot;Matched: &lt;$`&gt; $&amp; &lt;$'&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Matched: &lt;hot &gt; cross &lt; buns&gt;</span>
633             <span class="k">print</span> <span class="q">&quot;Left: &lt;$`&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Left: &lt;hot &gt;</span>
634             <span class="k">print</span> <span class="q">&quot;Match: &lt;$&amp;&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Match: &lt;cross&gt;</span>
635             <span class="k">print</span> <span class="q">&quot;Right: &lt;$'&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Right: &lt; buns&gt;</span></pre>
636            
637             =begin html
638            
639             <p>Which your browser will render as:</p>
640            
641             <pre> <span class="q">&quot;hot cross buns&quot;</span> =~ <span class="q">/cross/</span><span class="sc">;</span>
642             <span class="k">print</span> <span class="q">&quot;Matched: &lt;$`&gt; $&amp; &lt;$'&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Matched: &lt;hot &gt; cross &lt; buns&gt;</span>
643             <span class="k">print</span> <span class="q">&quot;Left: &lt;$`&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Left: &lt;hot &gt;</span>
644             <span class="k">print</span> <span class="q">&quot;Match: &lt;$&amp;&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Match: &lt;cross&gt;</span>
645             <span class="k">print</span> <span class="q">&quot;Right: &lt;$'&gt;\n&quot;</span><span class="sc">;</span> <span class="c"># Right: &lt; buns&gt;</span></pre>
646            
647             =end html
648            
649             Now if you want to colour and number the HTML code produced, it's as simple
650             as tackling the C<html> on top of the C<perl> filter:
651            
652             =begin filter perl | html nnn=1
653            
654             "hot cross buns" =~ /cross/;
655             print "Matched: <$`> $& <$'>\n"; # Matched: <hot > cross < buns>
656             print "Left: <$`>\n"; # Left: <hot >
657             print "Match: <$&>\n"; # Match: <cross>
658             print "Right: <$'>\n"; # Right: < buns>
659            
660             =end
661            
662             Which produces the rather unreadable piece of HTML:
663            
664             <pre><span class="h-lno"> 1</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>hot cross buns<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> =~ <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span>/cross/<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
665             <span class="h-lno"> 2</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Matched: <span class="h-ent">&amp;lt;</span>$`<span class="h-ent">&amp;gt;</span> $<span class="h-ent">&amp;amp;</span> <span class="h-ent">&amp;lt;</span>$'<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Matched: <span class="h-ent">&amp;lt;</span>hot <span class="h-ent">&amp;gt;</span> cross <span class="h-ent">&amp;lt;</span> buns<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
666             <span class="h-lno"> 3</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Left: <span class="h-ent">&amp;lt;</span>$`<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Left: <span class="h-ent">&amp;lt;</span>hot <span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
667             <span class="h-lno"> 4</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Match: <span class="h-ent">&amp;lt;</span>$<span class="h-ent">&amp;amp;</span><span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Match: <span class="h-ent">&amp;lt;</span>cross<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
668             <span class="h-lno"> 5</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Right: <span class="h-ent">&amp;lt;</span>$'<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Right: <span class="h-ent">&amp;lt;</span> buns<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span></pre>
669            
670             =begin html
671            
672             <p>But your your browser will render it as:</p>
673            
674            
675             <pre><span class="h-lno"> 1</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>hot cross buns<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> =~ <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span>/cross/<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
676             <span class="h-lno"> 2</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Matched: <span class="h-ent">&amp;lt;</span>$`<span class="h-ent">&amp;gt;</span> $<span class="h-ent">&amp;amp;</span> <span class="h-ent">&amp;lt;</span>$'<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Matched: <span class="h-ent">&amp;lt;</span>hot <span class="h-ent">&amp;gt;</span> cross <span class="h-ent">&amp;lt;</span> buns<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
677             <span class="h-lno"> 3</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Left: <span class="h-ent">&amp;lt;</span>$`<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Left: <span class="h-ent">&amp;lt;</span>hot <span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
678             <span class="h-lno"> 4</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Match: <span class="h-ent">&amp;lt;</span>$<span class="h-ent">&amp;amp;</span><span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Match: <span class="h-ent">&amp;lt;</span>cross<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span>
679             <span class="h-lno"> 5</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"k</span>"<span class="h-ab">&gt;</span>print<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"q</span>"<span class="h-ab">&gt;</span><span class="h-ent">&amp;quot;</span>Right: <span class="h-ent">&amp;lt;</span>$'<span class="h-ent">&amp;gt;</span>\n<span class="h-ent">&amp;quot;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span><span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"sc</span>"<span class="h-ab">&gt;</span>;<span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span> <span class="h-ab">&lt;</span><span class="h-tag">span</span> <span class="h-attr">class</span>=<span class="h-attv">"c</span>"<span class="h-ab">&gt;</span># Right: <span class="h-ent">&amp;lt;</span> buns<span class="h-ent">&amp;gt;</span><span class="h-ab">&lt;/</span><span class="h-tag">span</span><span class="h-ab">&gt;</span></pre>
680            
681             =end html
682            
683             =head2 Caveats
684            
685             There were a few things to keep in mind when mixing verbatim and text paragraphs
686             in a C<=begin> block. These problems do not exist any more as from version
687             0.06.
688            
689             =over 4
690            
691             =item Text paragraphs are not processed for POD escapes any more
692            
693             Because the C<=begin> / C<=end> block is now processed as a single
694             string of text, the following block:
695            
696             =begin filter html
697            
698             B<foo>
699            
700             =end
701            
702             will not be transformed into C< <b>foo</b> > before being passed to the
703             filters, but will produce the expected:
704            
705             <pre>B<span class="h-ab">&lt;</span><span class="h-tag">foo</span><span class="h-ab">&gt;</span></pre>
706            
707             =begin html
708            
709             <p>This will be rendered by your web browser as:</p>
710            
711             <pre>B<span class="h-ab">&lt;</span><span class="h-tag">foo</span><span class="h-ab">&gt;</span></pre>
712            
713             =end html
714            
715             And the same text in a verbatim block
716            
717             =begin filter html
718            
719             B<foo>
720            
721             =end
722            
723             will produce the same results.
724            
725             <pre> B<span class="h-ab">&lt;</span><span class="h-tag">foo</span><span class="h-ab">&gt;</span></pre>
726            
727             =begin html
728            
729             <p>Which a web browser will render as:</p>
730            
731             <pre> B<span class="h-ab">&lt;</span><span class="h-tag">foo</span><span class="h-ab">&gt;</span></pre>
732            
733             =end html
734            
735             Which looks quite the same, doesn't it?
736            
737             =item Separate paragraphs aren't filtered separately any more
738            
739             As seen in L<A note on verbatim and text blocks>, the filter now processes
740             the begin block as a single string of text. So, if you have a filter
741             that replace each C<*> character with an auto-incremented number in
742             square brackets, like this:
743            
744             $view->add(
745             notes => {
746             code => sub {
747             my ( $text, $opt ) = @_;
748             my $n = $opt =~ /(\d+)/ ? $1 : 1;
749             $text =~ s/\*/'[' . $n++ . ']'/ge;
750             $text;
751             }
752             }
753             );
754            
755             And you try to process the following block:
756            
757             =begin filter notes 2
758            
759             TIMTOWDI*, but your library should DWIM* when possible.
760            
761             You can't always claims that PICNIC*, can you?
762            
763             =end filter
764            
765             You'll get the expected result (contrary to previous versions):
766            
767             <p>TIMTOWDI[2], but your library should DWIM[3] when possible.
768            
769             You can't always claims that PICNIC[4], can you?</p>
770            
771             The filter was really called only once, starting at C<2>, just like requested.
772            
773             Future versions of C<Pod::POM::View::HTML::Filter> I<may> support
774             C<init>, C<begin> and C<end> callbacks to run filter initialisation and
775             clean up code.
776            
777             =back
778            
779             =head1 METHODS
780            
781             =head2 Public methods
782            
783             The following methods are available:
784            
785             =over 4
786            
787             =item C<< add( lang => { I<options> }, ... ) >>
788            
789             Add support for one or more languages. Options are passed in a hash
790             reference.
791            
792             The required C<code> option is a reference to the filter routine. The
793             filter must take a string as its only argument and return the formatted
794             HTML string (coloured accordingly to the language grammar, hopefully).
795            
796             Available options are:
797            
798             Name Type Content
799             ---- ---- -------
800            
801             code CODEREF filter implementation
802            
803             verbatim BOOLEAN if true, force the full content of the
804             =begin/=end block to be passed verbatim
805             to the filter
806            
807             requires ARRAYREF list of required modules for this filter
808            
809             Note that C<add()> is both a class and an instance method.
810            
811             When used as a class method, the new language is immediately available
812             for all future and existing instances.
813            
814             When used as an instance method, the new language is only available for
815             the instance itself.
816            
817             =item C<delete( $lang )>
818            
819             Remove the given language from the list of class or instance filters.
820             The deleted filter is returned by this method.
821            
822             C<delete()> is both a class and an instance method, just like C<add()>.
823            
824             =item C<filters()>
825            
826             Return the list of languages supported.
827            
828             =item C<know( I<$lang> )>
829            
830             Return true if the view knows how to handle language C<$lang>.
831            
832             =back
833            
834             =head2 Overloaded methods
835            
836             The following C<Pod::POM::View::HTML> methods are overridden in
837             C<Pod::POM::View::HTML::Filter>:
838            
839             =over 4
840            
841             =item C<new()>
842            
843             The overloaded constructor initialises some internal structures.
844             This means that you'll have to use a instance of the class as a
845             view for your C<Pod::POM> object. Therefore you must use C<new>.
846            
847             $Pod::POM::DEFAULT_VIEW = 'Pod::POM::View::HTML::Filter'; # WRONG
848             $pom->present( 'Pod::POM::View::HTML::Filter' ); # WRONG
849            
850             # this is CORRECT
851             $Pod::POM::DEFAULT_VIEW = Pod::POM::View::HTML::Filter->new;
852            
853             # this is also CORRECT
854             my $view = Pod::POM::View::HTML::Filter->new;
855             $pom->present( $view );
856            
857             The only option at this time is C<auto_unindent>, which is enabled by
858             default. This option remove leading indentation from all verbatim blocks
859             within the begin blocks, and put it back after highlighting.
860            
861             =item C<view_begin()>
862            
863             =item C<view_for()>
864            
865             These are the methods that support the C<filter> format.
866            
867             =back
868            
869             =head1 FILTERS
870            
871             =head2 Built-in filters
872            
873             C<Pod::POM::View::HTML::Filter> is shipped with a few built-in filters.
874            
875             The name for the filter is obtained by removing C<_filter> from the
876             names listed below (except for C<default>):
877            
878             =over 4
879            
880             =item default
881            
882             This filter is called when the required filter is not known by
883             C<Pod::POM::View::HTML::Filter>. It does nothing more than normal POD
884             processing (POD escapes for text paragraphs and C<< <pre> >> for
885             verbatim paragraphs.
886            
887             You can use the C<delete()> method to remove a filter and therefore
888             make it behave like C<default>.
889            
890             =item perl_tidy_filter
891            
892             This filter does Perl syntax highlighting with a lot of help from
893             C<Perl::Tidy>.
894            
895             It accepts options to C<Perl::Tidy>, such as C<-nnn> to number lines of
896             code. Check C<Perl::Tidy>'s documentation for more information about
897             those options.
898            
899             =item perl_ppi_filter
900            
901             This filter does Perl syntax highlighting using C<PPI::HTML>, which is
902             itself based on the incredible C<PPI>.
903            
904             It accepts the same options as C<PPI::HTML>, which at this time solely
905             consist of C<line_numbers> to, as one may guess, add line numbers to the
906             output.
907            
908             =item html_filter
909            
910             This filter does HTML syntax highlighting with the help of
911             C<Syntax::Highlight::HTML>.
912            
913             The filter supports C<Syntax::Highlight::HTML> options:
914            
915             =begin filter html nnn=1
916            
917             <p>The lines of the HTML code will be numbered.</p>
918             <p>This is line 2.</p>
919            
920             =end filter
921            
922             See C<Syntax::Highlight::HTML> for the list of supported options.
923            
924             =item shell_filter
925            
926             This filter does shell script syntax highlighting with the help of
927             C<Syntax::Highlight::Shell>.
928            
929             The filter supports C<Syntax::Highlight::Shell> options:
930            
931             =begin filter shell nnn=1
932            
933             #!/bin/sh
934             echo "This is a foo test" | sed -e 's/foo/shell/'
935            
936             =end filter
937            
938             See C<Syntax::Highlight::Shell> for the list of supported options.
939            
940             =item kate_filter
941            
942             This filter support syntax highlighting for numerous languages
943             with the help of C<Syntax::Highlight::Engine::Kate>.
944            
945             The filter supports C<Syntax::Highlight::Engine::Kate> languages as options:
946            
947             =begin filter kate Diff
948            
949             Index: lib/Pod/POM/View/HTML/Filter.pm
950             ===================================================================
951             --- lib/Pod/POM/View/HTML/Filter.pm (revision 99)
952             +++ lib/Pod/POM/View/HTML/Filter.pm (working copy)
953             @@ -27,6 +27,11 @@
954             requires => [qw( Syntax::Highlight::Shell )],
955             verbatim => 1,
956             },
957             + kate => {
958             + code => \&kate_filter,
959             + requires => [qw( Syntax::Highlight::Engine::Kate )],
960             + verbatim => 1,
961             + },
962             );
963            
964             my $HTML_PROTECT = 0;
965            
966             =end filter
967            
968             Check the C<Syntax::Highlight::Engine::Kate> documentation for the full
969             list of supported languages. Please note that some of them aren't well
970             supported yet (by C<Syntax::Highlight::Engine::Kate>), so the output
971             may not be what you expect.
972            
973             Here is a list of languages we have successfully tested with
974             C<Syntax::Highlight::Engine::Kate> version 0.02:
975             C<C>, C<Diff>, C<Fortran>, C<JavaScript>, C<LDIF>, C<SQL>.
976            
977             =item wiki_filter
978            
979             This filter converts the wiki format parsed by C<Text::WikiFormat>
980             in HTML.
981            
982             The supported options are: C<prefix>, C<extended>, C<implicit_links>,
983             C<absolute_links>. The option and value are separated by a C<=> character,
984             as in the example below:
985            
986             =begin filter wiki extended=1
987            
988             [link|title]
989            
990             =end
991            
992             =item wikimedia_filter
993            
994             This filter converts the wiki format parsed by C<Text::MediawikiFormat>
995             in HTML.
996            
997             The supported options are: C<prefix>, C<extended>, C<implicit_links>,
998             C<absolute_links> and C<process_html>. The option and value are separated
999             by a C<=> character.
1000            
1001             =back
1002            
1003             =head2 Writing your own filters
1004            
1005             Write a filter is quite easy: a filter is a subroutine that takes two
1006             arguments (text to parse and option string) and returns the filtered
1007             string.
1008            
1009             The filter is added to C<Pod::POM::View::HTML::Filter>'s internal filter
1010             list with the C<add()> method:
1011            
1012             $view->add(
1013             foo => {
1014             code => \&foo_filter,
1015             requires => [],
1016             }
1017             );
1018            
1019             When presenting the following piece of pod,
1020            
1021             =begin filter foo bar baz
1022            
1023             Some text to filter.
1024            
1025             =end filter
1026            
1027             the C<foo_filter()> routine will be called with two arguments, like this:
1028            
1029             foo_filter( "Some text to filter.", "bar baz" );
1030            
1031             If you have a complex set of options, your routine will have to parse
1032             the option string by itself.
1033            
1034             Please note that in a C<=for> construct, whitespace in the option string
1035             must be replaced with colons:
1036            
1037             =for filter=foo:bar:baz Some text to filter.
1038            
1039             The C<foo_filter()> routine will be called with the same two arguments
1040             as before.
1041            
1042             =head1 BUILT-IN FILTERS CSS STYLES
1043            
1044             Each filter uses its own CSS classes, so that one can define their
1045             favourite colours in a custom CSS file.
1046            
1047             =head2 C<perl> filter
1048            
1049             C<Perl::Tidy>'s HTML code looks like:
1050            
1051             <span class="i">$A</span>++<span class="sc">;</span>
1052            
1053             Here are the classes used by C<Perl::Tidy>:
1054            
1055             n numeric
1056             p paren
1057             q quote
1058             s structure
1059             c comment
1060             v v-string
1061             cm comma
1062             w bareword
1063             co colon
1064             pu punctuation
1065             i identifier
1066             j label
1067             h here-doc-target
1068             hh here-doc-text
1069             k keyword
1070             sc semicolon
1071             m subroutine
1072             pd pod-text
1073            
1074             =head2 C<ppi> filter
1075            
1076             C<PPI::HTML> uses the following CSS classes:
1077            
1078             comment
1079             double
1080             heredoc_content
1081             interpolate
1082             keyword for language keywords (my, use
1083             line_number
1084             number
1085             operator for language operators
1086             pragma for pragmatas (strict, warnings)
1087             single
1088             structure for syntaxic symbols
1089             substitute
1090             symbol
1091             word for module, function and method names
1092             words
1093             match
1094            
1095             =head2 C<html> filter
1096            
1097             C<Syntax::Highlight::HTML> makes use of the following classes:
1098            
1099             h-decl declaration # declaration <!DOCTYPE ...>
1100             h-pi process # process instruction <?xml ...?>
1101             h-com comment # comment <!-- ... -->
1102             h-ab angle_bracket # the characters '<' and '>' as tag delimiters
1103             h-tag tag_name # the tag name of an element
1104             h-attr attr_name # the attribute name
1105             h-attv attr_value # the attribute value
1106             h-ent entity # any entities: &eacute; &#171;
1107            
1108             =head2 C<shell> filter
1109            
1110             C<Syntax::Highlight::Shell> makes use of the following classes:
1111            
1112             s-key # shell keywords (like if, for, while, do...)
1113             s-blt # the builtins commands
1114             s-cmd # the external commands
1115             s-arg # the command arguments
1116             s-mta # shell metacharacters (|, >, \, &)
1117             s-quo # the single (') and double (") quotes
1118             s-var # expanded variables: $VARIABLE
1119             s-avr # assigned variables: VARIABLE=value
1120             s-val # shell values (inside quotes)
1121             s-cmt # shell comments
1122            
1123             =head2 C<kate> filter
1124            
1125             Output formatted with C<Syntax::Highlight::Engine::Kate> makes use
1126             of the following classes:
1127            
1128             k-alert # Alert
1129             k-basen # BaseN
1130             k-bstring # BString
1131             k-char # Char
1132             k-comment # Comment
1133             k-datatype # DataType
1134             k-decval # DecVal
1135             k-error # Error
1136             k-float # Float
1137             k-function # Function
1138             k-istring # IString
1139             k-keyword # Keyword
1140             k-normal # Normal
1141             k-operator # Operator
1142             k-others # Others
1143             k-regionmarker # RegionMarker
1144             k-reserved # Reserved
1145             k-string # String
1146             k-variable # Variable
1147             k-warning # Warning
1148            
1149             =head1 HISTORY
1150            
1151             The goal behind this module was to produce nice looking HTML pages from the
1152             articles the French Perl Mongers are writing for the French magazine
1153             GNU/Linux Magazine France (L<http://www.linuxmag-france.org/>).
1154            
1155             The resulting web pages can be seen at
1156             L<http://articles.mongueurs.net/magazines/>.
1157            
1158             =head1 AUTHOR
1159            
1160             Philippe "BooK" Bruhat, C<< <book@cpan.org> >>
1161            
1162             =head1 THANKS
1163            
1164             Many thanks to Sébastien Aperghis-Tramoni (Maddingue), who helped
1165             debugging the module and wrote C<Syntax::Highlight::HTML> and
1166             C<Syntax::Highlight::Shell> so that I could ship PPVHF with more than
1167             one filter. He also pointed me to C<Syntax::Highlight::Engine::Kate>,
1168             which led me to clean up PPVHF before adding support for SHEK.
1169            
1170             Perl code examples where borrowed in Amelia,
1171             aka I<Programming Perl, 3rd edition>.
1172            
1173             =head1 TODO
1174            
1175             There are a few other syntax highlighting modules on CPAN, which I should
1176             try to add support for in C<Pod::POM::View::HTML::Filter>:
1177            
1178             =over 4
1179            
1180             =item *
1181            
1182             C<Syntax::Highlight::Universal>
1183            
1184             =item *
1185            
1186             C<Syntax::Highlight::Mason>
1187            
1188             =item *
1189            
1190             C<Syntax::Highlight::Perl> (seems old)
1191            
1192             =item *
1193            
1194             C<Syntax::Highlight::Perl::Improved>
1195            
1196             =back
1197            
1198             =head1 BUGS
1199            
1200             Please report any bugs or feature requests to
1201             C<bug-pod-pom-view-html-filter@rt.cpan.org>, or through the web interface at
1202             L<http://rt.cpan.org>. I will be notified, and then you'll automatically
1203             be notified of progress on your bug as I make changes.
1204            
1205             =head1 COPYRIGHT & LICENSE
1206            
1207             Copyright 2004 Philippe "BooK" Bruhat, All Rights Reserved.
1208            
1209             This program is free software; you can redistribute it and/or modify it
1210             under the same terms as Perl itself.
1211            
1212             =cut
1213            
1214