2015-09-03 00:55:04 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# DOC RENDER MODULE
|
|
|
|
####################################################################################################################################
|
2015-10-28 11:10:36 +02:00
|
|
|
package BackRestDoc::Common::DocRender;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
|
|
|
|
|
|
|
use Exporter qw(import);
|
|
|
|
our @EXPORT = qw();
|
|
|
|
use File::Basename qw(dirname);
|
|
|
|
|
|
|
|
use lib dirname($0) . '/../lib';
|
2016-04-14 15:30:54 +02:00
|
|
|
use pgBackRest::Common::Log;
|
|
|
|
use pgBackRest::Common::String;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
use BackRestDoc::Common::DocManifest;
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# Render tags for various output types
|
|
|
|
####################################################################################################################################
|
|
|
|
my $oRenderTag =
|
|
|
|
{
|
|
|
|
'markdown' =>
|
|
|
|
{
|
2015-11-22 23:44:01 +02:00
|
|
|
'quote' => ['"', '"'],
|
2015-09-03 00:55:04 +02:00
|
|
|
'b' => ['**', '**'],
|
|
|
|
'i' => ['_', '_'],
|
2015-11-22 23:44:01 +02:00
|
|
|
# 'bi' => ['_**', '**_'],
|
2016-04-16 17:55:23 +02:00
|
|
|
'ul' => ["\n", ""],
|
2015-10-28 11:10:36 +02:00
|
|
|
'ol' => ["\n", "\n"],
|
2015-09-03 00:55:04 +02:00
|
|
|
'li' => ['- ', "\n"],
|
|
|
|
'id' => ['`', '`'],
|
|
|
|
'file' => ['`', '`'],
|
|
|
|
'path' => ['`', '`'],
|
|
|
|
'cmd' => ['`', '`'],
|
|
|
|
'param' => ['`', '`'],
|
|
|
|
'setting' => ['`', '`'],
|
|
|
|
'code' => ['`', '`'],
|
2015-11-22 23:44:01 +02:00
|
|
|
# 'code-block' => ['```', '```'],
|
|
|
|
# 'exe' => [undef, ''],
|
2015-09-03 00:55:04 +02:00
|
|
|
'backrest' => [undef, ''],
|
|
|
|
'postgres' => ['PostgreSQL', '']
|
|
|
|
},
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
'text' =>
|
|
|
|
{
|
2015-11-22 23:44:01 +02:00
|
|
|
'quote' => ['"', '"'],
|
2015-09-08 13:31:24 +02:00
|
|
|
'b' => ['', ''],
|
|
|
|
'i' => ['', ''],
|
2015-11-22 23:44:01 +02:00
|
|
|
# 'bi' => ['', ''],
|
2015-10-28 11:10:36 +02:00
|
|
|
'ul' => ["\n", "\n"],
|
|
|
|
'ol' => ["\n", "\n"],
|
2015-09-08 13:31:24 +02:00
|
|
|
'li' => ['* ', "\n"],
|
|
|
|
'id' => ['', ''],
|
|
|
|
'file' => ['', ''],
|
|
|
|
'path' => ['', ''],
|
|
|
|
'cmd' => ['', ''],
|
2015-10-28 11:10:36 +02:00
|
|
|
'br-option' => ['', ''],
|
2015-09-08 13:31:24 +02:00
|
|
|
'param' => ['', ''],
|
|
|
|
'setting' => ['', ''],
|
|
|
|
'code' => ['', ''],
|
|
|
|
'code-block' => ['', ''],
|
|
|
|
'exe' => [undef, ''],
|
|
|
|
'backrest' => [undef, ''],
|
|
|
|
'postgres' => ['PostgreSQL', '']
|
|
|
|
},
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
'latex' =>
|
|
|
|
{
|
|
|
|
'quote' => ['``', '"'],
|
|
|
|
'b' => ['\textbf{', '}'],
|
|
|
|
'i' => ['\textit{', '}'],
|
|
|
|
# 'bi' => ['', ''],
|
|
|
|
# 'ul' => ["\n", "\n"],
|
|
|
|
# 'ol' => ["\n", "\n"],
|
|
|
|
# 'li' => ['* ', "\n"],
|
|
|
|
'id' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'host' => ['\textnormal{\textbf{', '}}'],
|
|
|
|
'file' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'path' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'cmd' => ['\textnormal{\texttt{', "}}"],
|
|
|
|
'user' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'br-option' => ['', ''],
|
|
|
|
# 'param' => ['\texttt{', '}'],
|
|
|
|
# 'setting' => ['\texttt{', '}'],
|
|
|
|
'br-option' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'br-setting' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'pg-option' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'pg-setting' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
'code' => ['\textnormal{\texttt{', '}}'],
|
|
|
|
# 'code' => ['\texttt{', '}'],
|
|
|
|
# 'code-block' => ['', ''],
|
|
|
|
# 'exe' => [undef, ''],
|
|
|
|
'backrest' => [undef, ''],
|
|
|
|
'postgres' => ['PostgreSQL', '']
|
|
|
|
},
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
'html' =>
|
|
|
|
{
|
2015-11-22 23:44:01 +02:00
|
|
|
'quote' => ['<q>', '</q>'],
|
2015-10-28 11:10:36 +02:00
|
|
|
'b' => ['<b>', '</b>'],
|
|
|
|
'i' => ['<i>', '</i>'],
|
2015-11-22 23:44:01 +02:00
|
|
|
# 'bi' => ['<i><b>', '</b></i>'],
|
2015-10-28 11:10:36 +02:00
|
|
|
'ul' => ['<ul>', '</ul>'],
|
|
|
|
'ol' => ['<ol>', '</ol>'],
|
|
|
|
'li' => ['<li>', '</li>'],
|
|
|
|
'id' => ['<span class="id">', '</span>'],
|
2015-11-22 23:44:01 +02:00
|
|
|
'host' => ['<span class="host">', '</span>'],
|
2015-10-28 11:10:36 +02:00
|
|
|
'file' => ['<span class="file">', '</span>'],
|
|
|
|
'path' => ['<span class="path">', '</span>'],
|
|
|
|
'cmd' => ['<span class="cmd">', '</span>'],
|
|
|
|
'user' => ['<span class="user">', '</span>'],
|
|
|
|
'br-option' => ['<span class="br-option">', '</span>'],
|
|
|
|
'br-setting' => ['<span class="br-setting">', '</span>'],
|
|
|
|
'pg-option' => ['<span class="pg-option">', '</span>'],
|
|
|
|
'pg-setting' => ['<span class="pg-setting">', '</span>'],
|
2015-11-22 23:44:01 +02:00
|
|
|
'code' => ['<span class="id">', '</span>'],
|
2015-10-28 11:10:36 +02:00
|
|
|
'code-block' => ['<code-block>', '</code-block>'],
|
2015-11-22 23:44:01 +02:00
|
|
|
'exe' => [undef, ''],
|
2016-04-14 01:09:35 +02:00
|
|
|
'setting' => ['<span class="br-setting">', '</span>'], # ??? This will need to be fixed
|
2015-10-28 11:10:36 +02:00
|
|
|
'backrest' => [undef, ''],
|
|
|
|
'postgres' => ['<span class="postgres">PostgreSQL</span>', '']
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# CONSTRUCTOR
|
|
|
|
####################################################################################################################################
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift; # Class name
|
|
|
|
|
|
|
|
# Create the class hash
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
(
|
|
|
|
my $strOperation,
|
|
|
|
$self->{strType},
|
2015-11-22 23:44:01 +02:00
|
|
|
$self->{oManifest},
|
|
|
|
$self->{strRenderOutKey},
|
2015-09-03 00:55:04 +02:00
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->new', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'strType'},
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'oManifest'},
|
|
|
|
{name => 'strRenderOutKey', required => false}
|
2015-09-03 00:55:04 +02:00
|
|
|
);
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
# Initialize project tags
|
|
|
|
$$oRenderTag{markdown}{backrest}[0] = "{[project]}";
|
|
|
|
$$oRenderTag{markdown}{exe}[0] = "{[project-exe]}";
|
|
|
|
|
|
|
|
$$oRenderTag{text}{backrest}[0] = "{[project]}";
|
|
|
|
$$oRenderTag{text}{exe}[0] = "{[project-exe]}";
|
|
|
|
|
|
|
|
$$oRenderTag{latex}{backrest}[0] = "{[project]}";
|
|
|
|
$$oRenderTag{latex}{exe}[0] = "\\textnormal\{\\texttt\{[project-exe]}}\}\}";
|
|
|
|
|
|
|
|
$$oRenderTag{html}{backrest}[0] = "<span class=\"backrest\">{[project]}</span>";
|
|
|
|
$$oRenderTag{html}{exe}[0] = "<span class=\"file\">{[project-exe]}</span>";
|
|
|
|
|
|
|
|
if (defined($self->{strRenderOutKey}))
|
|
|
|
{
|
|
|
|
# Copy page data to self
|
|
|
|
my $oRenderOut = $self->{oManifest}->renderOutGet($self->{strType} eq 'latex' ? 'pdf' : $self->{strType}, $self->{strRenderOutKey});
|
|
|
|
|
2016-05-19 23:10:34 +02:00
|
|
|
# Determine if this is a custom source which signals special handling for different projects.
|
|
|
|
my $strSourceType = ${$self->{oManifest}->sourceGet('reference')}{strSourceType};
|
|
|
|
if (defined($strSourceType) && $strSourceType eq 'custom')
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
2016-05-19 23:10:34 +02:00
|
|
|
# Get the reference if this is the backrest project
|
|
|
|
if ($self->{oManifest}->isBackRest())
|
|
|
|
{
|
|
|
|
$self->{oReference} = new BackRestDoc::Common::DocConfig(${$self->{oManifest}->sourceGet('reference')}{doc}, $self);
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($$oRenderOut{source}) && $$oRenderOut{source} eq 'reference')
|
|
|
|
{
|
|
|
|
if ($self->{strRenderOutKey} eq 'configuration')
|
|
|
|
{
|
|
|
|
$self->{oDoc} = $self->{oReference}->helpConfigDocGet();
|
|
|
|
}
|
|
|
|
elsif ($self->{strRenderOutKey} eq 'command')
|
|
|
|
{
|
|
|
|
$self->{oDoc} = $self->{oReference}->helpCommandDocGet();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "cannot render $self->{strRenderOutKey} from source $$oRenderOut{source}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$self->{oDoc} = ${$self->{oManifest}->sourceGet($self->{strRenderOutKey})}{doc};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($self->{strRenderOutKey}))
|
|
|
|
{
|
|
|
|
# Build the doc
|
|
|
|
$self->build($self->{oDoc});
|
|
|
|
|
|
|
|
# Get required sections
|
|
|
|
foreach my $strPath (@{$self->{oManifest}->{stryRequire}})
|
|
|
|
{
|
|
|
|
if (defined(${$self->{oSection}}{$strPath}))
|
|
|
|
{
|
|
|
|
$self->required($strPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'self', value => $self}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# variableReplace
|
|
|
|
#
|
|
|
|
# Replace variables in the string.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub variableReplace
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return $self->{oManifest}->variableReplace(shift, $self->{strType});
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# variableSet
|
|
|
|
#
|
|
|
|
# Set a variable to be replaced later.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub variableSet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return $self->{oManifest}->variableSet(shift, shift);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# variableGet
|
|
|
|
#
|
|
|
|
# Get the current value of a variable.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub variableGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return $self->{oManifest}->variableGet(shift);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# build
|
|
|
|
#
|
|
|
|
# Build the section map and perform keyword matching.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub build
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $oNode = shift;
|
|
|
|
my $oParent = shift;
|
|
|
|
my $strPath = shift;
|
|
|
|
|
|
|
|
# &log(INFO, " node " . $oNode->nameGet());
|
|
|
|
|
|
|
|
my $strName = $oNode->nameGet();
|
|
|
|
|
|
|
|
if (defined($oParent))
|
|
|
|
{
|
|
|
|
if (!$self->{oManifest}->keywordMatch($oNode->paramGet('keyword', false)))
|
|
|
|
{
|
|
|
|
my $strDescription;
|
|
|
|
|
|
|
|
if (defined($oNode->nodeGet('title', false)))
|
|
|
|
{
|
|
|
|
$strDescription = $self->processText($oNode->nodeGet('title')->textGet());
|
|
|
|
}
|
|
|
|
|
|
|
|
&log(DEBUG, " filtered ${strName}" . (defined($strDescription) ? ": ${strDescription}" : ''));
|
|
|
|
|
|
|
|
$oParent->nodeRemove($oNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
&log(DEBUG, ' build document');
|
|
|
|
$self->{oSection} = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($strName eq 'section')
|
|
|
|
{
|
|
|
|
if (defined($strPath))
|
|
|
|
{
|
|
|
|
$oNode->paramSet('path-parent', $strPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
$strPath .= '/' . $oNode->paramGet('id');
|
|
|
|
|
|
|
|
&log(DEBUG, " path ${strPath}");
|
|
|
|
${$self->{oSection}}{$strPath} = $oNode;
|
|
|
|
$oNode->paramSet('path', $strPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Iterate all nodes
|
|
|
|
foreach my $oChild ($oNode->nodeList(undef, false))
|
|
|
|
{
|
|
|
|
$self->build($oChild, $oNode, $strPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# required
|
|
|
|
#
|
|
|
|
# Build a list of required sections
|
|
|
|
####################################################################################################################################
|
|
|
|
sub required
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strPath = shift;
|
|
|
|
my $bDepend = shift;
|
|
|
|
|
|
|
|
# If node is not found that means the path is invalid
|
|
|
|
my $oNode = ${$self->{oSection}}{$strPath};
|
|
|
|
|
|
|
|
if (!defined($oNode))
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "invalid path ${strPath}");
|
|
|
|
}
|
|
|
|
|
|
|
|
# Only add sections that are listed dependencies
|
|
|
|
if (!defined($bDepend) || $bDepend)
|
|
|
|
{
|
|
|
|
# Match section and all child sections
|
2016-05-19 16:25:04 +02:00
|
|
|
foreach my $strChildPath (sort(keys(%{$self->{oSection}})))
|
2015-11-22 23:44:01 +02:00
|
|
|
{
|
|
|
|
if ($strChildPath =~ /^$strPath$/ || $strChildPath =~ /^$strPath\/.*$/)
|
|
|
|
{
|
|
|
|
&log(INFO, " require section: ${strChildPath}");
|
|
|
|
|
|
|
|
${$self->{oSectionRequired}}{$strChildPath} = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Get the path of the current section's parent
|
|
|
|
my $strParentPath = $oNode->paramGet('path-parent', false);
|
|
|
|
|
|
|
|
if ($oNode->paramTest('depend'))
|
|
|
|
{
|
|
|
|
foreach my $strDepend (split(',', $oNode->paramGet('depend')))
|
|
|
|
{
|
|
|
|
if ($strDepend !~ /^\//)
|
|
|
|
{
|
|
|
|
if (!defined($strParentPath))
|
|
|
|
{
|
|
|
|
$strDepend = "/${strDepend}";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strDepend = "${strParentPath}/${strDepend}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->required($strDepend, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elsif (defined($strParentPath))
|
|
|
|
{
|
|
|
|
$self->required($strParentPath, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# isRequired
|
|
|
|
#
|
|
|
|
# Is it required to execute the section statements?
|
|
|
|
####################################################################################################################################
|
|
|
|
sub isRequired
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $oSection = shift;
|
|
|
|
|
|
|
|
if (!defined($self->{oSectionRequired}))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $strPath = $oSection->paramGet('path');
|
|
|
|
|
|
|
|
defined(${$self->{oSectionRequired}}{$strPath}) ? true : false;
|
|
|
|
}
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# process
|
|
|
|
#
|
|
|
|
# Render the document
|
|
|
|
####################################################################################################################################
|
|
|
|
sub process
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oDoc,
|
|
|
|
$iDepth,
|
|
|
|
$bChildList,
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->process', \@_,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'oDoc', trace => true},
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'iDepth', default => 1, trace => true},
|
|
|
|
{name => 'bChildList', default => true, trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $strType = $self->{strType};
|
|
|
|
|
|
|
|
my $strBuffer = "";
|
2015-09-08 13:31:24 +02:00
|
|
|
my $bList = $oDoc->nameGet() =~ /.*-bullet-list$/;
|
2015-09-03 00:55:04 +02:00
|
|
|
$bChildList = defined($bChildList) ? $bChildList : false;
|
|
|
|
my $iChildDepth = $iDepth;
|
|
|
|
|
|
|
|
my @stryMonth = ('January', 'February', 'March', 'April', 'May', 'June',
|
|
|
|
'July', 'August', 'September', 'October', 'November', 'December');
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
if ($strType eq 'markdown' || $strType eq 'text')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if (defined($oDoc->paramGet('id', false)))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
my @stryToken = split('-', $oDoc->nameGet());
|
2015-09-03 00:55:04 +02:00
|
|
|
my $strTitle = @stryToken == 0 ? '[unknown]' : $stryToken[@stryToken - 1];
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$strBuffer = ('#' x $iDepth) . ' `' . $oDoc->paramGet('id') . '` ' . $strTitle;
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
2016-04-14 01:05:31 +02:00
|
|
|
# Try to get the title param from the element (??? this is the old style and should be removed)
|
2015-10-28 11:10:36 +02:00
|
|
|
my $strTitle = $oDoc->paramGet('title', false);
|
|
|
|
|
|
|
|
if (!defined($strTitle))
|
|
|
|
{
|
|
|
|
$strTitle = $oDoc->paramGet('subtitle', false);
|
|
|
|
}
|
|
|
|
|
|
|
|
# If not found then get the title element
|
|
|
|
if (!defined($strTitle) && defined($oDoc->nodeGet('title', false)))
|
|
|
|
{
|
|
|
|
$strTitle = $self->processText($oDoc->nodeGet('title')->textGet());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($strTitle))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$strBuffer = ('#' x $iDepth) . ' ';
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
if (defined($oDoc->paramGet('version', false)))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
$strBuffer .= 'v' . $oDoc->paramGet('version') . ': ';
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
2016-04-16 17:55:23 +02:00
|
|
|
$strBuffer .= ($iDepth == 1 ? "{[project]} <br/> " : '') . $strTitle;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
if (defined($oDoc->paramGet('date', false)))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
my $strDate = $oDoc->paramGet('date');
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
if ($strDate !~ /^(XXXX-XX-XX)|([0-9]{4}-[0-9]{2}-[0-9]{2})$/)
|
|
|
|
{
|
|
|
|
confess "invalid date ${strDate}";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($strDate =~ /^X/)
|
|
|
|
{
|
|
|
|
$strBuffer .= "\n__No Release Date Set__";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strBuffer .= "\n__Released " . $stryMonth[(substr($strDate, 5, 2) - 1)] . ' ' .
|
|
|
|
(substr($strDate, 8, 2) + 0) . ', ' . substr($strDate, 0, 4) . '__';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($strBuffer ne "")
|
|
|
|
{
|
|
|
|
$iChildDepth++;
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
if (defined($oDoc->nodeGet('summary', false)))
|
|
|
|
{
|
|
|
|
if ($strBuffer ne "")
|
|
|
|
{
|
|
|
|
$strBuffer .= "\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($bChildList)
|
|
|
|
{
|
|
|
|
$strBuffer .= '* ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$strBuffer .= $self->processText($oDoc->nodeGet('summary')->textGet());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($oDoc->textGet(false)))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
if ($strBuffer ne "")
|
|
|
|
{
|
|
|
|
$strBuffer .= "\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($bChildList)
|
|
|
|
{
|
|
|
|
$strBuffer .= '* ';
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$strBuffer .= $self->processText($oDoc->textGet());
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($strBuffer ne "" && $iDepth != 1 && !$bList)
|
|
|
|
{
|
|
|
|
$strBuffer = "\n\n" . $strBuffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "unknown type ${strType}";
|
|
|
|
}
|
|
|
|
|
|
|
|
my $bFirst = true;
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
foreach my $oChild ($oDoc->nodeList(undef, false))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
if ($oChild->nameGet() ne 'summary' && $oChild->nameGet() ne 'title')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if ($strType eq 'markdown' || $strType eq 'text')
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "unknown type ${strType}";
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$strBuffer .= $self->process($oChild, $iChildDepth, $bList);
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($iDepth == 1)
|
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if ($strType eq 'markdown' || $strType eq 'text')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$strBuffer .= "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "unknown type ${strType}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strBuffer', value => $strBuffer, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# processTag
|
|
|
|
####################################################################################################################################
|
|
|
|
sub processTag
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oTag
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->processTag', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'oTag', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $strBuffer = "";
|
|
|
|
|
|
|
|
my $strType = $self->{strType};
|
2015-09-08 13:31:24 +02:00
|
|
|
my $strTag = $oTag->nameGet();
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
if (!defined($strTag))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
use Data::Dumper;
|
|
|
|
confess Dumper($oTag);
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
if ($strTag eq 'link')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
my $strUrl = $oTag->paramGet('url', false);
|
|
|
|
|
|
|
|
if ($strType eq 'markdown')
|
|
|
|
{
|
|
|
|
if (!defined($strUrl))
|
|
|
|
{
|
|
|
|
$strUrl = '{[backrest-url-base]}/' . $oTag->paramGet('page');
|
|
|
|
}
|
|
|
|
|
|
|
|
$strBuffer = '[' . $oTag->valueGet() . '](' . $strUrl . ')';
|
|
|
|
}
|
|
|
|
elsif ($strType eq 'html')
|
|
|
|
{
|
|
|
|
if (!defined($strUrl))
|
|
|
|
{
|
2015-12-23 18:04:26 +02:00
|
|
|
$strUrl = $oTag->paramGet('page', false);
|
|
|
|
|
|
|
|
if (!defined($strUrl))
|
|
|
|
{
|
|
|
|
$strUrl = '#' . substr($oTag->paramGet('section'), 1);
|
|
|
|
}
|
2015-10-28 11:10:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$strBuffer = '<a href="' . $strUrl . '">' . $oTag->valueGet() . '</a>';
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
elsif ($strType eq 'latex')
|
|
|
|
{
|
2015-12-23 18:04:26 +02:00
|
|
|
if (!defined($strUrl))
|
|
|
|
{
|
|
|
|
$strUrl = $oTag->paramGet('page', false);
|
|
|
|
|
|
|
|
if (!defined($strUrl))
|
|
|
|
{
|
|
|
|
$strUrl = $oTag->paramGet('section');
|
|
|
|
}
|
|
|
|
|
2016-03-10 17:58:07 +02:00
|
|
|
$strBuffer = "\\hyperref[$strUrl]{" . $oTag->valueGet() . "}";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strBuffer = "\\href{$strUrl}{" . $oTag->valueGet() . "}";
|
|
|
|
}
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
2015-10-28 11:10:36 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "tag link not valid for type ${strType}";
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
2015-09-08 13:31:24 +02:00
|
|
|
else
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
my $strStart = $$oRenderTag{$strType}{$strTag}[0];
|
|
|
|
my $strStop = $$oRenderTag{$strType}{$strTag}[1];
|
|
|
|
|
|
|
|
if (!defined($strStart) || !defined($strStop))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
confess "invalid type ${strType} or tag ${strTag}";
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
$strBuffer .= $strStart;
|
|
|
|
|
|
|
|
if ($strTag eq 'p' || $strTag eq 'title' || $strTag eq 'li' || $strTag eq 'code-block' || $strTag eq 'summary')
|
|
|
|
{
|
|
|
|
$strBuffer .= $self->processText($oTag);
|
|
|
|
}
|
|
|
|
elsif (defined($oTag->valueGet()))
|
|
|
|
{
|
|
|
|
$strBuffer .= $oTag->valueGet();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foreach my $oSubTag ($oTag->nodeList(undef, false))
|
|
|
|
{
|
|
|
|
$strBuffer .= $self->processTag($oSubTag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$strBuffer .= $strStop;
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strBuffer', value => $strBuffer, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# processText
|
|
|
|
####################################################################################################################################
|
|
|
|
sub processText
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oText
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->processText', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'oText', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $strType = $self->{strType};
|
2015-09-08 13:31:24 +02:00
|
|
|
my $strBuffer = '';
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
foreach my $oNode ($oText->nodeList(undef, false))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if (ref(\$oNode) eq "SCALAR")
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-11-22 23:44:01 +02:00
|
|
|
if ($oNode =~ /\"/)
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "unable to process quotes in string (use <quote> instead):\n${oNode}");
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$strBuffer .= $oNode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$strBuffer .= $self->processTag($oNode);
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-28 11:10:36 +02:00
|
|
|
#
|
|
|
|
# if ($strType eq 'html')
|
|
|
|
# {
|
|
|
|
# # $strBuffer =~ s/^\s+|\s+$//g;
|
|
|
|
#
|
|
|
|
# $strBuffer =~ s/\n/\<br\/\>\n/g;
|
|
|
|
# }
|
|
|
|
|
|
|
|
# if ($strType eq 'markdown')
|
|
|
|
# {
|
|
|
|
# $strBuffer =~ s/^\s+|\s+$//g;
|
|
|
|
|
|
|
|
$strBuffer =~ s/ +/ /g;
|
|
|
|
$strBuffer =~ s/^ //smg;
|
|
|
|
# }
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
if ($strType eq 'latex')
|
|
|
|
{
|
|
|
|
$strBuffer =~ s/\&mdash\;/---/g;
|
|
|
|
$strBuffer =~ s/\<\;/\</g;
|
|
|
|
$strBuffer =~ s/\<\=/\$\\leq\$/g;
|
|
|
|
$strBuffer =~ s/\>\=/\$\\geq\$/g;
|
|
|
|
# $strBuffer =~ s/\_/\\_/g;
|
|
|
|
}
|
|
|
|
|
|
|
|
$strBuffer = $self->variableReplace($strBuffer);
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strBuffer', value => $strBuffer, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# save
|
|
|
|
####################################################################################################################################
|
|
|
|
sub save
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strFileName,
|
|
|
|
$strBuffer
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->save', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'strFileName', trace => true},
|
|
|
|
{name => 'strBuffer', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
# Open the file
|
|
|
|
my $hFile;
|
|
|
|
open($hFile, '>', $strFileName)
|
|
|
|
or confess &log(ERROR, "unable to open ${strFileName}");
|
|
|
|
|
|
|
|
# Write the buffer
|
|
|
|
my $iBufferOut = syswrite($hFile, $strBuffer);
|
|
|
|
|
|
|
|
# Report any errors
|
|
|
|
if (!defined($iBufferOut) || $iBufferOut != length($strBuffer))
|
|
|
|
{
|
|
|
|
confess "unable to write '${strBuffer}'" . (defined($!) ? ': ' . $! : '');
|
|
|
|
}
|
|
|
|
|
|
|
|
# Close the file
|
|
|
|
close($hFile);
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|