use strict;
use warnings;
use Slay::Maker;
use File::Next;
use Path::Class;
use File::Cache::Parsed;
use Cwd 'abs_path';
use Text::Restructured;
use Text::Restructured::Writer::LibXML;
use YAML::Syck;
use Getopt::Long;
use WebCoso::Common;
use WebCoso::TT;
use WebCoso::XSLT;
my @TMPLPATH=('common/');
my $CLEAN=0;
{
my $res=GetOptions('src|s=s'=>\$WebCoso::Common::SRCPATH,
'dst|d=s'=>\$WebCoso::Common::DSTPATH,
'url|u=s'=>\$WebCoso::Common::DSTBASEURL,
'include|I=s'=>\@TMPLPATH,
'clean'=>\$CLEAN,
);
exit 1 unless $res;
$WebCoso::Common::SRCPATH=~s{/+$}{};
$WebCoso::Common::DSTPATH=~s{/+$}{};
$WebCoso::Common::DSTBASEURL=~s{/*$}{/};
}
my $rest=Text::Restructured->new(
{
D=>{
'file-insertion-enabled'=>0,
generator=>0,
date=>0,
'time'=>0,
'source-link'=>0,
'section-subtitles'=>1,
},
},
'WebCoso');
my $fc=File::Cache::Parsed->new(follow=>1);
$fc->add_parser(qr{\.rest\.txt$} =>
sub {
my $dudom=$rest->Parse($_[1],$_[0]);
return Text::Restructured::Writer::LibXML
->new->ProcessDOM($dudom);
});
$fc->add_parser(qr{\.ya?ml$} =>
sub { Load($_[1]) });
$fc->add_writer(qr{\.ya?ml$} =>
sub { DumpFile($_[0],$_[1]) });
my $template=WebCoso::TT->new(TMPLPATH=>\@TMPLPATH,fc=>$fc);
my $xslt=WebCoso::XSLT->new(fc=>$fc);
sub parseRST {
my ($maker,$target,$deps,$matches)=@_;
$fc->put($target,$fc->get($deps->[-1]));
}
sub getTags {
my ($maker,$target,$deps,$matches)=@_;
$fc->put($target,WebCoso::Common::getTags($fc,@$deps));
}
sub getChanges {
my ($maker,$target,$deps,$matches)=@_;
warn "changes: $target <- @$deps, @$matches\n";
open my $fh,'>',$target;
}
sub ifExists {
my ($src)=@_;
return sub {
my ($maker,$target,$matches)=@_;
my $dep=Slay::MakerRule::var_expand_dep($src,$target,$matches);
return if -e $target and ! -e $dep;
return $dep;
}
}
sub fromTo {
my ($base,$opts)=@_;
my $iter=File::Next::files(
{
file_filter=>$opts->{files},
descend_filter=>$opts->{dirs},
},
$base);
my (@ret,$file);
if (defined $opts->{transform}) {
push @ret,$opts->{transform}->($file) while $file=$iter->();
}
else {
push @ret,$file while $file=$iter->();
}
return @ret;
}
{
my %order=(
'rest.tt'=>0,
'rest.txt'=>1,
'du.xml'=>2,
);
sub earliest {
my ($a,$b)=@_;
return $a unless $b;
return $order{$a} < $order{$b}
? $a
: $b;
}
sub keepEarliest {
my %dirs;
for my $f (@_) {
my $c=file($f);
my $lang=WebCoso::Common::langOf($c->basename);
my $type=WebCoso::Common::typeOf($c->basename);
if (!defined $lang or !defined $type) {
die "Weird document name <$f>";
}
$dirs{$c->parent}->{$lang}=earliest($type,$dirs{$c->parent}->{$lang});
}
my @ret;
while (my ($d,$langs)=each %dirs) {
while (my ($lang,$type)=each %$langs) {
push @ret,file($d,"document.$lang.$type")->stringify;
}
}
return @ret;
}
}
my %docfiles=(
files=>sub{m{^document\.}},
dirs=>sub{!m{^(tags|_webcoso|\.svn)$}});
if ($CLEAN) {
my %to_keep;
@to_keep{keepEarliest(fromTo($WebCoso::Common::SRCPATH,{%docfiles,dirs=>sub{!m{^(_webcoso|\.svn)$}}}))}=();
@to_keep{fromTo($WebCoso::Common::SRCPATH,{files=>sub{!m{^document\.}},dirs=>sub{!m{^(_webcoso|\.svn)$}}})}=();
my $iter=File::Next::files({descend_filter=>sub{!m{^\.svn$}}},$WebCoso::Common::SRCPATH,$WebCoso::Common::DSTPATH);
while (defined (my $file=$iter->())) {
next if exists $to_keep{$file};
unlink $file;
}
dir($WebCoso::Common::DSTPATH)->rmtree;
dir($WebCoso::Common::SRCPATH,'_webcoso')->rmtree;
exit 0;
}
my %maker_opts=(
options => {
auto_create_dirs => 1,
},
);
my @passes=(
{maker=>Slay::Maker->new({
rules => [
["$WebCoso::Common::SRCPATH/tags/(**)/document.(*).rest.txt",
':',
"$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
ifExists("$WebCoso::Common::SRCPATH/tags/\$1/document.\$2.rest.tt"),
'=',
$template->expandTT()],
["$WebCoso::Common::SRCPATH/tags/(**)/document.(*).du.xml",
':',
"$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
ifExists("$WebCoso::Common::SRCPATH/tags/\$1/document.\$2.rest.txt"),
'=',
\&parseRST],
["$WebCoso::Common::SRCPATH/(**)/document.(*).rest.txt",
':',
ifExists("$WebCoso::Common::SRCPATH/\$1/document.\$2.rest.tt"),
'=',
$template->expandTT()],
["$WebCoso::Common::SRCPATH/(**)/document.(*).du.xml",
':',
ifExists("$WebCoso::Common::SRCPATH/\$1/document.\$2.rest.txt"),
'=',
\&parseRST],
["$WebCoso::Common::SRCPATH/()document.(*).rest.txt",
':',
ifExists("$WebCoso::Common::SRCPATH/document.\$2.rest.tt"),
'=',
$template->expandTT()],
["$WebCoso::Common::SRCPATH/()document.(*).du.xml",
':',
ifExists("$WebCoso::Common::SRCPATH/document.\$2.rest.txt"),
'=',
\&parseRST],
["$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
':',
fromTo($WebCoso::Common::SRCPATH,
{
%docfiles,
transform=>sub{WebCoso::Common::typedAs($_[0],'du.xml')}
}),
'=',
\&getTags],
["$WebCoso::Common::SRCPATH/_webcoso/changes.xml",
':',
keepEarliest(fromTo($WebCoso::Common::SRCPATH,{%docfiles})),
'=',
\&getChanges],
],
%maker_opts,
}),
targets=>[
fromTo("$WebCoso::Common::SRCPATH/",
{
%docfiles,
transform=>sub{WebCoso::Common::typedAs($_[0],'du.xml')},
}),
fromTo("$WebCoso::Common::SRCPATH/tags/",
{
%docfiles,
transform=>sub{WebCoso::Common::typedAs($_[0],'du.xml')},
})]},
{maker=>Slay::Maker->new({
rules => [
["$WebCoso::Common::DSTPATH/tags/(**)/document.(*).html",
':',
"$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
"$WebCoso::Common::SRCPATH/tags/\$1/document.\$2.du.xml",
'=',
$xslt->du2html()],
["$WebCoso::Common::DSTPATH/(**)/document.(*).html",
':',
"$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
"$WebCoso::Common::SRCPATH/\$1/document.\$2.du.xml",
'=',
$xslt->du2html()],
["$WebCoso::Common::DSTPATH/()document.(*).html",
':',
"$WebCoso::Common::SRCPATH/_webcoso/tags.yml",
"$WebCoso::Common::SRCPATH/document.\$2.du.xml",
'=',
$xslt->du2html()],
],
%maker_opts,
}),
targets=>[fromTo("$WebCoso::Common::SRCPATH/",
{
%docfiles,
transform=>sub{
(my $file=WebCoso::Common::typedAs($_[0],'html'))
=~s{^\Q$WebCoso::Common::SRCPATH\E/}{$WebCoso::Common::DSTPATH/};
return $file;
},
}),
fromTo("$WebCoso::Common::SRCPATH/tags/",
{
%docfiles,
transform=>sub{
(my $file=WebCoso::Common::typedAs($_[0],'html'))
=~s{^\Q$WebCoso::Common::SRCPATH\E/tags/}{$WebCoso::Common::DSTPATH/tags/};
return $file;
},
})]},
);
$_->{maker}->make(@{$_->{targets}}) for @passes;