Skip to content
Browse files

*** empty log message ***

git-svn-id: svn://svn.tt2.org/tt/Template2/trunk@14 d5a88997-0a34-4036-9ed2-92fb5d660d91
  • Loading branch information...
1 parent 3070bc1 commit 850d474a574b9f3e8d7b2a88b8f26bd6854b4c2d @abw committed
Showing with 923 additions and 113 deletions.
  1. +59 −34 TODO
  2. +19 −9 lib/Template/Context.pm
  3. +2 −0 lib/Template/Filters.pm
  4. +1 −0 lib/Template/Grammar.pm
  5. +242 −0 lib/Template/Plugin/Date.pm
  6. +1 −0 lib/Template/Plugins.pm
  7. +73 −66 lib/Template/Service.pm
  8. +19 −0 lib/Template/Test.pm
  9. +1 −0 parser/Grammar.pm.skel
  10. +1 −1 t/README
  11. +186 −0 t/date.t
  12. +262 −0 t/directive.t
  13. +20 −1 t/document.t
  14. +35 −0 t/filter.t
  15. +1 −1 t/include.t
  16. +1 −1 t/service.t
View
93 TODO
@@ -1,40 +1,54 @@
Pending
-------
-* cvs add t/test/src/incblock for t/include.t
+* Template -> Service -> Context -> Stash
+ -> Provider -> Parser -> Grammar
+ -> Document
+ -> Directive
+ -> Plugins -> Plugin -> Plugin::*
+ -> Filters
-Fix
----
+ + Base, Config, Constants, Exception, Iterator, Test, Utils
+
+Misc
+----
-* Fix Plugin.pm
+* Fix Plugin.pm - it's still basically v1 code and much can be discarded
-* Change ttree to have knowledge of new config options
+* Memory leaks (there's something creating circular references and it's
+ probably glaringly obvious but I haven't bothered to look yet)
-* Improve tpage to do the same
+* Change ttree to have knowledge of new config options. Add --define option
+ to define a template variable.
+
+* Improve tpage to do the same (i.e. have --define, at least)
* A COMPILE_DIR option to compliment COMPILE_EXT, specifying an alternate
directory in which to store compiled template documents.
-* Change filter factory interface to accept $context as first parameter?
+* Modules are mostly autoloaded. Need PRELOAD option to preload all relevant
+ modules? (e.g. for mod_perl)
+
+* a FOR, like FOREACH but without using an iterator?
+
+* Change filter factory interface to accept $context as first parameter.
+ Dynamic dynamic filters can't grab context reference and some of them
+ need it.
+
+* add 'perl' filter - needs context access noted above to test EVAL_PERL
+
+* filters and plugins cache may bloat. Perhaps reset() should accept
+ flags to clear BLOCKS, PLUGINS, FILTERS, etc.
* Do something (i.e. mail Lincoln) about the CGI special case in
Template::Stash to work around the problem of CGI objects disclaiming
membership of the UNVIERSAL class after the first method call.
+* copy over new plugins and filters from v1.07
+
* Change docs/examples to uniformly name the template variable hash as
'$replace'.
-* Modules are mostly autoloaded. Need PRELOAD option to preload all relevant
- modules? (e.g. for mod_perl)
-
-* a FOR, like FOREACH but without using an iterator?
-
-* block persistance - sometimes need to define BLOCKs that persist
- through service invocations (AUTO_RESET => 0).
-
-* BLOCK caching is still a little messy - it works, but with belt and braces.
- Need to finalise behaviour wrt importing BLOCK defs via INCLUDE/PROCESS.
-
* note that no recursion checking is performed for BLOCKs, only
Template::Document instances
@@ -42,9 +56,6 @@ Fix
DONT_COMPILE (e.g. for [% INSERT file %] directive), or should there
be public interfaces for load(), compile(), etc.?
-* should be able to pre-define BLOCKS as text which is auto-pre-compiled
- - may rely on above to get access to Provider's PARSER object.
-
* move Template::Utils::output somewhere better (Template.pm?) and get rid
of Template::Utils
@@ -54,21 +65,12 @@ Fix
* change all hardcoded object isa tests to use $Template::Config:XXXXX
e.g. if (UNIVERSAL::isa($foo, $Template::Config::CONTEXT))
-* filters and plugins cache may bloat...
-
-* dynamic filters can't grab context reference - this screws up 'redirect'
- filter which needs fixing/replacing anyway
-
-* add 'perl' filter - needs context access to determine if allowed or not.
* check [% INCLUDE $template %] works where $template is a Template::Document
-* copy over new plugins and filters from v1.07, changes to Template::Test,
- and any other changes...
+* merge Directive into Parse.yp via template?
-* fix \@ quoting (and others) in Directive and email dude who sent patch.
-* merge Directive into Parse.yp via template?
-- DONE --
@@ -87,7 +89,7 @@ Fix
* fixed if/elsif generation
-* optimised FOREACH to only use an iterator if already so ( but note that
+* optimised FOREACH to only use an iterator if already so (but note that
this got changed again later)
* cleaned up Template::Iterator. Now derived from Template::Base.
@@ -102,9 +104,32 @@ Fix
* Fixed bug in parse grammer preventing commas in a META list
-* Added cache persistance. Had to re-organise a bunch of code around the
- parser/provider/document. Activated by COMPILE_EXT configuration item.
+* Added cache persistance by writing real Perl to file (rather than
+ the previous Data::Dumper dump of the opcode tree). Had to
+ re-organise a bunch of code around the parser/provider/document. Activated
+ by COMPILE_EXT configuration item.
* Added a work-around in Template::Stash to the problem of CGI disclaiming
membership of the UNIVERSAL class after the first method call.
+* block persistance - sometimes need to define BLOCKs that persist
+ through service invocations (AUTO_RESET => 0).
+
+* fix \@ quoting (and others) in Directive (Perrin reported / Chuck patched)
+
+* BLOCK caching is still a little messy - it works, but with belt and braces.
+ Need to finalise behaviour wrt importing BLOCK defs via INCLUDE/PROCESS.
+
+* Added Date plugin and test, as provided by Thierry-Michel Barral and abw.
+
+* Integrate changes to Template::Test from version 1.07 and beyond. Now
+ supports -- process - option in expect, mainly for use of t/date.t et al.
+
+* Integrated new upper and lower filters from 1.08, and '|' alias for FILTER
+ from 1.07.
+
+* Added new directive.t test to test chomping and comments.
+
+* should be able to pre-define BLOCKS as text which is auto-pre-compiled
+ - may rely on above to get access to Provider's PARSER object.
+
View
28 lib/Template/Context.pm
@@ -415,18 +415,17 @@ sub leave {
#------------------------------------------------------------------------
-# reset_blocks(\%blocks)
+# reset()
#
# Reset the state of the internal BLOCKS hash to clear any BLOCK
-# definitions imported via the PROCESS directive. A hash reference
-# can be passed to provide default BLOCK definitions which should be
-# used to re-initialise it.
+# definitions imported via the PROCESS directive. Any original
+# BLOCKS definitions passed to the constructor will be restored.
#------------------------------------------------------------------------
-sub reset_blocks {
+sub reset {
my ($self, $blocks) = @_;
$self->{ BLKSTACK } = [ ];
- $self->{ BLOCKS } = { $blocks ? %$blocks : () };
+ $self->{ BLOCKS } = { %{ $self->{ INIT_BLOCKS } } };
}
@@ -479,7 +478,7 @@ sub DESTROY {
sub _init {
my ($self, $config) = @_;
- my ($name, $item, $method);
+ my ($name, $item, $method, $block, $blocks);
my @itemlut = (
TEMPLATES => 'provider',
PLUGINS => 'plugins',
@@ -506,16 +505,27 @@ sub _init {
|| return $self->error($Template::Config::ERROR);
};
+ # compile any template BLOCKS specified as text
+ $blocks = $config->{ BLOCKS } || { };
+ $self->{ INIT_BLOCKS } = $self->{ BLOCKS } = {
+ map {
+ $block = $blocks->{ $_ };
+ $block = $self->template(\$block)
+ || return undef
+ unless ref $block;
+ ($_ => $block);
+ }
+ keys %$blocks
+ };
+
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# EVAL_PERL - flag indicating if PERL blocks should be processed
# EVAL_PERL - flag to remove leading and trailing whitespace from output
# BLKSTACK - list of hashes of BLOCKs defined in current template(s)
- # BLOCKS - hash of local BLOCKs imported from templates via PROCESS
$self->{ EVAL_PERL } = $config->{ EVAL_PERL } || 0;
$self->{ TRIM } = $config->{ TRIM } || 0;
$self->{ BLKSTACK } = [ ];
- $self->{ BLOCKS } = { };
return $self;
}
View
2 lib/Template/Filters.pm
@@ -38,6 +38,8 @@ $STD_FILTERS = {
'html' => sub { return \&html_filter },
'html_para' => sub { return \&html_paragraph; },
'html_break' => sub { return \&html_break; },
+ 'upper' => sub { return sub { uc $_[0] } },
+ 'lower' => sub { return sub { lc $_[0] } },
# dynamic filters
'format' => \&format_filter_factory,
View
1 lib/Template/Grammar.pm
@@ -68,6 +68,7 @@ $LEXTABLE = {
'&&' => 'AND',
'||' => 'OR',
'!' => 'NOT',
+ '|' => 'FILTER',
'.' => 'DOT',
'..' => 'TO',
# ':' => 'MACRO',
View
242 lib/Template/Plugin/Date.pm
@@ -0,0 +1,242 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::Date
+#
+# DESCRIPTION
+#
+# Plugin to generate formatted date strings.
+#
+# AUTHORS
+# Thierry-Michel Barral <kktos@electron-libre.com>
+# Andy Wardley <abw@cre.canon.co.uk>
+#
+# COPYRIGHT
+# Copyright (C) 2000 Thierry-Michel Barral, Andy Wardley.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#============================================================================
+
+package Template::Plugin::Date;
+
+use strict;
+use vars qw( @ISA $VERSION $FORMAT );
+use base qw( Template::Plugin );
+use Template::Plugin;
+
+use POSIX ();
+
+$VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);
+$FORMAT = '%H:%M:%S %d-%b-%Y'; # default strftime() format
+
+
+#------------------------------------------------------------------------
+# new(\%options)
+#------------------------------------------------------------------------
+
+sub new {
+ my ($class, $context, $params) = @_;
+ bless {
+ $params ? %$params : ()
+ }, $class;
+}
+
+
+#------------------------------------------------------------------------
+# now()
+#
+# Call time() to return the current system time in seconds since the epoch.
+#------------------------------------------------------------------------
+
+sub now {
+ return time();
+}
+
+
+#------------------------------------------------------------------------
+# format()
+# format($time)
+# format($time, $format)
+# format($time, $format, $locale)
+# format(\%named_params);
+#
+# Returns a formatted time/date string for the specified time, $time,
+# (or the current system time if unspecified) using the $format and
+# $locale values specified as arguments or internal values set defined
+# at construction time). Any or all of the arguments may be specified
+# as named parameters which get passed as a hash array reference as
+# the final argument.
+# ------------------------------------------------------------------------
+
+sub format {
+ my $self = shift;
+ my $params = ref($_[$#_]) eq 'HASH' ? pop(@_) : { };
+ my $time = shift(@_) || $params->{ time } || $self->{ time }
+ || $self->now();
+ my $format = @_ ? shift(@_)
+ : ($params->{ format } || $self->{ format } || $FORMAT);
+ my $locale = @_ ? shift(@_)
+ : ($params->{ locale } || $self->{ locale });
+ my (@date, $datestr);
+
+ unless ($time =~ /^\d+$/) {
+ # if $time is numeric, then we assume it's seconds since the epoch
+ # otherwise, we try to parse it as a 'H:M:S D:M:Y' string
+ @date = (split(/(?:\/| |:|-)/, $time))[2,1,0,3..5];
+ return (undef, Template::Exception->new('date',
+ "bad time/date string: expects 'h:m:s d:m:y' got: '$time'"))
+ unless @date >= 6 && defined $date[5];
+ $date[4] -= 1; # correct month number 1-12 to range 0-11
+ $date[5] -= 1900; # convert absolute year to years since 1900
+ $time = &POSIX::mktime(@date);
+ }
+
+ # $time is now in seconds since epoch
+ @date = (localtime($time))[0..6];
+
+ if ($locale) {
+ # format the date in a specific locale, saving and subsequently
+ # restoring the current locale.
+ my $old_locale = &POSIX::setlocale(&POSIX::LC_ALL);
+ &POSIX::setlocale(&POSIX::LC_ALL, $locale);
+ $datestr = &POSIX::strftime($format, @date);
+ &POSIX::setlocale(&POSIX::LC_ALL, $old_locale);
+ }
+ else {
+ $datestr = &POSIX::strftime($format, @date);
+ }
+
+ return $datestr;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Template::Plugin::Date - generate formatted date strings
+
+=head1 SYNOPSIS
+
+ [% USE date %]
+
+ # use current time and default format
+ [% date.format %]
+
+ # specify time as seconds since epoch or 'h:m:s d-m-y' string
+ [% date.format(960973980) %]
+ [% date.format('4:20:36 21/12/2000') %]
+
+ # specify format
+ [% date.format(mytime, '%H:%M:%S') %]
+
+ # specify locale
+ [% date.format(date.now, '%a %d %b %y', 'en_GB') %]
+
+ # named parameters
+ [% date.format(mytime, format = '%H:%M:%S') %]
+ [% date.format(locale = 'en_GB') %]
+ [% date.format(time = date.now,
+ format = '%H:%M:%S',
+ locale = 'en_GB) %]
+
+ # specify default format to plugin
+ [% USE date(format = '%H:%M:%S', locale = 'de_DE') %]
+
+ [% date.format %]
+ ...
+
+=head1 DESCRIPTION
+
+The Date plugin provides an easy way to generate formatted time and date
+strings by delegating to the POSIX strftime() routine.
+
+The plugin can be loaded via the familiar USE directive.
+
+ [% USE date %]
+
+This creates a plugin object with the default name of 'date'. An alternate
+name can be specified as such:
+
+ [% USE myname = date %]
+
+The plugin provides the format() method which accepts a time value, a
+format string and a locale name. All of these parameters are optional
+with the current system time, default format ('%H:%M:%S %d-%b-%Y') and
+current locale being used respectively, if undefined. Default values
+for the time, format and/or locale may be specified as named parameters
+in the USE directive.
+
+ [% USE date(format = '%a %d-%b-%Y', locale = 'fr_FR') %]
+
+When called without any parameters, the format() method returns a string
+representing the current system time, formatted by strftime() according
+to the default format and for the default locale (which may not be the
+current one, if locale is set in the USE directive).
+
+ [% date.format %]
+
+The plugin allows a time/date to be specified as seconds since the epoch,
+as is returned by time().
+
+ File last modified: [% date.format(filemod_time) %]
+
+The time/date can also be specified as a string of the form 'h:m:s d/m/y'.
+Any of the characters : / - or space may be used to delimit fields.
+
+ [% USE day = date(format => '%A', locale => 'en_GB') %]
+ [% day.format('4:20:00 9-13-2000') %]
+
+Output:
+
+ Tuesday
+
+A format string can also be passed to the format() method, and a locale
+specification may follow that.
+
+ [% date.format(filemod, '%d-%b-%Y') %]
+ [% date.format(filemod, '%d-%b-%Y', 'en_GB') %]
+
+Any or all of these parameters may be named. Positional parameters
+should always be in the order ($time, $format, $locale).
+
+ [% date.format(format => '%H:%M:%S') %]
+ [% date.format(time => filemod, format => '%H:%M:%S') %]
+ [% date.format(mytime, format => '%H:%M:%S') %]
+ [% date.format(mytime, format => '%H:%M:%S', locale => 'fr_FR') %]
+ ...etc...
+
+The now() method returns the current system time in seconds since the
+epoch.
+
+ [% date.format(date.now, '%A') %]
+
+=head1 AUTHORS
+
+Thierry-Michel Barral E<lt>kktos@electron-libre.comE<gt> wrote the original
+plugin and Andy Wardley E<lt>abw@cre.canon.co.ukE<gt> provided some minor
+fixups/enhancements, a test script and documentation).
+
+=head1 REVISION
+
+$Revision$
+
+=head1 COPYRIGHT
+
+Copyright (C) 2000 Thierry-Michel Barral, Andy Wardley.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>, L<POSIX|POSIX>
+
+=cut
+
View
1 lib/Template/Plugins.pm
@@ -35,6 +35,7 @@ $VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);
$STD_PLUGINS = {
'cgi' => 'CGI',
+ 'date' => 'Date',
'dbi' => 'DBI',
'url' => 'URL',
'format' => 'Format',
View
139 lib/Template/Service.pm
@@ -5,7 +5,7 @@
# DESCRIPTION
# Module implementing a template processing service which wraps a
# template within PRE_PROCESS and POST_PROCESS templates and offers
-# error recovery.
+# ERROR recovery.
#
# AUTHOR
# Andy Wardley <abw@kfs.org>
@@ -47,10 +47,9 @@ $DEBUG = 0;
# Process a template within a service framework. A service may encompass
# PRE_PROCESS and POST_PROCESS templates and an ERROR hash which names
# templates to be substituted for the main template document in case of
-# Each service invocation begins by resetting the state of the context
-# object via a call to reset(), passing any BLOCKS definitions to pre-
-# define blocks for the templates. The AUTO_RESET option may be set to
-# 0 (default: 1) to bypass this step.
+# error. Each service invocation begins by resetting the state of the
+# context object via a call to reset(). The AUTO_RESET option may be set
+# to 0 (default: 1) to bypass this step.
#------------------------------------------------------------------------
sub process {
@@ -58,8 +57,7 @@ sub process {
my $context = $self->{ CONTEXT };
my ($name, $output, $procout, $error);
- # clear any BLOCK definitions back to the known default if
- $context->reset_blocks($self->{ BLOCKS })
+ $context->reset()
if $self->{ AUTO_RESET };
# pre-request compiled template from context so that we can alias it
@@ -68,7 +66,7 @@ sub process {
|| return $self->error($context->error);
# localise the variable stash with any parameters passed
- # set the 'template' variable in the stash
+ # and set the 'template' variable
$params ||= { };
$params->{ template } = $template
unless ref $template eq 'CODE';
@@ -94,7 +92,7 @@ sub process {
};
if ($error = $@) {
last SERVICE
- unless defined ($procout = $self->recover(\$error));
+ unless defined ($procout = $self->_recover(\$error));
}
$output .= $procout;
@@ -119,7 +117,47 @@ sub process {
#------------------------------------------------------------------------
-# recover(\$exception)
+# context()
+#
+# Returns the internal CONTEXT reference.
+#------------------------------------------------------------------------
+
+sub context {
+ return $_[0]->{ CONTEXT };
+}
+
+
+#========================================================================
+# -- PRIVATE METHODS --
+#========================================================================
+
+sub _init {
+ my ($self, $config) = @_;
+ my ($item, $data, $context, $block, $blocks);
+
+ # coerce PRE_PROCESS and POST_PROCESS to arrays if necessary,
+ # by splitting on non-word characters
+ foreach $item (qw( PRE_PROCESS POST_PROCESS )) {
+ $data = $config->{ $item };
+ $data = [ split(/\W+/, $data || '') ]
+ unless ref $data eq 'ARRAY';
+ $self->{ $item } = $data;
+ }
+
+ $self->{ ERROR } = $config->{ ERROR };
+ $self->{ AUTO_RESET } = defined $config->{ AUTO_RESET }
+ ? $config->{ AUTO_RESET } : 1;
+
+ $context = $self->{ CONTEXT } = $config->{ CONTEXT }
+ || Template::Config->context($config)
+ || return $self->error(Template::Config->error);
+
+ return $self;
+}
+
+
+#------------------------------------------------------------------------
+# _recover(\$exception)
#
# Examines the internal ERROR hash array to find a handler suitable
# for the exception object passed by reference. Selecting the handler
@@ -129,7 +167,7 @@ sub process {
# template which should be processed.
#------------------------------------------------------------------------
-sub recover {
+sub _recover {
my ($self, $error) = @_;
my $context = $self->{ CONTEXT };
my ($hkey, $handler, $output);
@@ -181,66 +219,35 @@ sub recover {
}
+
#------------------------------------------------------------------------
-# context()
-#
-# Returns the internal CONTEXT reference.
+# _dump()
+#
+# Debug method which return a string representing the internal object
+# state.
#------------------------------------------------------------------------
-sub context {
- return $_[0]->{ CONTEXT };
-}
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-sub _init {
- my ($self, $config) = @_;
- my ($item, $data, $context, $block, $blocks);
-
- # coerce PRE_PROCESS and POST_PROCESS to arrays if necessary,
- # by splitting on non-word characters
- foreach $item (qw( PRE_PROCESS POST_PROCESS )) {
- $data = $config->{ $item };
- $data = [ split(/\W+/, $data || '') ]
- unless ref $data eq 'ARRAY';
- $self->{ $item } = $data;
- }
-
- $self->{ ERROR } = $config->{ ERROR };
- $self->{ AUTO_RESET } = defined $config->{ AUTO_RESET }
- ? $config->{ AUTO_RESET } : 1;
-
- $context = $self->{ CONTEXT } = $config->{ CONTEXT }
- || Template::Config->context($config)
- || return $self->error(Template::Config->error);
-
- # compile any template BLOCKS specified as text
- $blocks = $config->{ BLOCKS } || { };
- $self->{ BLOCKS } = {
- map {
- $block = $blocks->{ $_ };
- $block = $context->template(\$block)
- || return $self->error("BLOCK $_: ", $context->error())
- unless ref $block;
- ($_ => $block);
- }
- keys %$blocks
- };
-
- # call context reset_blocks() to install defined BLOCKS
- $context->reset_blocks($self->{ BLOCKS })
- if %$blocks;
-
- return $self;
-}
-
-
sub _dump {
my $self = shift;
- print("$self\n", (map { " $_ => $self->{ $_ }\n" } keys %$self), "\n");
+ my $context = $self->{ CONTEXT }->_dump();
+ $context =~ s/\n/\n /gm;
+
+ my $error = $self->{ ERROR };
+ $error = join('',
+ "{\n",
+ (map { " $_ => $error->{ $_ }\n" }
+ keys %$error),
+ "}\n")
+ if ref $error;
+
+ local $" = ', ';
+ return <<EOF;
+$self
+PRE_PROCESS => [ @{ $self->{ PRE_PROCESS } } ]
+POST_PROCESS => [ @{ $self->{ POST_PROCESS } } ]
+ERROR => $error
+CONTEXT => $context
+EOF
}
View
19 lib/Template/Test.pm
@@ -231,6 +231,25 @@ sub test_expect {
# processed OK
ok(1);
+ # another hack: if the '-- expect --' section starts with
+ # '-- process --' then we process the expected output
+ # before comparing it with the generated output. This is
+ # slightly twisted but it makes it possible to run tests
+ # where the expected output isn't static. See t/date.t for
+ # an example.
+
+ if ($expect =~ s/^\s*--+\s*process\s*--+\s*\n//im) {
+ my $out;
+ $tproc->process(\$expect, $params, \$out) || do {
+ warn("Template process failed (expect): ",
+ $tproc->error(), "\n");
+ # report failure and automatically fail the expect match
+ ok(0);
+ next;
+ };
+ $expect = $out;
+ };
+
# strip any trailing blank lines from expected and real output
foreach ($expect, $output) {
s/\n*\Z//mg;
View
1 parser/Grammar.pm.skel
@@ -68,6 +68,7 @@ $LEXTABLE = {
'&&' => 'AND',
'||' => 'OR',
'!' => 'NOT',
+ '|' => 'FILTER',
'.' => 'DOT',
'..' => 'TO',
# ':' => 'MACRO',
View
2 t/README
@@ -11,6 +11,7 @@ compile3.t Ensure that touching source template causes re-compilation
config.t Template::Config factory module
context.t Template::Context module
datafile.t Datafile plugin (Template::Plugin::Datafile)
+directive.t Directive layout, chomping, comments, etc.
document.t Template::Document module
evalperl.t Evaluation of PERL and RAWPERL blocks
exception.t Template::Exception module
@@ -39,7 +40,6 @@ switch.t SWITCH / CASE directives
plugins.t Template::Plugins provider module
template.t Template module
try.t TRY / THROW / CATCH / FINAL directives
-chomp.t (merge chomp.t, prechomp.t and postchomp.t)
code.t binding code to variables (or covered in vars.t?)
dom.t copy from v1
rss.t copy from v1
View
186 t/date.t
@@ -0,0 +1,186 @@
+#============================================================= -*-perl-*-
+#
+# t/date.t
+#
+# Tests the 'Date' plugin.
+#
+# NOTE: this relies on a hacked version of Template::Test.pm that supports
+# the '-- process --' flag in an '-- expect --' block. We need this
+# because we can't hard-code expected output in advance when we're
+# dealing with generating date string based on the current time at
+# execution.
+#
+# Written by Andy Wardley <abw@cre.canon.co.uk>
+#
+# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+#
+# $Id$
+#
+#========================================================================
+
+use strict;
+use lib qw( ./lib ../lib );
+use Template;
+use Template::Test;
+use Template::Plugin::Date;
+use POSIX;
+$^W = 1;
+
+$Template::Test::DEBUG = 0;
+
+my $format = {
+ 'default' => $Template::Plugin::Date::FORMAT,
+ 'time' => '%H:%M:%S',
+ 'date' => '%d-%b-%Y',
+ 'timeday' => 'the time is %H:%M:%S on %A',
+};
+
+my $time = time;
+my @ltime = localtime($time);
+
+my $params = {
+ time => $time,
+ format => $format,
+ timestr => &POSIX::strftime($format->{ time }, @ltime),
+ datestr => &POSIX::strftime($format->{ date }, @ltime),
+ daystr => &POSIX::strftime($format->{ timeday }, @ltime),
+ defstr => &POSIX::strftime($format->{ default }, @ltime),
+ now => sub {
+ &POSIX::strftime(shift || $format->{ default }, localtime(time));
+ },
+ nowloc => sub { my ($time, $format, $locale) = @_;
+ my $old_locale = &POSIX::setlocale(&POSIX::LC_ALL);
+ &POSIX::setlocale(&POSIX::LC_ALL, $locale);
+ my $datestr = &POSIX::strftime($format, localtime($time));
+ &POSIX::setlocale(&POSIX::LC_ALL, $old_locale);
+ return $datestr;
+ },
+};
+
+test_expect(\*DATA, { POST_CHOMP => 1 }, $params);
+
+
+#------------------------------------------------------------------------
+# test input
+#
+# NOTE: these tests check that the Date plugin is behaving as expected
+# but don't attempt to validate that the output returned from strftime()
+# is semantically correct. It's a closed loop (aka "vicious circle" :-)
+# in which we compare what date.format() returns to what we get by
+# calling strftime() directly. Despite this, we can rest assured that
+# the plugin is correctly parsing the various parameters and passing
+# them to strftime() as expected.
+#------------------------------------------------------------------------
+
+__DATA__
+-- test --
+[% USE date %]
+Let's hope the year doesn't roll over in between calls to date.format()
+and now()...
+Year: [% date.format(format => '%Y') %]
+
+-- expect --
+-- process --
+Let's hope the year doesn't roll over in between calls to date.format()
+and now()...
+Year: [% now('%Y') %]
+
+-- test --
+[% USE date(time => time) %]
+default: [% date.format %]
+
+-- expect --
+-- process --
+default: [% defstr %]
+
+-- test --
+[% USE date(time => time) %]
+[% date.format(format => format.timeday) %]
+
+-- expect --
+-- process --
+[% daystr %]
+
+-- test --
+[% USE date(time => time, format = format.date) %]
+Date: [% date.format %]
+
+-- expect --
+-- process --
+Date: [% datestr %]
+
+-- test --
+[% USE date(format = format.date) %]
+Time: [% date.format(time, format.time) %]
+
+-- expect --
+-- process --
+Time: [% timestr %]
+
+-- test --
+[% USE date(format = format.date) %]
+Time: [% date.format(time, format = format.time) %]
+
+-- expect --
+-- process --
+Time: [% timestr %]
+
+
+-- test --
+[% USE date(format = format.date) %]
+Time: [% date.format(time = time, format = format.time) %]
+
+-- expect --
+-- process --
+Time: [% timestr %]
+
+-- test --
+[% USE english = date(format => '%A', locale => 'en_GB') %]
+[% USE french = date(format => '%A', locale => 'fr_FR') %]
+In English, today's day is: [% english.format +%]
+In French, today's day is: [% french.format +%]
+
+-- expect --
+-- process --
+In English, today's day is: [% nowloc(time, '%A', 'en_GB') +%]
+In French, today's day is: [% nowloc(time, '%A', 'fr_FR') +%]
+
+-- test --
+[% USE english = date(format => '%A') %]
+[% USE french = date() %]
+In English, today's day is:
+[%- english.format(locale => 'en_GB') +%]
+In French, today's day is:
+[%- french.format(format => '%A', locale => 'fr_FR') +%]
+
+-- expect --
+-- process --
+In English, today's day is: [% nowloc(time, '%A', 'en_GB') +%]
+In French, today's day is: [% nowloc(time, '%A', 'fr_FR') +%]
+
+-- test --
+[% USE date %]
+[% date.format('4:20:00 6-13-2000', '%H') %]
+
+-- expect --
+04
+
+-- test --
+[% USE day = date(format => '%A', locale => 'en_GB') %]
+[% day.format('4:20:00 9-13-2000') %]
+
+-- expect --
+Tuesday
+
+-- test --
+[% TRY %]
+[% USE date %]
+[% date.format('some stupid date') %]
+[% CATCH date %]
+Bad date: [% e.info %]
+[% END %]
+-- expect --
+Bad date: bad time/date string: expects 'h:m:s d:m:y' got: 'some stupid date'
View
262 t/directive.t
@@ -0,0 +1,262 @@
+#============================================================= -*-perl-*-
+#
+# t/directive.t
+#
+# Test basic directive layout and processing options.
+#
+# Written by Andy Wardley <abw@kfs.org>
+#
+# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
+# Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+#
+# $Id$
+#
+#========================================================================
+
+use strict;
+use lib qw( ./lib ../lib );
+use Template::Test;
+$^W = 1;
+
+my $tt1 = Template->new();
+my $tt2 = Template->new( PRE_CHOMP => 1 );
+my $tt3 = Template->new( POST_CHOMP => 1 );
+
+test_expect(\*DATA, [ tt => $tt1, pre => $tt2, post => $tt3 ], callsign);
+
+__DATA__
+#------------------------------------------------------------------------
+# comments
+#------------------------------------------------------------------------
+-- test --
+[%# this is a comment which should
+ be ignored in totality
+%]hello world
+-- expect --
+hello world
+
+-- test --
+[% # this is a one-line comment
+ a
+%]
+-- expect --
+alpha
+
+-- test --
+[% # this is a two-line comment
+ a =
+ # here's the next line
+ b
+-%]
+[% a %]
+-- expect --
+bravo
+
+-- test --
+[% a = c # this is a comment on the end of the line
+ b = d # so is this
+-%]
+a: [% a %]
+b: [% b %]
+-- expect --
+a: charlie
+b: delta
+
+#------------------------------------------------------------------------
+# manual chomping
+#------------------------------------------------------------------------
+
+-- test --
+[% a %]
+[% b %]
+-- expect --
+alpha
+bravo
+
+-- test --
+[% a -%]
+[% b %]
+-- expect --
+alphabravo
+
+-- test --
+[% a -%]
+ [% b %]
+-- expect --
+alpha bravo
+
+-- test --
+[% a %]
+[%- b %]
+-- expect --
+alphabravo
+
+-- test --
+[% a %]
+ [%- b %]
+-- expect --
+alphabravo
+
+-- test --
+start
+[% a %]
+[% b %]
+end
+-- expect --
+start
+alpha
+bravo
+end
+
+-- test --
+start
+[%- a %]
+[% b -%]
+end
+-- expect --
+startalpha
+bravoend
+
+-- test --
+start
+[%- a -%]
+[% b -%]
+end
+-- expect --
+startalphabravoend
+
+-- test --
+start
+[%- a %]
+[%- b -%]
+end
+-- expect --
+startalphabravoend
+
+#------------------------------------------------------------------------
+# PRE_CHOMP enabled
+#------------------------------------------------------------------------
+
+-- test --
+-- use pre --
+start
+[% a %]
+mid
+[% b %]
+end
+-- expect --
+startalpha
+midbravo
+end
+
+-- test --
+start
+ [% a %]
+mid
+ [% b %]
+end
+-- expect --
+startalpha
+midbravo
+end
+
+-- test --
+start
+[%+ a %]
+mid
+[% b %]
+end
+-- expect --
+start
+alpha
+midbravo
+end
+
+-- test --
+start
+ [%+ a %]
+mid
+[% b %]
+end
+-- expect --
+start
+ alpha
+midbravo
+end
+
+-- test --
+start
+ [%- a %]
+mid
+ [%- b %]
+end
+-- expect --
+startalpha
+midbravo
+end
+
+#------------------------------------------------------------------------
+# POST_CHOMP enabled
+#------------------------------------------------------------------------
+
+-- test --
+-- use post --
+start
+[% a %]
+mid
+[% b %]
+end
+-- expect --
+start
+alphamid
+bravoend
+
+-- test --
+start
+ [% a %]
+mid
+ [% b %]
+end
+-- expect --
+start
+ alphamid
+ bravoend
+
+-- test --
+start
+[% a +%]
+mid
+[% b %]
+end
+-- expect --
+start
+alpha
+mid
+bravoend
+
+-- test --
+start
+[% a +%]
+[% b +%]
+end
+-- expect --
+start
+alpha
+bravo
+end
+
+-- test --
+start
+[% a -%]
+mid
+[% b -%]
+end
+-- expect --
+start
+alphamid
+bravoend
+
+
View
21 t/document.t
@@ -78,7 +78,6 @@ __END__
version [% template.version %] by [% template.author %]
-- expect --
version 1.23 by Tom Smith
--- stop --
# test local block definitions are accessible
-- test --
@@ -97,3 +96,23 @@ version 1.23 by Tom Smith
This is block bar
This is the end of block foo
+-- test --
+[% META title = 'My Template Title' -%]
+[% BLOCK header -%]
+title: [% template.title or title %]
+[% END -%]
+[% INCLUDE header %]
+-- expect --
+title: My Template Title
+
+-- test --
+[% META title = 'My Template Title' -%]
+[% BLOCK header -%]
+title: [% title or template.title %]
+[% END -%]
+[% INCLUDE header title = 'A New Title' %]
+[% INCLUDE header %]
+-- expect --
+title: A New Title
+
+title: My Template Title
View
35 t/filter.t
@@ -311,4 +311,39 @@ The_cat_sat_on_the_mat
The cat shat on the mat
The cplat splat on the mplat
+-- test --
+[% text = 'The <=> operator' %]
+[% text|html %]
+-- expect --
+The &lt;=&gt; operator
+
+-- test --
+[% text = 'The <=> operator, blah, blah' %]
+[% text | html | replace('blah', 'rhubarb') %]
+-- expect --
+The &lt;=&gt; operator, rhubarb, rhubarb
+
+-- test --
+[% | truncate(25) %]
+The cat sat on the mat, and wondered to itself,
+"How might I be able to climb up onto the shelf?",
+For up there I am sure I'll see,
+A tasty fishy snack for me.
+[% END %]
+-- expect --
+The cat sat on the mat...
+
+-- test --
+[% FILTER upper %]
+The cat sat on the mat
+[% END %]
+-- expect --
+THE CAT SAT ON THE MAT
+
+-- test --
+[% FILTER lower %]
+The cat sat on the mat
+[% END %]
+-- expect --
+the cat sat on the mat
View
2 t/include.t
@@ -55,7 +55,7 @@ my $tproc = Template->new({
INTERPOLATE => 1,
INCLUDE_PATH => "$dir/src:$dir/lib",
TRIM => 1,
- AUTO_RESET => 0,
+ RESET_BLOCKS => 0,
});
my $tt_reset = Template->new({
View
2 t/service.t
@@ -129,7 +129,7 @@ header:
error: [file] [block1: not found]
footer
-# now try it again with AUTO_RESET turned off...
+# now try it again with RESET_BLOCKS turned off...
-- test --
-- use tt2 --
[% PROCESS blockdef -%]

0 comments on commit 850d474

Please sign in to comment.
Something went wrong with that request. Please try again.