diff --git a/cpanfile b/cpanfile index 6638c4e2c..852c469f9 100644 --- a/cpanfile +++ b/cpanfile @@ -35,7 +35,7 @@ requires 'Ref::Util'; requires 'Safe::Isa'; requires 'Sub::Quote'; requires 'Template'; -requires 'Template::Tiny'; +requires 'Template::Tiny', '1.16'; requires 'Test::Builder'; requires 'Test::More'; requires 'Types::Standard'; diff --git a/lib/Dancer2/Template/Implementation/ForkedTiny.pm b/lib/Dancer2/Template/Implementation/ForkedTiny.pm deleted file mode 100644 index 6347a90da..000000000 --- a/lib/Dancer2/Template/Implementation/ForkedTiny.pm +++ /dev/null @@ -1,369 +0,0 @@ -package Dancer2::Template::Implementation::ForkedTiny; - -# ABSTRACT: Dancer2 own implementation of Template::Tiny - -use 5.00503; -use strict; -no warnings; -use Ref::Util qw; - -# Evaluatable expression -my $EXPR = qr/ [a-z_][\w.]* /xs; - -sub new { - my $self = bless { - start_tag => '[%', - end_tag => '%]', - @_[ 1 .. $#_ ] - }, - $_[0]; - -# Opening tag including whitespace chomping rules - my $LEFT = $self->{LEFT} = qr/ - (?: - (?: (?:^|\n) [ \t]* )? \Q$self->{start_tag}\E\- - | - \Q$self->{start_tag}\E \+? - ) \s* -/xs; - -# Closing %] tag including whitespace chomping rules - my $RIGHT = $self->{RIGHT} = qr/ - \s* (?: - \+? \Q$self->{end_tag}\E - | - \-\Q$self->{end_tag}\E (?: [ \t]* \n )? - ) -/xs; - -# Preparsing run for nesting tags - $self->{PREPARSE} = qr/ - $LEFT ( IF | UNLESS | FOREACH ) \s+ - ( - (?: \S+ \s+ IN \s+ )? - \S+ ) - $RIGHT - (?! - .*? - $LEFT (?: IF | UNLESS | FOREACH ) \b - ) - ( .*? ) - (?: - $LEFT ELSE $RIGHT - (?! - .*? - $LEFT (?: IF | UNLESS | FOREACH ) \b - ) - ( .+? ) - )? - $LEFT END $RIGHT -/xs; - - $self->{CONDITION} = qr/ - \Q$self->{start_tag}\E\s - ( ([IUF])\d+ ) \s+ - (?: - ([a-z]\w*) \s+ IN \s+ - )? - ( $EXPR ) - \s\Q$self->{end_tag}\E - ( .*? ) - (?: - \Q$self->{start_tag}\E\s \1 \s\Q$self->{end_tag}\E - ( .+? ) - )? - \Q$self->{start_tag}\E\s \1 \s\Q$self->{end_tag}\E -/xs; - - $self; -} - -# Copy and modify -sub preprocess { - my $self = shift; - my $text = shift; - $self->_preprocess( \$text ); - return $text; -} - -sub process { - my $self = shift; - my $copy = ${ shift() }; - my $stash = shift || {}; - - local $@ = ''; - local $^W = 0; - - # Preprocess to establish unique matching tag sets - $self->_preprocess( \$copy ); - - # Process down the nested tree of conditions - my $result = $self->_process( $stash, $copy ); - if (@_) { - ${ $_[0] } = $result; - } - elsif ( defined wantarray ) { - require Carp; - Carp::carp( - 'Returning of template results is deprecated in Template::Tiny 0.11' - ); - return $result; - } - else { - print $result; - } -} - - -###################################################################### -# Support Methods - -# The only reason this is a standalone is so we can -# do more in-depth testing. -sub _preprocess { - my $self = shift; - my $copy = shift; - - # Preprocess to establish unique matching tag sets - my $id = 0; - 1 while $$copy =~ s/ - $self->{PREPARSE} - / - my $tag = substr($1, 0, 1) . ++$id; - "\[\% $tag $2 \%\]$3\[\% $tag \%\]" - . (defined($4) ? "$4\[\% $tag \%\]" : ''); - /sex; -} - -sub _process { - my ( $self, $stash, $text ) = @_; - - $text =~ s/ - $self->{CONDITION} - / - ($2 eq 'F') - ? $self->_foreach($stash, $3, $4, $5) - : eval { - $2 eq 'U' - xor - !! # Force boolification - $self->_expression($stash, $4) - } - ? $self->_process($stash, $5) - : $self->_process($stash, $6) - /gsex; - - # Resolve expressions - $text =~ s/ - $self->{LEFT} ( $EXPR ) $self->{RIGHT} - / - eval { - $self->_expression($stash, $1) - . '' # Force stringification - } - /gsex; - - # Trim the document - $text =~ s/^\s*(.+?)\s*\z/$1/s if $self->{TRIM}; - - return $text; -} - -# Special handling for foreach -sub _foreach { - my ( $self, $stash, $term, $expr, $text ) = @_; - - # Resolve the expression - my $list = $self->_expression( $stash, $expr ); - is_arrayref($list) or return ''; - - # Iterate - return join '', - map { $self->_process( { %$stash, $term => $_ }, $text ) } @$list; -} - -# Evaluates a stash expression -sub _expression { - my $cursor = $_[1]; - my @path = split /\./, $_[2]; - foreach (@path) { - - # Support for private keys - return if substr( $_, 0, 1 ) eq '_'; - - # Split by data type - ref $cursor or return ''; - if ( is_arrayref($cursor) ) { - return '' unless /^(?:0|[0-9]\d*)\z/; - $cursor = $cursor->[$_]; - } - elsif ( is_plain_hashref($cursor) ) { - $cursor = $cursor->{$_}; - } - else { - $cursor = $cursor->$_(); - } - } - - # If the last expression is a CodeRef, execute it - is_coderef($cursor) - and $cursor = $cursor->(); - return $cursor; -} - -1; - -__END__ - -=pod - -=head1 NAME - -Dancer2::Template::Implementation::ForkedTiny - Template Toolkit reimplemented in as little code as possible, forked from Template::Tiny - -=head1 SYNOPSIS - - my $template = Dancer2::Template::Implementation::ForkedTiny->new( - TRIM => 1, - ); - - # Print the template results to STDOUT - $template->process( <<'END_TEMPLATE', { foo => 'World' } ); - Hello [% foo %]! - END_TEMPLATE - -=head1 DESCRIPTION - -B is a reimplementation of a subset of the functionality from -L