The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Pod::HtmlEasy - Generate easy and personalized HTML from PODs, without extra modules and on "the flight".

DESCRIPTION

The purpose of this module is to generate HTML data from POD in a easy and personalized mode.

By default the HTML generated is similar to the CPAN site style for module documentation.

USAGE

Simple usage:

  my $podhtml = Pod::HtmlEasy->new() ;

  my $html = $podhtml->pod2html( 'test.pod' ) ;

  print "$html\n" ;

Complete usage:

  use Pod::HtmlEasy ;

  ## Create the object and set my own events subs:
  ## ** Note that here are all the events, and examples of how to implement **
  ## ** them, and actually this are the default events, so you don't need   **
  ## ** to set everything.                                                  **

  my $podhtml = Pod::HtmlEasy->new (

  on_B         => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<b>$txt</b>" ;
                  } ,

  on_C         => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<font face='Courier New'>$txt</font>" ;
                  } ,

  on_E         => sub {
                    my ( $this , $txt ) = @_ ;
                    return '<' if $txt =~ /^lt$/i ;
                    return '>' if $txt =~ /^gt$/i ;
                    return '|' if $txt =~ /^verbar$/i ;
                    return '/' if $txt =~ /^sol$/i ;
                    return chr($txt) if $txt =~ /^\d+$/ ;
                    return $txt ;
                  } ,

  on_F         => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<b><i>$txt</i></b>" ;
                  } ,

  on_I         => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<i>$txt</i>" ;
                  } ,

  on_L         => sub {
                    my ( $this , $L , $text, $page , $section, $type ) = @_ ;
                    if   ( $type eq 'pod' ) {
                      $section = defined $section ? "#$section" : ''; 
                      $page = '' unless defined $page; 
                      return "<i><a href='http://search.cpan.org/perldoc?$page$section'>$text</a></i>" ;
                    }
                    elsif( $type eq 'man' ) { return "<i>$text</i>" ;}
                    elsif( $type eq 'url' ) { return "<a href='$page' target='_blank'>$text</a>" ;}
                  } ,

  on_S         => sub {
                    my ( $this , $txt ) = @_ ;
                    $txt =~ s/\n/ /gs ;
                    return $txt ;
                  } ,

  on_X         => sub { return '' ; } ,

  on_Z         => sub { return '' ; } ,

  on_back      => sub {
                    my $this = shift ;
                    return "</ul>\n" ;
                  } ,

  on_begin     => sub {
                    my $this = shift ;
                    my ( $txt , $a_name ) = @_ ;
                    $this->{IN_BEGIN} = 1;
                    return '';
                  } ,

  on_error     => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<!-- POD_ERROR: $txt -->" ;
                  } ,

  on_end       => sub { 
                    my $this = shift ;
                    my ( $txt , $a_name ) = @_ ;
                    delete $this->{IN_BEGIN};
                    return '';
                  } ,

  on_for       => sub { return '' ;} ,

  on_head1     => sub {
                    my ( $this , $txt , $a_name ) = @_ ;
                    return "<a name='$a_name'></a><h1>$txt</h1>\n\n" ;
                  } ,

  on_head2     => sub {
                    my ( $this , $txt , $a_name ) = @_ ;
                    return "<a name='$a_name'></a><h2>$txt</h2>\n\n" ;
                  } ,

  on_head3     => sub {
                    my ( $this , $txt , $a_name ) = @_ ;
                    return "<a name='$a_name'></a><h3>$txt</h3>\n\n" ;
                  } ,

  on_head4     => sub {
                    my ( $this , $txt , $a_name ) = @_ ;
                    return "<a name='$a_name'></a><h4>$txt</h4>\n\n" ;
                  } ,

  on_include   => sub {
                    my ( $this , $file ) = @_ ;
                    return "./$file" ;
                  } ,

  on_item      => sub {
                    my ( $this , $txt ) = @_ ;
                    return "<li>$txt</li>\n" ;
                  } ,

  on_index_node_start => sub {
                    my ( $this , $txt , $a_name , $has_childs ) = @_ ;
                    my $ret = "<li><a href='#$a_name'>$txt</a>\n" ;
                    $ret .= "\n<ul>\n" if $has_childs ;
                    return $ret ;
                  } ,

  on_index_node_end => sub {
                    my $this = shift ;
                    my ( $txt , $a_name , $has_childs ) = @_ ;
                    my $ret = $has_childs ? "</ul>" : '' ;
                    return $ret ;
                  } ,

  on_over      => sub {
                    my ( $this , $level ) = @_ ;
                    return "<ul>\n" ;
                  } ,

  on_textblock => sub {
                    my ( $this , $txt ) = @_ ;
                    return if exists $this->{IN_BEGIN};
                    return "<p>$txt</p>\n" ;
                  } ,

  on_uri       => sub {
                    my ( $this , $uri ) = @_ ;
                    return "<a href='$uri' target='_blank'>$uri</a>" ;
                  } ,

  on_verbatim  => sub {
                    my ( $this , $txt ) = @_ ;
                    $txt =~ s{(^[\r\n])*(^[\r\n])\z}{}mg;
                    return '' unless length $txt;
                    return "<pre>$txt</pre>\n" ;
                  } ,
  ) ;

  ## Convert to HTML:

  my $html = $podhtml->pod2html('test.pod' ,
                                'test.html' ,
                                title => 'POD::Test' ,
                                body  => { bgcolor => '#CCCCCC' } ,
                                css   => 'test.css' ,
                               ) ;

METHODS

new ( %EVENTS_SUBS )

By default the object has it own subs to handler the events.

But if you want to personalize/overwrite them you can set the keys in the initialization:

(For examples of how to implement the event subs see USAGE above).

on_B ( $txt )

When B<...> is found. (bold text).

on_C ( $txt )

When C<...> is found. (code text).

on_E ( $txt )

When E<...> is found. (a character escape).

on_I ( $txt )

When I<...> is found. (italic text).

on_L ( $L , $text, $page , $section, $type )

When L<...> is found. (Link).

$L

The link content. This is what is parsed to generate the other variables.

$text

The link text.

$page

The page of the link. Can be an URI, pack::age, or some other reference.

$section

The section of the $page.

$type

The type of the link: pod, man, url.

on_F ( $txt )

When F<...> is found. (used for filenames).

on_S ( $txt )

When S<...> is found. (text contains non-breaking spaces).

on_X ( $txt )

When X<...> is found. (a null (zero-effect) formatting code).

on_Z ( $txt )

When Z<...> is found. (a null (zero-effect) formatting code).

on_back

When =back is found.

on_begin

When =begin is found.

By default everything from '=begin' to '=end' is ignored.

on_error ( $txt )

Called on POD syntax error occurrence.

on_head1 ( $txt , $a_name )

When =head1 is found.

$txt

The text of the command.

$a_name

The text of the command filtered to be used as <a name="$a_name"</a>>.

on_head2 ( $txt , $a_name )

When =head2 is found. See on_head1.

on_head3 ( $txt , $a_name )

When =head3 is found. See on_head1.

on_head4 ( $txt , $a_name )

When =head4 is found. See on_head1.

on_for

When =for is found.

By default '=for' is ignored!

on_item ( $txt )

When =item foo is found.

on_end

When =end is found.

See '=begin' above.

on_include ( $file )

When =include is found.

Should be used only to handle the localtion of the $file.

on_index_node_start ( $txt , $a_name , $has_childs )

Called to build the INDEX. This is called when a node is start.

$has_childs can be used to know if the node has childs (sub-nodes).

on_index_node_end ( $txt , $a_name , $has_childs )

Called to build the INDEX. This is called when a node ends.

$has_childs can be used to know if the node has childs (sub-nodes).

on_over ( $level )

When =over X is found.

on_textblock ( $txt )

When normal text blocks are found.

on_uri ( $uri )

When an URI (URL, E-MAIL, etc...) is found.

on_verbatim ( $txt )

When VERBATIM data is found, trailing empty lines are deleted.

Note: This interface was previously called "on_verbatin". That interface has been retained for backwards compatibility.

pod2html ( POD_FILE|POD_DATA|FILEHANDLER , HTML_FILE , %OPTIONS )

Convert a POD to HTML. Also returns the HTML data generated.

POD_FILE|POD_DATA|GLOB

The POD file (file path) , data (SCALAR) or FILEHANDLER (GLOB opened).

HTML_FILE (optional)

The output HTML file path.

** Note that the method also returns the HTML data generated, so you also can use it wihtout generate files.

%OPTIONS (optional)
title

The title of the HTML.

** Default: file path

body

The body values.

Examples:

  body => q`alink="#FF0000" bgcolor="#FFFFFF" link="#000000" text="#000000" vlink="#000066"` ,

  ## Or:

  body => { bgcolor => "#CCCCCC" , link => "#0000FF" } , ## This will overwrite only this 2 values,

** Default: alink="#FF0000" bgcolor="#FFFFFF" link="#000000" text="#000000" vlink="#000066"

css

Can be a css file path (HREF) or the css data.

Examples:

  css => 'test.css' ,

  ## Or:

  css => q`
    BODY {
      background: white;
      color: black;
      font-family: arial,sans-serif;
      margin: 0;
      padding: 1ex;
    }
    TABLE {
      border-collapse: collapse;
      border-spacing: 0;
      border-width: 0;
      color: inherit;
    }
  ` ,
top

Set a TOP data. The HTML paste with top will be added just before the index.

index

Set the index data. If not set will generate automatically, calling the events subs on_index_node_start and on_index_node_end

no_index

If TRUE tell to not build and insert the index.

no_css

If TRUE tell to not use css.

only_content

If TRUE tell to only generate the HTML content (between <body>...</body>).

index_item

If TRUE items will be added in the index.

basic_entities

If TRUE encode only basic entities:

  & < >
common_entities

If TRUE encode only common entities:

  & < > á é í ó ú Á É Í Ó Ú â ê î ô û Â Ê Î Ô Û ã õ Ã Õ ç Ç ©
no_generator

If TRUE the meta GENERATOR tag won't be added.

pm_version ( FILE )

Return the version of a Perl Module file.

pm_package ( FILE )

Return the package name of a Perl Module file.

pm_name

Returns =head1 NAME description.

pm_package_version_name

Returns all the 3 values at the same time.

default_css

Returns the default CSS.

EXTENDING POD

You can extend POD defining non-standard events.

For example, to enable the command "=hr":

  my $podhtml = Pod::HtmlEasy->new(
  on_hr => sub {
            my ( $this , $txt ) = @_ ;
            return "<hr>" ;
           }
  ) ;

To define a new formatting code, do the same thing, but the code must be a single letter.

So, to enable "G<...>":

  my $podhtml = Pod::HtmlEasy->new(
  on_G => sub {
            my ( $this , $txt ) = @_ ;
            return "<img src='$txt' border=0>" ;
          }
  ) ;

DEFAULT CSS

This is the default CSS added to the HTML.

** If you will set your own CSS use this as base.

  BODY {
    background: white;
    color: black;
    font-family: arial,sans-serif;
    margin: 0;
    padding: 1ex;
  }
  TABLE {
    border-collapse: collapse;
    border-spacing: 0;
    border-width: 0;
    color: inherit;
  }
  IMG { border: 0; }
  FORM { margin: 0; }
  input { margin: 2px; }
  A.fred {
    text-decoration: none;
  }
  A:link, A:visited {
    background: transparent;
    color: #006699;
  }
  TD {
    margin: 0;
    padding: 0;
  }
  DIV {
    border-width: 0;
  }
  DT {
    margin-top: 1em;
  }
  TH {
    background: #bbbbbb;
    color: inherit;
    padding: 0.4ex 1ex;
    text-align: left;
  }
  TH A:link, TH A:visited {
    background: transparent;
    color: black;
  }
  A.m:link, A.m:visited {
    background: #006699;
    color: white;
    font: bold 10pt Arial,Helvetica,sans-serif;
    text-decoration: none;
  }
  A.o:link, A.o:visited {
    background: #006699;
    color: #ccffcc;
    font: bold 10pt Arial,Helvetica,sans-serif;
    text-decoration: none;
  }
  A.o:hover {
    background: transparent;
    color: #ff6600;
    text-decoration: underline;
  }
  A.m:hover {
    background: transparent;
    color: #ff6600;
    text-decoration: underline;
  }
  table.dlsip     {
    background: #dddddd;
    border: 0.4ex solid #dddddd;
  }
  .pod PRE     {
    background: #eeeeee;
    border: 1px solid #888888;
    color: black;
    padding-top: 1em;
    white-space: pre;
  }
  .pod H1      {
    background: transparent;
    color: #006699;
    font-size: large;
  }
  .pod H2      {
    background: transparent;
    color: #006699;
    font-size: medium;
  }
  .pod IMG     {
    vertical-align: top;
  }
  .pod .toc A  {
    text-decoration: none;
  }
  .pod .toc LI {
    line-height: 1.2em;
    list-style-type: none;
  }

DIAGNOSTICS

HtmlEasy does not produce any messages other than those that result from the use warnings specified for each module. The maintainer would appreciate hearing about any such.

HtmlEasy uses Pod::Parser, which may produce error messages concerning malformed HTML.

SEE ALSO

Pod::Parser perlpod.

AUTHOR

Graciliano M. P. <gm@virtuasites.com.br>

I will appreciate any type of feedback (include your opinions and/or suggestions). ;-P

Thanks to Ivan Tubert-Brohman <itub@cpan.org> that suggested to add the basic_entities and common_entities options and for tests.

MAINTENANCE

Updates for version 0.8_01 by Geoffrey Leach <gleach@cpan.org>

COPYRIGHT

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 1205:

Non-ASCII character seen before =encoding in 'á'. Assuming CP1252