package Solution::Document;
{
use strict;
use warnings;
use lib '../';
our $VERSION = '0.9.1';
use Solution::Variable;
use Solution::Utility;
#
sub resolve { $_[0]->template->context->resolve($_[1], $_[2]); }
sub template { $_[0]->{'template'} }
sub parent { $_[0]->{'parent'} }
#sub context { return $_[0]->{'context'}; }
#sub filters { return $_[0]->{'filters'}; }
#sub resolve {
# return $_[0]->context->resolve($_[1], defined $_[2] ? $_[2] : ());
#}
#sub stack { return $_[0]->context->stack($_[1]); }
#sub scopes { return $_[0]->context->scopes; }
#sub scope { return $_[0]->context->scope; }
#sub merge { return $_[0]->context->merge($_[1]); }
#BEGIN { our @ISA = qw[Solution::Template]; }
sub new {
my ($class, $args) = @_;
raise Solution::ContextError {message => 'Missing template argument',
fatal => 1
}
if !defined $args->{'template'};
return
bless {template => $args->{'template'},
parent => $args->{'template'}
}, $class;
}
sub parse {
my ($class, $args, $tokens);
(scalar @_ == 3 ? ($class, $args, $tokens) : ($class, $tokens)) = @_;
my $self = ref $class ? $class : $class->new($args);
NODE: while (my $token = shift @{$tokens}) {
if ($token =~ qr[^${Solution::Utility::TagStart} # {%
(.+?) # etc
${Solution::Utility::TagEnd} # %}
$]x
)
{ my ($tag, $attrs) = (split ' ', $1, 2);
my ($package, $call) = $self->template->tags->{$tag};
if ($package
&& ($call = $self->template->tags->{$tag}->can('new')))
{ my $_tag =
$call->($package,
{template => $self->template,
parent => $self,
tag_name => $tag,
markup => $token,
attrs => $attrs
}
);
push @{$self->{'nodelist'}}, $_tag;
if ($_tag->conditional_tag) {
push @{$_tag->{'blocks'}},
Solution::Block->new(
{tag_name => $tag,
attrs => $attrs,
template => $_tag->template,
parent => $_tag
}
);
$_tag->parse($tokens);
{ # finish previous block
${$_tag->{'blocks'}[-1]}{'nodelist'}
= $_tag->{'nodelist'};
$_tag->{'nodelist'} = [];
}
}
elsif ($_tag->end_tag) {
$_tag->parse($tokens);
}
}
elsif ($self->can('end_tag') && $tag =~ $self->end_tag) {
$self->{'markup_2'} = $token;
last NODE;
}
elsif ( $self->conditional_tag
&& $tag =~ $self->conditional_tag)
{ $self->push_block({tag_name => $tag,
attrs => $attrs,
markup => $token,
template => $self->template,
parent => $self
},
$tokens
);
}
else {
raise Solution::SyntaxError 'Unknown tag: ' . $token;
}
}
elsif (
$token =~ qr[^
${Solution::Utility::VariableStart} # {{
(.+?) # stuff + filters?
${Solution::Utility::VariableEnd} # }}
$]x
)
{ my ($variable, $filters) = split qr[\s*\|\s*], $1, 2;
my @filters;
for my $filter (split $Solution::Utility::FilterSeparator,
$filters || '')
{ my ($filter, $args)
= split $Solution::Utility::FilterArgumentSeparator,
$filter, 2;
$filter =~ s[\s*$][]; # XXX - the splitter should clean...
$filter =~ s[^\s*][]; # XXX - ...this up for us.
my @args
= $args ?
split
$Solution::Utility::VariableFilterArgumentParser,
$args
: ();
push @filters, [$filter, \@args];
}
push @{$self->{'nodelist'}},
Solution::Variable->new({template => $self->template,
parent => $self,
markup => $token,
variable => $variable,
filters => \@filters
}
);
}
else {
push @{$self->{'nodelist'}}, $token;
}
}
return $self;
}
sub render {
my ($self) = @_;
my $return = '';
for my $node (@{$self->{'nodelist'}}) {
my $rendering = ref $node ? $node->render() : $node;
$return .= defined $rendering ? $rendering : '';
}
return $return;
}
sub conditional_tag { return $_[0]->{'conditional_tag'} || undef; }
}
1;