#! /bin/false
$Qgoda::Builder::VERSION
=
'0.9.8'
;
use
Qgoda::Util
qw(empty read_file read_body write_file blength)
;
sub
new {
my
$self
=
''
;
bless
\
$self
,
shift
;
}
sub
build {
my
(
$self
,
$site
,
%options
) =
@_
;
my
$qgoda
= Qgoda->new;
my
$logger
=
$qgoda
->logger;
my
$config
=
$qgoda
->config;
my
$site
=
$qgoda
->getSite;
my
$errors
=
$site
->getErrors;
ASSET:
foreach
my
$asset
(
sort
{
$b
->{priority} <=>
$a
->{priority} }
$site
->getAssets) {
my
$saved_locale
= setlocale(POSIX::LC_ALL());
eval
{
local
$SIG
{__WARN__} =
sub
{
my
(
$msg
) =
@_
;
$logger
->warning(
"$asset->{path}: $msg"
);
};
$logger
->debug(__x(
"processing asset '/{relpath}'"
,
relpath
=>
$asset
->getRelpath));
$self
->processAsset(
$asset
,
$site
);
};
if
($@) {
++
$errors
;
my
$path
=
$asset
->getPath;
$logger
->error(
"$path: $@"
);
}
setlocale(POSIX::LC_ALL(),
$saved_locale
);
}
$site
->computeRelations;
ASSET:
foreach
my
$asset
(
sort
{
$b
->{priority} <=>
$a
->{priority} }
$site
->getAssets) {
if
(
$asset
->{virtual}) {
$logger
->debug(__x(
"not wrapping virtual asset '/{relpath}'"
,
relpath
=>
$asset
->getRelpath));
next
;
}
my
$saved_locale
= setlocale(POSIX::LC_ALL());
eval
{
local
$SIG
{__WARN__} =
sub
{
my
(
$msg
) =
@_
;
$logger
->warning(
"$asset->{path}: $msg"
);
};
$logger
->debug(__x(
"wrapping asset '/{relpath}'"
,
relpath
=>
$asset
->getRelpath));
$self
->wrapAsset(
$asset
,
$site
);
if
(!
$options
{dry_run}) {
$self
->saveArtefact(
$asset
,
$site
,
$asset
->{location});
}
$logger
->debug(__x(
"successfully built '{location}'"
,
location
=>
$asset
->{location}));
};
if
($@) {
++
$errors
;
my
$path
=
$asset
->getPath;
$logger
->error(
"$path: $@"
);
}
setlocale(POSIX::LC_ALL(),
$saved_locale
);
}
if
(
$errors
) {
$logger
->error(
">>>>>>>>>>>>>>>>>>>"
);
$logger
->error(__nx(
"one artefact has not been built because of errors (see above)"
,
"{num} artefacts have not been built because of errors (see above)"
,
$errors
,
num
=>
$errors
))
if
$errors
;
$logger
->error(
">>>>>>>>>>>>>>>>>>>"
);
}
return
$self
;
}
sub
readAssetContent {
my
(
$self
,
$asset
,
$site
) =
@_
;
if
(
$asset
->{raw}) {
return
read_file(
$asset
->getPath);
}
elsif
(!empty
$asset
->{master}) {
return
translate_body
$asset
;
}
else
{
my
$chain
=
$asset
->{chain};
my
$config
= Qgoda->new->config;
my
$placeholder
=
$config
->{
'front-matter-placeholder'
}->{
$chain
}
||
$config
->{
'front-matter-placeholder'
}->{
'*'
};
return
read_body(
$asset
->getPath,
$placeholder
);
}
}
sub
saveArtefact {
my
(
$self
,
$asset
,
$site
,
$permalink
) =
@_
;
my
$qgoda
= Qgoda->new;
my
$config
=
$qgoda
->config;
$permalink
=
'/'
.
$asset
->getRelpath
if
empty
$permalink
;
my
$path
= File::Spec->catdir(
$config
->{paths}->{site},
$permalink
);
my
$existing
=
$site
->getArtefact(
$path
);
if
(
$existing
) {
my
$origin
=
$existing
->getAsset;
my
$logger
=
$qgoda
->logger;
$logger
->warning(__x(
"Overwriting artefact at '{outpath}', "
.
"origin: {origin}"
,
outpath
=>
$path
,
origin
=>
$origin
?
$origin
->getOrigin : __
"[unknown origin]"
));
}
my
$write_file
= 1;
if
(
$config
->{
'compare-output'
}) {
my
@stat
=
stat
$path
;
if
(
@stat
) {
if
(
$stat
[7] == blength
$asset
->{content}) {
my
$old
= read_file
$path
;
Encode::_utf8_on(
$old
)
if
Encode::is_utf8(
$asset
->{content});
if
(
defined
$old
&&
$old
eq
$asset
->{content}) {
undef
$write_file
;
$qgoda
->logger->debug(__x(
"Skipping unchanged file"
.
" '{output}'"
,
output
=>
$path
));
}
}
}
}
if
(
$write_file
) {
$site
->addModified(
$path
,
$asset
);
unless
(write_file
$path
,
$asset
->{content}) {
my
$logger
=
$qgoda
->logger;
$logger
->error(__x(
"error writing '{filename}': {error}"
,
filename
=>
$path
,
error
=> $!));
return
;
}
}
$site
->addArtefact(
$path
,
$asset
);
}
sub
processAsset {
my
(
$self
,
$asset
,
$site
) =
@_
;
my
$qgoda
= Qgoda->new;
my
$logger
=
$qgoda
->logger;
$logger
->debug(__x(
"processing asset '/{relpath}'"
,
relpath
=>
$asset
->getRelpath));
my
$template_name
=
$asset
->getRelpath;
my
$content
=
$self
->readAssetContent(
$asset
,
$site
);
$asset
->{content} =
$content
;
my
@processors
=
$qgoda
->getProcessors(
$asset
);
foreach
my
$processor
(
@processors
) {
my
$short_name
=
ref
$processor
;
$short_name
=~ s/^Qgoda::Processor:://;
$logger
->debug(__x(
"processing with {processor}"
,
processor
=>
$short_name
));
$asset
->{content} =
$processor
->process(
$asset
->{content},
$asset
,
$template_name
);
Encode::_utf8_on(
$asset
->{content})
if
!
$asset
->{raw};
}
if
(
@processors
) {
my
%postmeta
=
$processors
[-1]->postMeta(
$asset
->{content},
$asset
,
$site
);
$asset
->{excerpt} =
$postmeta
{excerpt}
if
empty
$asset
->{excerpt};
$asset
->{links} ||=
$postmeta
{links};
}
return
$self
;
}
sub
wrapAsset {
my
(
$self
,
$asset
) =
@_
;
my
$qgoda
= Qgoda->new;
my
$site
=
$qgoda
->getSite;
my
@processors
=
$qgoda
->getWrapperProcessors(
$asset
);
return
$self
if
!
@processors
;
my
$view
=
$asset
->{view};
die
__
"no view specified.\n"
if
empty
$view
;
my
$logger
=
$qgoda
->logger;
my
$srcdir
=
$qgoda
->config->{srcdir};
my
$view_dir
=
$qgoda
->config->{paths}->{views};
my
$view_file
= File::Spec->
join
(
$srcdir
,
$view_dir
,
$view
);
if
(-e
$view_file
&& !
$qgoda
->versionControlled(
$view_file
, 1)) {
die
__x(
"view file '{file}' is not under version control.\n"
,
file
=>
$view_file
);
}
if
(!-e
$view_file
&&
'default.html'
eq
$view
) {
warn
__x(
"no default view '{file}', creating one with defaults.\n"
,
file
=>
$view_file
);
my
$msg
= __x(
"This view has been automatically created. Please edit "
.
" '{path}' to your needs!"
,
path
=>
$view_file
);
my
$html
=
<<EOF;
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>[% asset.title | html %]</title>
</head>
<body>
<h1>[% asset.title | html %]</h1>
[% asset.content %]
<p>$msg</p>
</body>
</html>
EOF
write_file
$view_file
,
$html
or
die
__x(
"error writing view '{file}': {error}.\n"
,
file
=>
$view_file
,
error
=> $!);
}
my
$content
= read_file
$view_file
;
die
__x(
"error reading view '{file}': {error}.\n"
,
file
=>
$view_file
,
error
=> $!)
if
!
defined
$content
;
Encode::_utf8_on(
$content
)
if
!
$asset
->{raw};
my
$template_name
= File::Spec->
join
(
$view_dir
,
$view
);
foreach
my
$processor
(
@processors
) {
my
$short_name
=
ref
$processor
;
$short_name
=~ s/^Qgoda::Processor:://;
$logger
->debug(__x(
"wrapping with {processor}"
,
processor
=>
$short_name
));
$content
=
$processor
->process(
$content
,
$asset
,
$template_name
);
Encode::_utf8_on(
$content
)
if
!
$asset
->{raw};
}
$asset
->{content} =
$content
;
return
$self
;
}
1;
=head1 NAME
Qgoda::Builder - Default builder
for
Qgoda posts.