1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-06-18 23:57:33 +02:00

A number of doc improvements:

1) Started on a general markdown renderer
2) Internal links now work in PDF
3) Improvements to PDF styling
4) Some comment and formatting fixes
5) User guide edits.
This commit is contained in:
David Steele
2015-12-23 11:04:26 -05:00
parent fdc99e30bd
commit b0a6954671
17 changed files with 702 additions and 28 deletions

View File

@ -45,6 +45,8 @@ use constant RENDER_FILE => 'file';
use constant RENDER_TYPE => 'type';
use constant RENDER_TYPE_HTML => 'html';
push @EXPORT, qw(RENDER_TYPE_HTML);
use constant RENDER_TYPE_MARKDOWN => 'markdown';
push @EXPORT, qw(RENDER_TYPE_MARKDOWN);
use constant RENDER_TYPE_PDF => 'pdf';
push @EXPORT, qw(RENDER_TYPE_PDF);
@ -144,12 +146,35 @@ sub new
$$oRenderOutHash{source} = $strSource;
# Get the filename if this is a pdf
$$oRenderOutHash{menu} = $oRenderOut->paramGet('menu', false);
if (defined($$oRenderOutHash{menu}) && $strType ne RENDER_TYPE_HTML)
# Get the menu caption
if (defined($oRenderOut->paramGet('menu', false)) && $strType ne RENDER_TYPE_HTML)
{
confess &log(ERROR, 'only the html render type can have menu set')
confess &log(ERROR, "menu is only valid with html render type");
}
# Get the filename
if (defined($oRenderOut->paramGet('file', false)))
{
if ($strType eq RENDER_TYPE_HTML || $strType eq RENDER_TYPE_MARKDOWN)
{
$$oRenderOutHash{file} = $oRenderOut->paramGet('file');
}
else
{
confess &log(ERROR, "file is only valid with html or markdown render types");
}
}
if (defined($oRenderOut->paramGet('menu', false)))
{
if ($strType eq RENDER_TYPE_HTML)
{
$$oRenderOutHash{menu} = $oRenderOut->paramGet('menu', false);
}
else
{
confess &log(ERROR, 'only the html render type can have menu set');
}
}
logDebugMisc

View File

@ -628,14 +628,29 @@ sub processTag
{
if (!defined($strUrl))
{
$strUrl = $oTag->paramGet('page');
$strUrl = $oTag->paramGet('page', false);
if (!defined($strUrl))
{
$strUrl = '#' . substr($oTag->paramGet('section'), 1);
}
}
$strBuffer = '<a href="' . $strUrl . '">' . $oTag->valueGet() . '</a>';
}
elsif ($strType eq 'latex')
{
$strBuffer = $oTag->valueGet();
if (!defined($strUrl))
{
$strUrl = $oTag->paramGet('page', false);
if (!defined($strUrl))
{
$strUrl = $oTag->paramGet('section');
}
}
$strBuffer = "\\hyperref[$strUrl]{" . $oTag->valueGet() . "}";
}
else
{

View File

@ -207,7 +207,7 @@ sub sectionProcess
}
# Working variables
$strAnchor = (defined($strAnchor) ? "${strAnchor}-" : '') . $oSection->paramGet('id');
$strAnchor = (defined($strAnchor) ? "${strAnchor}/" : '') . $oSection->paramGet('id');
# Create the section toc element
my $oSectionTocElement = new BackRestDoc::Html::DocHtmlElement(HTML_DIV, "section${iDepth}-toc");

View File

@ -149,7 +149,7 @@ sub sectionProcess
confess &log(ASSERT, "section depth of ${iDepth} exceeds maximum");
}
$strLatex .= "\{${strSectionTitle}\}\n";
$strLatex .= "\{${strSectionTitle}\}\\label{" . $oSection->paramGet('path', false) . "}\n";
foreach my $oChild ($oSection->nodeList())
{

View File

@ -0,0 +1,119 @@
####################################################################################################################################
# DOC MARKDOWN MODULE
####################################################################################################################################
package BackRestDoc::Markdown::DocMarkdown;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Data::Dumper;
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use File::Copy;
use POSIX qw(strftime);
use Storable qw(dclone);
use lib dirname($0) . '/../lib';
use BackRest::Common::Log;
use BackRest::Common::String;
use BackRest::FileCommon;
use BackRest::Version;
use lib dirname($0) . '/../test/lib';
use BackRestTest::Common::ExecuteTest;
use BackRestDoc::Common::DocConfig;
use BackRestDoc::Common::DocManifest;
use BackRestDoc::Markdown::DocMarkdownRender;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_DOC_MARKDOWN => 'DocMarkdown';
use constant OP_DOC_MARKDOWN_NEW => OP_DOC_MARKDOWN . '->new';
use constant OP_DOC_MARKDOWN_PROCESS => OP_DOC_MARKDOWN . '->process';
####################################################################################################################################
# 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->{oManifest},
$self->{strXmlPath},
$self->{strMarkdownPath},
$self->{bExe}
) =
logDebugParam
(
OP_DOC_MARKDOWN_NEW, \@_,
{name => 'oManifest'},
{name => 'strXmlPath'},
{name => 'strMarkdownPath'},
{name => 'bExe'}
);
# Remove the current html path if it exists
if (-e $self->{strMarkdownPath})
{
executeTest("rm -rf $self->{strMarkdownPath}/*");
}
# Else create the html path
else
{
mkdir($self->{strMarkdownPath})
or confess &log(ERROR, "unable to create path $self->{strMarkdownPath}");
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# process
#
# Generate the site html
####################################################################################################################################
sub process
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my $strOperation = logDebugParam(OP_DOC_MARKDOWN_PROCESS);
foreach my $strRenderOutId ($self->{oManifest}->renderOutList(RENDER_TYPE_MARKDOWN))
{
my $oRenderOut = $self->{oManifest}->renderOutGet(RENDER_TYPE_MARKDOWN, $strRenderOutId);
my $strFile = "$self->{strMarkdownPath}/" . (defined($$oRenderOut{file}) ? $$oRenderOut{file} : "${strRenderOutId}.md");
&log(INFO, " render out: ${strRenderOutId}");
# Save the html page
fileStringWrite($strFile,
$self->{oManifest}->variableReplace((new BackRestDoc::Markdown::DocMarkdownRender($self->{oManifest},
$strRenderOutId, $self->{bExe}))->process()),
false);
}
# Return from function and log return values if any
logDebugReturn($strOperation);
}
1;

View File

@ -0,0 +1,472 @@
####################################################################################################################################
# DOC MARKDOWN RENDER MODULE
####################################################################################################################################
package BackRestDoc::Markdown::DocMarkdownRender;
use parent 'BackRestDoc::Common::DocExecute';
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use Data::Dumper;
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use File::Copy;
use Storable qw(dclone);
use lib dirname($0) . '/../lib';
use BackRest::Common::Log;
use BackRest::Common::String;
use BackRest::Config::ConfigHelp;
use BackRestDoc::Common::DocManifest;
####################################################################################################################################
# Operation constants
####################################################################################################################################
use constant OP_DOC_MARKDOWN_RENDER => 'DocMarkdownRender';
use constant OP_DOC_MARKDOWN_RENDER_BACKREST_CONFIG_PROCESS => OP_DOC_MARKDOWN_RENDER . '->backrestConfigProcess';
use constant OP_DOC_MARKDOWN_RENDER_NEW => OP_DOC_MARKDOWN_RENDER . '->new';
use constant OP_DOC_MARKDOWN_RENDER_POSTGRES_CONFIG_PROCESS => OP_DOC_MARKDOWN_RENDER . '->postgresConfigProcess';
use constant OP_DOC_MARKDOWN_RENDER_PROCESS => OP_DOC_MARKDOWN_RENDER . '->process';
use constant OP_DOC_MARKDOWN_RENDER_SECTION_PROCESS => OP_DOC_MARKDOWN_RENDER . '->sectionProcess';
####################################################################################################################################
# CONSTRUCTOR
####################################################################################################################################
sub new
{
my $class = shift; # Class name
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oManifest,
$strRenderOutKey,
$bExe
) =
logDebugParam
(
OP_DOC_MARKDOWN_RENDER_NEW, \@_,
{name => 'oManifest'},
{name => 'strRenderOutKey'},
{name => 'bExe'}
);
# Create the class hash
my $self = $class->SUPER::new(RENDER_TYPE_MARKDOWN, $oManifest, $strRenderOutKey, $bExe);
bless $self, $class;
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'self', value => $self}
);
}
####################################################################################################################################
# process
#
# Generate the site html
####################################################################################################################################
sub process
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my $strOperation = logDebugParam(OP_DOC_MARKDOWN_RENDER_PROCESS);
# Working variables
my $oPage = $self->{oDoc};
# Initialize page
my $strMarkdown = "# {[project]}" .
(defined($oPage->paramGet('title', false)) ? ' ' . $oPage->paramGet('title') : '');
if (defined($oPage->paramGet('subtitle', false)))
{
$strMarkdown .= ' - ' . $oPage->paramGet('subtitle');
}
# my $oHtmlBuilder = new BackRestDoc::Html::DocHtmlBuilder("{[project]} - Reliable PostgreSQL Backup",
# $strTitle . (defined($strSubTitle) ? " - ${strSubTitle}" : ''),
# $self->{bPretty});
#
# # Generate header
# my $oPageHeader = $oHtmlBuilder->bodyGet()->addNew(HTML_DIV, 'page-header');
#
# $oPageHeader->
# addNew(HTML_DIV, 'page-header-title',
# {strContent => $strTitle});
#
# if (defined($strSubTitle))
# {
# $oPageHeader->
# addNew(HTML_DIV, 'page-header-subtitle',
# {strContent => $strSubTitle});
# }
#
# # Generate menu
# my $oMenuBody = $oHtmlBuilder->bodyGet()->addNew(HTML_DIV, 'page-menu')->addNew(HTML_DIV, 'menu-body');
#
# if ($self->{strRenderOutKey} ne 'index')
# {
# my $oRenderOut = $self->{oManifest}->renderOutGet(RENDER_TYPE_HTML, 'index');
#
# $oMenuBody->
# addNew(HTML_DIV, 'menu')->
# addNew(HTML_A, 'menu-link', {strContent => $$oRenderOut{menu}, strRef => '{[project-url-root]}'});
# }
#
# foreach my $strRenderOutKey ($self->{oManifest}->renderOutList(RENDER_TYPE_HTML))
# {
# if ($strRenderOutKey ne $self->{strRenderOutKey} && $strRenderOutKey ne 'index')
# {
# my $oRenderOut = $self->{oManifest}->renderOutGet(RENDER_TYPE_HTML, $strRenderOutKey);
#
# $oMenuBody->
# addNew(HTML_DIV, 'menu')->
# addNew(HTML_A, 'menu-link', {strContent => $$oRenderOut{menu}, strRef => "${strRenderOutKey}.html"});
# }
# }
#
# # Generate table of contents
# my $oPageTocBody;
#
# if (!defined($oPage->paramGet('toc', false)) || $oPage->paramGet('toc') eq 'y')
# {
# my $oPageToc = $oHtmlBuilder->bodyGet()->addNew(HTML_DIV, 'page-toc');
#
# $oPageToc->
# addNew(HTML_DIV, 'page-toc-title',
# {strContent => "Table of Contents"});
#
# $oPageTocBody = $oPageToc->
# addNew(HTML_DIV, 'page-toc-body');
# }
#
# # Generate body
# my $oPageBody = $oHtmlBuilder->bodyGet()->addNew(HTML_DIV, 'page-body');
# Render sections
foreach my $oSection ($oPage->nodeList('section'))
{
$strMarkdown .= "\n\n" . $self->sectionProcess($oSection, 1);
}
$strMarkdown .= "\n";
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strMarkdown', value => $strMarkdown, trace => true}
);
}
####################################################################################################################################
# sectionProcess
####################################################################################################################################
sub sectionProcess
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oSection,
$iDepth
) =
logDebugParam
(
OP_DOC_MARKDOWN_RENDER_SECTION_PROCESS, \@_,
{name => 'oSection'},
{name => 'iDepth'}
);
&log($iDepth == 1 ? INFO : DEBUG, (' ' x ($iDepth + 1)) . 'process section: ' . $oSection->paramGet('id'));
if ($iDepth > 3)
{
confess &log(ASSERT, "section depth of ${iDepth} exceeds maximum");
}
my $strMarkdown = '#' . ('#' x $iDepth) . ' ' . $self->processText($oSection->nodeGet('title')->textGet());
foreach my $oChild ($oSection->nodeList())
{
&log(DEBUG, (' ' x ($iDepth + 2)) . 'process child ' . $oChild->nameGet());
# Execute a command
if ($oChild->nameGet() eq 'execute-list')
{
# my $oSectionBodyExecute = $oSectionBodyElement->addNew(HTML_DIV, "execute");
# my $bFirst = true;
# my $strHostName = $self->{oManifest}->variableReplace($oChild->paramGet('host'));
#
# $oSectionBodyExecute->
# addNew(HTML_DIV, "execute-title",
# {strContent => "<span class=\"host\">${strHostName}</span> <b>&#x21d2;</b> " .
# $self->processText($oChild->nodeGet('title')->textGet())});
#
# my $oExecuteBodyElement = $oSectionBodyExecute->addNew(HTML_DIV, "execute-body");
#
# foreach my $oExecute ($oChild->nodeList('execute'))
# {
# my $bExeShow = !$oExecute->paramTest('show', 'n');
# my $bExeExpectedError = defined($oExecute->paramGet('err-expect', false));
#
# my ($strCommand, $strOutput) = $self->execute($oSection, $strHostName, $oExecute, $iDepth + 3);
#
# if ($bExeShow)
# {
# # Add continuation chars and proper spacing
# $strCommand =~ s/\n/\n /smg;
#
# $oExecuteBodyElement->
# addNew(HTML_PRE, "execute-body-cmd",
# {strContent => $strCommand, bPre => true});
#
# my $strHighLight = $self->{oManifest}->variableReplace($oExecute->fieldGet('exe-highlight', false));
# my $bHighLightFound = false;
#
# if (defined($strOutput))
# {
# my $bHighLightOld;
# my $strHighLightOutput;
#
# if ($oExecute->fieldTest('exe-highlight-type', 'error'))
# {
# $bExeExpectedError = true;
# }
#
# foreach my $strLine (split("\n", $strOutput))
# {
# my $bHighLight = defined($strHighLight) && $strLine =~ /$strHighLight/;
#
# if (defined($bHighLightOld) && $bHighLight != $bHighLightOld)
# {
# $oExecuteBodyElement->
# addNew(HTML_PRE, 'execute-body-output' .
# ($bHighLightOld ? '-highlight' . ($bExeExpectedError ? '-error' : '') : ''),
# {strContent => $strHighLightOutput, bPre => true});
#
# undef($strHighLightOutput);
# }
#
# $strHighLightOutput .= (defined($strHighLightOutput) ? "\n" : '') . $strLine;
# $bHighLightOld = $bHighLight;
#
# $bHighLightFound = $bHighLightFound ? true : $bHighLight ? true : false;
# }
#
# if (defined($bHighLightOld))
# {
# $oExecuteBodyElement->
# addNew(HTML_PRE, 'execute-body-output' .
# ($bHighLightOld ? '-highlight' . ($bExeExpectedError ? '-error' : '') : ''),
# {strContent => $strHighLightOutput, bPre => true});
# }
#
# $bFirst = true;
# }
#
# if ($self->{bExe} && $self->isRequired($oSection) && defined($strHighLight) && !$bHighLightFound)
# {
# confess &log(ERROR, "unable to find a match for highlight: ${strHighLight}");
# }
# }
#
# $bFirst = false;
# }
}
# Add code block
elsif ($oChild->nameGet() eq 'code-block')
{
# $oSectionBodyElement->
# addNew(HTML_DIV, 'code-block',
# {strContent => $oChild->valueGet()});
}
# Add descriptive text
elsif ($oChild->nameGet() eq 'p')
{
$strMarkdown .= "\n\n" . $self->processText($oChild->textGet());
}
# Add option descriptive text
elsif ($oChild->nameGet() eq 'option-description')
{
# my $strOption = $oChild->paramGet("key");
# my $oDescription = ${$self->{oReference}->{oConfigHash}}{&CONFIG_HELP_OPTION}{$strOption}{&CONFIG_HELP_DESCRIPTION};
#
# if (!defined($oDescription))
# {
# confess &log(ERROR, "unable to find ${strOption} option in sections - try adding command?");
# }
#
# $oSectionBodyElement->
# addNew(HTML_DIV, 'section-body-text',
# {strContent => $self->processText($oDescription)});
}
# Add/remove backrest config options
elsif ($oChild->nameGet() eq 'backrest-config')
{
# my $oConfigElement = $self->backrestConfigProcess($oSection, $oChild, $iDepth + 3);
#
# if (defined($oConfigElement))
# {
# $oSectionBodyElement->add($oConfigElement);
# }
}
# Add/remove postgres config options
elsif ($oChild->nameGet() eq 'postgres-config')
{
# my $oConfigElement = $self->postgresConfigProcess($oSection, $oChild, $iDepth + 3);
#
# if (defined($oConfigElement))
# {
# $oSectionBodyElement->add($oConfigElement);
# }
}
# Add a subsection
elsif ($oChild->nameGet() eq 'section')
{
$strMarkdown .= "\n\n" . $self->sectionProcess($oChild, $iDepth + 1);
}
# Check if the child can be processed by a parent
else
{
# $self->sectionChildProcess($oSection, $oChild, $iDepth + 1);
}
}
# Return from function and log return values if any
return logDebugReturn
(
$strOperation,
{name => 'strMarkdown', value => $strMarkdown, trace => true}
);
}
####################################################################################################################################
# backrestConfigProcess
####################################################################################################################################
sub backrestConfigProcess
{
my $self = shift;
# Assign function parameters, defaults, and log debug info
my
(
$strOperation,
$oSection,
$oConfig,
$iDepth
) =
logDebugParam
(
OP_DOC_MARKDOWN_RENDER_BACKREST_CONFIG_PROCESS, \@_,
{name => 'oSection'},
{name => 'oConfig'},
{name => 'iDepth'}
);
# # Generate the config
# my $oConfigElement;
# my ($strFile, $strConfig, $bShow) = $self->backrestConfig($oSection, $oConfig, $iDepth);
#
# if ($bShow)
# {
# my $strHostName = $self->{oManifest}->variableReplace($oConfig->paramGet('host'));
#
# # Render the config
# $oConfigElement = new BackRestDoc::Html::DocHtmlElement(HTML_DIV, "config");
#
# $oConfigElement->
# addNew(HTML_DIV, "config-title",
# {strContent => "<span class=\"host\">${strHostName}</span>:<span class=\"file\">${strFile}</span>" .
# " <b>&#x21d2;</b> " . $self->processText($oConfig->nodeGet('title')->textGet())});
#
# my $oConfigBodyElement = $oConfigElement->addNew(HTML_DIV, "config-body");
# #
# # $oConfigBodyElement->
# # addNew(HTML_DIV, "config-body-title",
# # {strContent => "${strFile}:"});
#
# $oConfigBodyElement->
# addNew(HTML_DIV, "config-body-output",
# {strContent => $strConfig});
# }
#
# # Return from function and log return values if any
# return logDebugReturn
# (
# $strOperation,
# {name => 'oConfigElement', value => $oConfigElement, trace => true}
# );
}
####################################################################################################################################
# postgresConfigProcess
####################################################################################################################################
sub postgresConfigProcess
{
my $self = shift;
# # Assign function parameters, defaults, and log debug info
# my
# (
# $strOperation,
# $oSection,
# $oConfig,
# $iDepth
# ) =
# logDebugParam
# (
# OP_DOC_MARKDOWN_RENDER_POSTGRES_CONFIG_PROCESS, \@_,
# {name => 'oSection'},
# {name => 'oConfig'},
# {name => 'iDepth'}
# );
#
# # Generate the config
# my $oConfigElement;
# my ($strFile, $strConfig, $bShow) = $self->postgresConfig($oSection, $oConfig, $iDepth);
#
# if ($bShow)
# {
# # Render the config
# my $strHostName = $self->{oManifest}->variableReplace($oConfig->paramGet('host'));
# $oConfigElement = new BackRestDoc::Html::DocHtmlElement(HTML_DIV, "config");
#
# $oConfigElement->
# addNew(HTML_DIV, "config-title",
# {strContent => "<span class=\"host\">${strHostName}</span>:<span class=\"file\">${strFile}</span>" .
# " <b>&#x21d2;</b> " . $self->processText($oConfig->nodeGet('title')->textGet())});
#
# my $oConfigBodyElement = $oConfigElement->addNew(HTML_DIV, "config-body");
#
# # $oConfigBodyElement->
# # addNew(HTML_DIV, "config-body-title",
# # {strContent => "append to ${strFile}:"});
#
# $oConfigBodyElement->
# addNew(HTML_DIV, "config-body-output",
# {strContent => defined($strConfig) ? $strConfig : '<No PgBackRest Settings>'});
#
# $oConfig->fieldSet('actual-config', $strConfig);
# }
#
# # Return from function and log return values if any
# return logDebugReturn
# (
# $strOperation,
# {name => 'oConfigElement', value => $oConfigElement, trace => true}
# );
}
1;