#################################################################################################################################### # DOC HTML BUILDER MODULE #################################################################################################################################### package pgBackRestDoc::Html::DocHtmlBuilder; use strict; use warnings FATAL => qw(all); use Carp qw(confess); use Exporter qw(import); our @EXPORT = qw(); use pgBackRestDoc::Common::Log; use pgBackRestDoc::Common::String; use pgBackRestDoc::Html::DocHtmlElement; #################################################################################################################################### # CONSTRUCTOR #################################################################################################################################### sub new { my $class = shift; # Class name # Create the class hash my $self = {}; bless $self, $class; $self->{strClass} = $class; # Assign function parameters, defaults, and log debug info ( my $strOperation, $self->{strName}, $self->{strTitle}, $self->{strFavicon}, $self->{strLogo}, $self->{strDescription}, $self->{bPretty}, $self->{bCompact}, $self->{strCss}, ) = logDebugParam ( __PACKAGE__ . '->new', \@_, {name => 'strName'}, {name => 'strTitle'}, {name => 'strFavicon', required => false}, {name => 'strLogo', required => false}, {name => 'strDescription', required => false}, {name => 'bPretty', default => false}, {name => 'bCompact', default => false}, {name => 'strCss', required => false}, ); $self->{oBody} = new pgBackRestDoc::Html::DocHtmlElement(HTML_BODY); # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'self', value => $self} ); } #################################################################################################################################### # indent # # Indent html #################################################################################################################################### sub indent { my $self = shift; my $iDepth = shift; return $self->{bPretty} ? (' ' x $iDepth) : ''; } #################################################################################################################################### # lf # # Add a linefeed. #################################################################################################################################### sub lf { my $self = shift; return $self->{bPretty} ? "\n" : ''; } #################################################################################################################################### # bodyGet # # Get the body element. #################################################################################################################################### sub bodyGet { my $self = shift; return $self->{oBody}; } #################################################################################################################################### # htmlRender # # Render each html element. #################################################################################################################################### sub htmlRender { my $self = shift; # Assign function parameters, defaults, and log debug info my ( $strOperation, $oElement, $iDepth ) = logDebugParam ( __PACKAGE__ . '->htmlRender', \@_, {name => 'oElement', trace => true}, {name => 'iDepth', trace => true} ); # If a pre tag add a linefeed before the tag unless the prior tag was also pre. This makes the output more diffable. my $strHtml = ""; if ($oElement->{strType} eq HTML_PRE && !$self->{bPretty}) { if (!$self->{bPrePrior}) { $strHtml .= "\n"; } $self->{bPrePrior} = true; } else { $self->{bPrePrior} = false; } # Build the tag $strHtml .= $self->indent($iDepth) . "<$oElement->{strType}" . (defined($oElement->{strClass}) ? " class=\"$oElement->{strClass}\"": '') . (defined($oElement->{strRef}) ? " href=\"$oElement->{strRef}\"": '') . (defined($oElement->{strId}) ? " id=\"$oElement->{strId}\"": '') . (defined($oElement->{strExtra}) ? " $oElement->{strExtra}": '') . '>'; if (defined($oElement->{strContent})) { if (!defined($oElement->{bPre}) || !$oElement->{bPre}) { $oElement->{strContent} = trim($oElement->{strContent}); # Add a linefeed before the content if not pre. This makes the output more diffable. $strHtml .= "\n"; } else { $oElement->{strContent} =~ s/\&/\&\;/g; } $strHtml .= $oElement->{strContent}; # Add a linefeed after the content if not pre. This makes the output more diffable. if (!defined($oElement->{bPre}) || !$oElement->{bPre}) { $strHtml .= "\n" . $self->indent($iDepth); } } else { if (!($oElement->{strType} eq HTML_A && @{$oElement->{oyElement}} == 0)) { $strHtml .= $self->lf(); } foreach my $oChildElement (@{$oElement->{oyElement}}) { $strHtml .= $self->htmlRender($oChildElement, $iDepth + 1); } if (!($oElement->{strType} eq HTML_A && @{$oElement->{oyElement}} == 0)) { $strHtml .= $self->indent($iDepth); } } $strHtml .= "{strType}>"; # If a pre tag add an lf after the tag. This makes the output more diffable. $strHtml .= $oElement->{strType} eq HTML_PRE ? "\n" : $self->lf(); # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'strHtml', value => $strHtml, trace => true} ); } #################################################################################################################################### # escape # # Generate the HTML. #################################################################################################################################### sub escape { my $self = shift; my $strBuffer = shift; $strBuffer =~ s/\&/\&\;/g; $strBuffer =~ s/\htmlGet', \@_, {name => 'bAnalytics', optional => true, default => false, trace => true}, ); # Build the header my $strHtml = $self->indent(0) . "" . $self->lf() . $self->indent(0) . "" . $self->lf() . $self->indent(0) . "" . $self->lf() . $self->indent(1) . "\n" . $self->indent(2) . $self->escape($self->{strTitle}) . "\n" . $self->indent(1) . '' . $self->lf() . $self->indent(1) . "\n"; if (!$self->{bCompact}) { $strHtml .= # $self->indent(1) . "\n" . $self->indent(1) . '\n" . $self->indent(1) . '\n" . $self->indent(1) . "\n"; if (defined($self->{strFavicon})) { $strHtml .= $self->indent(1) . "{strFavicon}\" type=\"image/png\">\n"; } if (defined($self->{strLogo})) { $strHtml .= $self->indent(1) . "\n" . $self->indent(1) . "{strLogo}\">\n"; } if (defined($self->{strDescription})) { $strHtml .= $self->indent(1) . '\n" . $self->indent(1) . '\n"; } } if (defined($self->{strCss})) { my $strCss = $self->{strCss}; if (!$self->{bPretty}) { $strCss =~ s/^\s+//mg; $strCss =~ s/\n//g; $strCss =~ s/\/\*.*?\*\///g; } $strHtml .= $self->indent(1) . "\n"; } else { $strHtml .= $self->indent(1) . "\n"; } if ($bAnalytics) { $strHtml .= $self->indent(1) . "\n" . $self->indent(1) . "\n"; } $strHtml .= $self->indent(0) . "" . $self->lf() . $self->htmlRender($self->bodyGet(), 0); # Complete the html $strHtml .= $self->indent(0) . "" . $self->lf(); # Return from function and log return values if any return logDebugReturn ( $strOperation, {name => 'strHtml', value => $strHtml, trace => true} ); } 1;