File Coverage

blib/lib/Pod/HtmlEasy.pm
Criterion Covered Total %
statement 286 322 88.8
branch 94 128 73.4
condition 14 23 60.8
subroutine 43 46 93.4
pod 6 30 20.0
total 443 549 80.6


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: HtmlEasy.pm
3             ## Purpose: Pod::HtmlEasy
4             ## Author: Graciliano M. P.
5             ## Modified by: Geoffrey Leach
6             ## Created: 2004-01-11
7             ## Updated: 2011-08-13
8             ## Copyright: (c) 2004 Graciliano M. P. (c) 2007 - 2013 Geoffrey Leach
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12              
13             package Pod::HtmlEasy;
14 4     4   621095 use 5.006003;
  4         16  
  4         185  
15              
16 4     4   23 use strict;
  4         6  
  4         150  
17 4     4   21 use warnings;
  4         11  
  4         139  
18              
19 4     4   3460 use Pod::HtmlEasy::Parser;
  4         13  
  4         317  
20             use Pod::HtmlEasy::Data
21 4     4   32 qw( EMPTY NL NUL TRUE FALSE body css gen head headend title top toc toc_tag podon podoff );
  4         7  
  4         543  
22 4     4   23 use Carp;
  4         9  
  4         267  
23 4     4   78 use English qw{ -no_match_vars };
  4         8  
  4         35  
24 4     4   3399 use File::Slurp;
  4         15838  
  4         312  
25 4     4   27 use Pod::Parser; # Just for its VERSION
  4         6  
  4         130  
26 4     4   21 use Readonly;
  4         6  
  4         169  
27 4     4   23 use Regexp::Common qw{ whitespace };
  4         7  
  4         36  
28              
29 4     4   4386 use version;
  4         10082  
  4         29  
30             our $VERSION = version->declare("v1.1.11"); # Also appears in "=head1 VERSION" in the POD below
31              
32             ########
33             # VARS #
34             ########
35              
36             Readonly::Scalar my $NUL => NUL;
37             Readonly::Scalar my $TITLE_TEXT_LOC => -2;
38             Readonly::Scalar my $DEFAULT_INDEX_LENGTH => 60;
39              
40             # This keeps track of valid options
41             Readonly::Hash my %OPTS => (
42             body => 1,
43             css => 1,
44             index => 1,
45             index_item => 1,
46             index_length => 1,
47             output => 1,
48             no_css => 1,
49             no_generator => 1,
50             no_index => 1,
51             only_content => 1,
52             parserwarn => 1,
53             title => 1,
54             top => 1,
55             );
56              
57             #######################
58             # _ORGANIZE_CALLBACKS #
59             #######################
60              
61             sub _organize_callbacks {
62 5     5   12 my $this = shift;
63              
64 5         42 $this->{ON_B} = \&evt_on_b;
65 5         20 $this->{ON_C} = \&evt_on_c;
66 5         19 $this->{ON_E} = \&evt_on_e;
67 5         19 $this->{ON_F} = \&evt_on_f;
68 5         16 $this->{ON_I} = \&evt_on_i;
69 5         18 $this->{ON_L} = \&evt_on_l;
70 5         18 $this->{ON_S} = \&evt_on_s;
71 5         19 $this->{ON_X} = \&evt_on_x; # [20078]
72 5         17 $this->{ON_Z} = \&evt_on_z;
73              
74 5         17 $this->{ON_HEAD1} = \&evt_on_head1;
75 5         18 $this->{ON_HEAD2} = \&evt_on_head2;
76 5         16 $this->{ON_HEAD3} = \&evt_on_head3;
77 5         15 $this->{ON_HEAD4} = \&evt_on_head4;
78              
79 5         17 $this->{ON_VERBATIM} = \&evt_on_verbatim;
80 5         13 $this->{ON_TEXTBLOCK} = \&evt_on_textblock;
81              
82 5         26 $this->{ON_OVER} = \&evt_on_over;
83 5         15 $this->{ON_ITEM} = \&evt_on_item;
84 5         17 $this->{ON_BACK} = \&evt_on_back;
85              
86 5         13 $this->{ON_FOR} = \&evt_on_for;
87 5         17 $this->{ON_BEGIN} = \&evt_on_begin;
88 5         15 $this->{ON_END} = \&evt_on_end;
89              
90 5         19 $this->{ON_URI} = \&evt_on_uri;
91              
92 5         15 $this->{ON_ERROR} = \&evt_on_error;
93              
94 5         11 return;
95             }
96              
97             #######
98             # NEW #
99             #######
100              
101             sub new {
102 5     5 0 9288 my ( $this, %args ) = @_;
103 5 50       31 return $this if ref $this;
104 5   50     23 my $class = $this || __PACKAGE__;
105 5         21 $this = bless {}, $class;
106              
107 5         35 _organize_callbacks($this);
108              
109 5         24 foreach my $key ( keys %args ) {
110              
111             # Add in any ON_ callbacks
112 1 50       10 if ( $key =~ m{^on_(\w+)$}ismx ) {
    0          
113 1         5 my $cmd = uc $1;
114 1         7 $this->{qq{ON_$cmd}} = $args{$key};
115             }
116             elsif ( $key =~ m{^(?:=(\w+)|(\w)<>)$}smx ) {
117 0   0     0 my $cmd = uc $1 || $2;
118 0         0 $this->{$cmd} = $args{$key};
119             }
120             }
121              
122 5         20 return $this;
123             }
124              
125             ############
126             # POD2HTML #
127             ############
128              
129             sub pod2html { ## no critic (ProhibitExcessComplexity)
130 48     48 1 22427 my @args = @_;
131 48         101 my $this = shift @args;
132              
133             # The first argument is either the input file or an option,
134             # In the latter case, input must be coming from STDIN
135 48         92 my $pod = shift @args;
136 48 50       616 if ( exists $OPTS{$pod} ) {
137              
138             # Oops, its an arg;
139 0         0 unshift @args, $pod;
140 0         0 $pod = q{-};
141             }
142              
143             # If the following assignment is to work, we must have pairs in @args
144 48 50       583 if ( @args & 1 ) {
145 0         0 carp q{All options must be paired with values};
146 0         0 exit 1;
147             }
148 48         188 my %args = @args;
149              
150             # Check options for validity
151 48         164 foreach my $key ( keys %args ) {
152 164 50       1272 if ( not exists $OPTS{$key} ) {
153 0         0 carp qq{option $key is not supported};
154             }
155             }
156              
157 48         373 my $save;
158 48 100       161 if ( exists $args{output} ) { $save = $args{output}; }
  1         44  
159              
160             # Personal pecularity: I hate double negatives, and perlcritic hates unless
161 48         70 my ( $do_css, $do_generator, $do_index, $do_content );
162 48 100       252 if ( not exists $args{no_css} ) { $do_css = 1; }
  4         8  
163 48 100       165 if ( not exists $args{no_generator} ) { $do_generator = 1; }
  7         16  
164 48 100       264 if ( not exists $args{no_index} ) { $do_index = 1; }
  38         55  
165 48 100       180 if ( not exists $args{only_content} ) { $do_content = 1; }
  46         67  
166              
167             # This will fall through to Pod::Parser::new
168             # which is the base for Pod::HtmlEasy::Parser.
169             # Pod::HtmlEasy::Parser does not implement new()
170 48         1220 my $parser = Pod::HtmlEasy::Parser->new();
171              
172             $parser->errorsub(
173             sub { ## no critic (ProtectPrivateSubs)
174 0     0   0 Pod::HtmlEasy::Parser::_errors( $parser, @_ );
175             }
176 48         672 );
177              
178             # Pod::Parser wiii complain about multiple blank lines in INDEX_ITEM,
179             # which is moderately annoying
180 48 50       160 if ( exists $args{parserwarn} ) { $parser->parseopts( -warnings => 1 ); }
  0         0  
181              
182             # This allows us to search for non-POD stuff is preprocess_paragraph
183             # my $VERSION ..., for example
184 48         866 $parser->parseopts( -want_nonPODs => 1 );
185              
186             # This puts a subsection in the $parser hash that will record data
187             # that is "local" to this code. Throughout, $parser will refer to
188             # Pod::Parser and $this to Pod::HtmlEasy
189 48         125 $parser->{POD_HTMLEASY} = $this;
190              
191 48 100       164 if ( exists $args{index_item} ) {
192 10         26 $parser->{INDEX_ITEM} = 1;
193 10 100       55 $parser->{INDEX_LENGTH}
194             = exists $args{index_length}
195             ? $args{index_length}
196             : $DEFAULT_INDEX_LENGTH;
197             }
198              
199             # This is where we accumulate the results of Pod::Parser
200 48         71 my @output;
201 48         155 $parser->{POD_HTMLEASY}->{HTML} = \@output;
202              
203 48         350 my $title = $args{title};
204              
205 48 100       151 if ( ref $pod eq q{GLOB} ) { # $pod is an open file handle
206 2 50       7 if ( not defined $title ) { $title = q{}; }
  2         16  
207             }
208             else {
209 46 50 33     999 if ( ( !-e $pod ) && ( $pod ne q{-} ) ) {
210 0         0 carp qq{No file $pod};
211 0         0 exit 1;
212             }
213 46 50       128 if ( not defined $title ) {
214 0 0       0 $title = defined $save ? $save : $pod eq q{-} ? q{STDIN} : $pod;
    0          
215             }
216             }
217              
218             # Build the header to the HTML file
219 48         115 my ( @html, $title_line_ref );
220 48 100       273 if ( defined $do_content ) { # [31784]
221 46         177 push @html, head();
222              
223             # We assume here that Pod::Parser is always at the same level as the main
224 46 100       137 if ( defined $do_generator ) {
225 6         39 push @html, gen( $VERSION, $Pod::Parser::VERSION );
226             }
227              
228 46         154 push @html, title($title);
229              
230             # Save pointer for later, in case title gets replaced
231             # NB: index depends on the structure of the returned HTML
232 46         138 $title_line_ref = \$html[$TITLE_TEXT_LOC];
233              
234 46 100       132 if ( defined $do_css ) { push @html, css( $args{css} ); }
  3         12  
235              
236 46         130 push @html, headend;
237              
238 46         270 push @html, body( $args{body} );
239             }
240              
241 48         145 delete $this->{UPARROW};
242 48         105 delete $this->{UPARROW_FILE};
243 48 100       145 if ( exists $args{top} ) {
244 2         8 push @html, top;
245              
246             # Checking for the file is the only way I know of to distinguish
247 2 100       22 if ( -e $args{top} ) { $this->{UPARROW_FILE} = $args{top}; }
  1         4  
248 1         4 else { $this->{UPARROW} = $args{top}; }
249             }
250              
251             # Avoid carry-over on multiple files
252 48         75 delete $this->{IN_BEGIN};
253 48         86 delete $this->{PACKAGE};
254 48         77 delete $this->{TITLE};
255 48         85 delete $this->{VERSION};
256 48         192 $this->{INFO_COUNT} = 0;
257              
258 48         5475 $parser->parse_from_file($pod);
259              
260             # If there's a head1 NAME, we've picked this up during processing
261             # BUT, let the caller force override of NAME content
262 48 50 66     343 if ( exists $this->{TITLE}
      100        
      66        
263             && length $this->{TITLE} > 0
264             && !exists $args{title}
265             && defined $title_line_ref )
266             {
267 0         0 ${$title_line_ref} = $this->{TITLE};
  0         0  
268             }
269              
270 48 100       177 if ( defined $do_index ) {
271 38         231 push @html, $this->_do_index( $args{index} );
272             }
273              
274 48         350 push @html, podon;
275 48         135 push @html, @output; # The pod converted to HTML
276 48 100       240 push @html, podoff( defined $args{only_content} ? 1 : undef ); # [31784]
277              
278             # Add newlines to the HTML
279 48         102 @html = map { $_ . NL } @html;
  915         1927  
280              
281 48 100       289 if ( defined $save ) {
282 1 50       77 open my $out, q{>}, $save or carp qq{Unable to open $save - $ERRNO};
283 1 50       2 print {$out} @html or carp qq{Could not write to $out};
  1         20  
284 1 50       45 close $out or carp qq{Could not close $out};
285             }
286             else {
287 47 0       156 if ( $pod eq q{-} ) { print @html or carp q{Could not print}; }
  0 50       0  
288             }
289              
290 48 100       600 return wantarray ? @html : join EMPTY, @html;
291             }
292              
293             #############
294             # _DO_INDEX #
295             #############
296              
297             sub _do_index {
298 38     38   108 my ( $this, $add ) = @_;
299              
300 38 100       90 if ( defined $add ) { return toc($add); }
  1         5  
301 37 100       63 if ( @{ $this->{INDEX} } == 0 ) { return toc(); }
  37         134  
  19         71  
302              
303 18         118 my @index;
304 18         37 my $index_ref = $this->{INDEX};
305 18         30 my $cur_level = 1;
306 18         68 my $doing_item = FALSE;
307 18         29 while ( my $index_element = shift @{$index_ref} ) {
  69         225  
308 51         50 my ( $level, $txt ) = @{$index_element};
  51         101  
309              
310             # Eliminate http references. This is in aid of persons who use =item to
311             # list URLs.
312 51         255 my $tag = toc_tag($txt);
313              
314             # =item lists are level 0 and generate a level change wherever they show up
315             # so, when we get a non-zero level we're indexing a non-item
316 51 100       114 if ($level) {
317 35 100       70 if ($doing_item) {
318 3         8 push @index, q{};
319 3         5 $cur_level--;
320 3         11 $doing_item = FALSE;
321             }
322              
323 35         83 while ( $level > $cur_level ) {
324 17         20 $cur_level++;
325 17         40 push @index, q{
    };
326             }
327              
328 35         77 while ( $level < $cur_level ) {
329 8         9 $cur_level--;
330 8         17 push @index, q{};
331             }
332             }
333             else {
334              
335             # Indexing an =item
336 16 100       145 if ( not $doing_item ) {
337 9         23 push @index, q{
    };
338 9         13 $cur_level++;
339 9         34 $doing_item = TRUE;
340             }
341              
342             # Strip http to conform to =item
343 16         38 $txt =~ s{\Ahttps?://}{}gmsx;
344 16         42 $tag = toc_tag($txt);
345             }
346              
347 51         199 push @index, qq{
  • $txt
  • };
    348             }
    349              
    350 18         55 while ( $cur_level > 1 ) {
    351 15         19 $cur_level--;
    352              
    353             # =item without an enclosing =head will get duplicate
      and
    s.
    354             # That's OK, because its supposed to be illegal POD.
    355 15         223 push @index, q{};
    356             }
    357              
    358             # Note LIST return. Result is pushed onto @html
    359 18         71 return ( toc(@index) );
    360             }
    361              
    362             #############
    363             # _DO_TITLE #
    364             #############
    365              
    366             sub _do_title {
    367 19     19   34 my ( $this, $txt ) = @_;
    368              
    369             # This happens only on the _first_ head1 NAME
    370 19 100 100     167 if ( ( not exists $this->{TITLE} ) and ( $txt =~ m{\ANAME}smx ) ) {
    371 7         30 my ($title) = $txt =~ m{\ANAME\s+(.*)}smx;
    372 7 100       24 if ( defined $title ) {
    373              
    374             # Oh, goody
    375 5         29 $title =~ s{$RE{ws}{crop}}{}gsmx; # delete surrounding whitespace
    376 5         646 $this->{TITLE} = $title;
    377             }
    378             else {
    379              
    380             # If we don't get anything off of NAME, it will be filled in by preprocess_paragraph()
    381 2         6 $this->{TITLE} = undef;
    382             }
    383             }
    384 19         34 return;
    385             }
    386              
    387             ##################
    388             # DEFAULT EVENTS #
    389             ##################
    390              
    391             sub evt_on_head1 {
    392 19     19 0 50 my ( $this, $txt ) = @_;
    393              
    394 19 50       58 if ( not defined $txt ) { $txt = EMPTY; }
      0         0  
    395              
    396 19         66 my $tag = toc_tag($txt);
    397              
    398 19         69 _do_title( $this, $txt );
    399              
    400             # "Go to top" is attached to =head1 if selected.
    401 19 100       76 if ( exists $this->{UPARROW} ) {
    402             return
    403 1         5 q{

    404             . NL
    405             . q{title='click to go to top of document'}
    406             . NL
    407             . qq{name='$tag'>$txt&$this->{UPARROW};};
    408             }
    409              
    410 18 100       53 if ( exists $this->{UPARROW_FILE} ) {
    411             return
    412 1         5 q{

    413             . NL
    414             . q{title='click to go to top of document'}
    415             . NL
    416             . qq{name='$tag'>$txt
    417             . NL
    418             . q{alt=⇑>};
    419             }
    420              
    421 17         100 return qq{

    $txt

    };
    422             }
    423              
    424             sub evt_on_head2 {
    425 11     11 0 23 my ( $this, $txt ) = @_;
    426              
    427 11         57 my $tag = toc_tag($txt);
    428              
    429 11         60 return qq{

    $txt

    };
    430             }
    431              
    432             sub evt_on_head3 {
    433 3     3 0 7 my ( $this, $txt ) = @_;
    434              
    435 3         12 my $tag = toc_tag($txt);
    436              
    437 3         19 return qq{

    $txt

    };
    438             }
    439              
    440             sub evt_on_head4 {
    441 3     3 0 8 my ( $this, $txt ) = @_;
    442              
    443 3         18 my $tag = toc_tag($txt);
    444              
    445 3         19 return qq{

    $txt

    };
    446             }
    447              
    448             sub evt_on_begin {
    449 2     2 0 6 my ( $this, $txt ) = @_;
    450              
    451             # We don't do any processing for =begin/=end other than ignore
    452             # However, without a command, the construct is illegal
    453             # Embedded =head, etc are also illegal, but we don't check
    454 2 100       14 if ( length $txt == 0 ) { $this->{IN_BEGIN} = 1; }
      1         4  
    455 2         11 return EMPTY;
    456             }
    457              
    458             sub evt_on_end {
    459 2     2 0 5 my ( $this, $txt ) = @_;
    460              
    461             # Ignore any commands
    462 2         6 delete $this->{IN_BEGIN};
    463 2         9 return EMPTY;
    464             }
    465              
    466             # See perlpodsec for details on interpreting the items
    467             sub evt_on_l { ## no critic (ProhibitManyArgs)
    468 42     42 0 106 my ( $this, $text, $inferred, $name, $section, $type ) = @_;
    469              
    470 42 100       106 if ( $type eq q{pod} ) {
    471 25 100       84 $section = defined $section ? qq{#$section} : EMPTY; # [6062]
    472             # Corrupt the href to avoid having it recognized (and converted) by _add_uri_href
    473 25         173 $inferred =~ s{\A(.)}{$1$NUL}smx;
    474 25         78 my $toc_tag = toc_tag($section);
    475              
    476 25 100       65 if ( defined $name ) {
    477 19         137 return qq{$inferred};
    479             }
    480 6         45 return qq{$inferred};
    481             }
    482              
    483 17 100       41 if ( $type eq q{man} ) {
    484              
    485             # $name probably looks like "foo(1)", and the () are interpreted as metachars
    486 4 100       42 if ( $inferred !~ m{\Q$name\E}msx ) { $inferred .= qq{ in $name}; }
      1         3  
    487 4         25 return qq{$inferred};
    488             }
    489 13 50       28 if ( $type eq q{url} ) {
    490              
    491             # We'll let _add_uri_href handle this.
    492 13         68 return $name;
    493             }
    494              
    495             # Unknown type
    496 0         0 return $inferred;
    497             }
    498              
    499             sub evt_on_b {
    500 3     3 0 7 my ( $this, $txt ) = @_;
    501 3         16 return qq{$txt};
    502             }
    503              
    504             sub evt_on_i {
    505 5     5 0 9 my ( $this, $txt ) = @_;
    506 5         29 return qq{$txt};
    507             }
    508              
    509             sub evt_on_c {
    510 18     18 0 34 my ( $this, $txt ) = @_;
    511 18         484 return qq{$txt};
    512             }
    513              
    514             sub evt_on_e {
    515 11     11 0 18 my ( $this, $txt ) = @_;
    516              
    517 11         27 $txt =~ s{^&}{}smx;
    518 11         19 $txt =~ s{;$}{}smx;
    519 11 50       39 if ( $txt =~ m{^\d+$}smx ) { $txt = qq{#$txt}; }
      0         0  
    520 11         45 return qq{&$txt;};
    521             }
    522              
    523             sub evt_on_f {
    524 1     1 0 2 my ( $this, $txt ) = @_;
    525 1         5 return qq{$txt};
    526             }
    527              
    528             sub evt_on_s {
    529 5     5 0 10 my ( $this, $txt ) = @_;
    530              
    531             # Eliminate newlines; dos files use \r\n
    532             # \r\n is said to be not portable
    533 5         16 $txt =~ s{[\cM\cJ]}{}gsmx;
    534 5         20 return $txt;
    535             }
    536              
    537 1     1 0 5 sub evt_on_x { return EMPTY; } # [20078]
    538              
    539 2     2 0 9 sub evt_on_z { return EMPTY; }
    540              
    541             sub evt_on_verbatim {
    542 208     208 0 307 my ( $this, $txt ) = @_;
    543              
    544 208 50       547 return if exists $this->{IN_BEGIN};
    545              
    546             # Multiple empty lines are parsed as verbatim text by Pod::Parser
    547             # And will show up as empty
     blocks, which is mucho messy 
    548             {
    549 208         316 local $RS = EMPTY;
      208         480  
    550 208         765 chomp $txt;
    551             }
    552              
    553 208 100       432 if ( not length $txt ) { return EMPTY; }
      204         528  
    554 4 50       14 if ( exists $this->{IN_ITEM} ) {
    555 0         0 delete $this->{IN_ITEM};
    556 0         0 return evt_on_item( $this, $txt );
    557             }
    558 4         19 return qq{
    $txt
    };
    559             }
    560              
    561             sub evt_on_textblock {
    562 107     107 0 178 my ( $this, $txt ) = @_;
    563 107 50       573 if ( exists $this->{IN_BEGIN} ) { return; }
      0         0  
    564 107 100       348 if ( exists $this->{IN_ITEM} ) {
    565 6         20 delete $this->{IN_ITEM};
    566 6         20 return evt_on_item( $this, $txt );
    567             }
    568 101         472 return qq{

    $txt

    };
    569             }
    570              
    571             sub evt_on_over {
    572 5     5 0 10 my ( $this, $txt ) = @_;
    573              
    574             # Note that level is ignored
    575 5         21 return q{
      };
    576             }
    577              
    578             sub evt_on_item {
    579 39     39 0 69 my ( $this, $txt ) = @_;
    580              
    581 39 100 66     165 if ( ( length($txt) == 1 ) && ( $txt !~ m{\d}msx ) ) {
    582              
    583             # Use the content for the tag
    584 6         21 $this->{IN_ITEM} = 1;
    585 6         21 return EMPTY;
    586             }
    587              
    588 33         106 my $tag = toc_tag($txt);
    589 33         173 return qq{
  • $txt
  • };
    590             }
    591              
    592 5     5 0 20 sub evt_on_back { return q{}; }
    593              
    594 1     1 0 5 sub evt_on_for { return EMPTY; }
    595              
    596             sub evt_on_error {
    597 0     0 0 0 my ( $this, $txt ) = @_;
    598 0         0 return qq{};
    599             }
    600              
    601             sub evt_on_uri {
    602 0     0 0 0 my ( $this, $uri ) = @_;
    603 0 0       0 my $target
    604             = $uri !~ m{^(?:mailto|telnet|ssh|irc):}ismx
    605             ? q{ target='_blank'}
    606             : EMPTY; # [6062]
    607 0         0 my $txt = $uri;
    608 0         0 $txt =~ s{^mailto:}{}ismx;
    609 0         0 return qq{$txt};
    610             }
    611              
    612             ##############
    613             # PM_VERSION #
    614             ##############
    615              
    616             sub pm_version {
    617 2     2 1 889 my $this = shift;
    618 2 50       8 if ( not defined $this ) {
    619 0         0 carp q{pm_version must be referenced through Pod::HtmlEasy};
    620 0         0 return;
    621             }
    622              
    623 2         10 return $this->{VERSION};
    624             }
    625              
    626             ##############
    627             # PM_PACKAGE #
    628             ##############
    629              
    630             sub pm_package {
    631 2     2 1 9 my $this = shift;
    632 2 50       8 if ( not defined $this ) {
    633 0         0 carp q{pm_package must be referenced through Pod::HtmlEasy};
    634 0         0 return;
    635             }
    636              
    637 2         9 return $this->{PACKAGE};
    638             }
    639              
    640             ###########
    641             # PM_NAME #
    642             ###########
    643              
    644             sub pm_name {
    645 2     2 1 590 my $this = shift;
    646 2 50       9 if ( not defined $this ) {
    647 0         0 carp q{pm_name must be referenced through Pod::HtmlEasy};
    648 0         0 return;
    649             }
    650 2         8 return $this->{TITLE};
    651             }
    652              
    653             ###########################
    654             # PM_PACKAGE_VERSION_NAME #
    655             ###########################
    656              
    657             sub pm_package_version_name {
    658 1     1 1 547 my $this = shift;
    659 1 50       7 if ( not defined $this ) {
    660 0         0 carp
    661             q{pm_package_version_name must be referenced through Pod::HtmlEasy};
    662 0         0 return;
    663             }
    664              
    665 1         7 return ( $this->pm_package(), $this->pm_version(), $this->pm_name() );
    666             }
    667              
    668             ################
    669             # DEFAULOT_CSS #
    670             ################
    671              
    672 1     1 1 801 sub default_css { return css(); }
    673              
    674             1;
    675              
    676             __END__