The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#========================================================================
#
# Changes 
#
# DESCRIPTION
#   Revision history for Template Toolkit.
#
# AUTHOR
#   Andy Wardley   <abw@cre.canon.co.uk>
#
#------------------------------------------------------------------------
# $Id: Changes,v 1.111 2000/03/28 15:53:21 abw Exp $
#========================================================================

#------------------------------------------------------------------------
# Version 1.06  2000/03/28 15:52:48
#------------------------------------------------------------------------

* Interim release to fix a bug in Datafile plugin which became noticable
  with Perl 5.6.  Thanks to Nathan Torkington for spotting it.

#------------------------------------------------------------------------
# Version 1.05  2000/03/20 16:31:05
#------------------------------------------------------------------------

* Added the CALL directive, identical to GET in every way except
  that it doesn't print the value returned by evaluating the variable.
  This allows you to call sub-routines or methods and effectively
  ignore the return value.  Errors and exceptions returned are still
  raised automatically.

* Added the 'html_para', 'html_break', 'truncate' and 'repeat' filters 
  kindly provided by Leslie Michael Orchard, or minor adaptations 
  thereof.  Also added 'replace' and 'remove' filters as suggested by 
  Neil Bowers.  Updated documentation and test suite accordingly.

* Added the 'URL' plugin for constructing a URL from a base part and
  variable set of parameters. Based on a suggestion by Andrew Brindeew
  <abr@df.ru>.  Added t/url.t and updated docs.

* Added the 'Table' plugin which allows you to slice up a data set 
  into rows and columns.  Specify either a fixed number of 'rows' or 
  'cols' with an optional 'overlap' and then call the col() or row()
  method to request a specific row or cols() or rows() to return all
  cols/rows as list references.  See t/table.t for examples and 
  documentation in Template::Plugin::Table.

* Added get_all() method to Template::Iterator to return all remaining
  data.  This allows it to be passed to the Table plugin (and others)
  which can then easily extract all remaining data from it.  Here's a
  short example showing how you might integrate the results of a DBI
  query (iterator) into a table:

    [% USE DBI(dsn,user,pass) -%]
    [% USE table( DBI.query('SELECT * FROM alphabet ORDER BY letter'),
                            rows=8 overlap=1 pad=0) -%]
    [% FOREACH row = table.cols -%]
    [% row.first.letter %] - [% row.last.letter +%]:
       [% FOREACH item = row %][% item.name %] [% END %]
    [% END %]

  Producing output something like this:

    a - h:
      alpha bravo charlie delta echo foxtrot golf hotel 
    h - o:
      hotel india juliet kilo lima mike november oscar 
    o - v:
      oscar papa quebec romeo sierra tango umbrella victor 
    v - z:
      victor whisky x-ray yankee zulu 

* Added the facility to specify iterator options directly in FOREACH
  directives.  These are simply added after the list name or list
  construction.  e.g.

    [% FOREACH name = list order = 'sorted' %]
    [% FOREACH name = [ 'tom' 'dick' 'harry' ] order = 'sorted' %]

  It was previously possible to specify parenthesised iterator options
  when creating anonymous lists (e.g. "[ ... ](order=>'sorted')" ).
  This is still supported for backwards compatibility but is no longer
  documented.  The new syntax is now preferred.  Added new parameter
  'field' which names a key within the data items (presumably hashes)
  which should be used as the sort key.  See examples in t/

    [% FOREACH p = people order='sorted' field='surname' %]  

* Removed a rogue debug statement printed when calling a code based 
  CATCH handler.

* Applied a patch sent by Swen Thuemmler to fix a problem in the Template
  DESTROY method reporting 'Can't call method "old" on an undefined value...'
  when a $SIG{__DIE__} handler is defined.

#------------------------------------------------------------------------
# Version 1.04  2000/03/01 14:22:01
#------------------------------------------------------------------------

* Added the XML::DOM and XML::RSS plugin modules to the distribution.

* Changed the handling of file errors generated when redirecting
  output and/or error, as suggested by Jonas Lilligren.  Errors are
  now raised as 'file' exceptions and are reported back to the caller
  as per usual.  That is, the process() method returns 0 and the error
  can be retrieved by the usual error() method.  e.g.
 
  $template->process($infile, \%params, $path_to_output_file)
	|| die $template->error(), "\n";

  If a global OUTPUT or ERROR redirect is established by means of the
  Template constructor parameters then any error will be stored and
  also accessible via the error() method.  e.g.
  
  my $template = Template->new({ OUTPUT => $path_to_some_file });

  # check for any OUTPUT errors
  die $error
	if $error = $template->error();

* Changed the way in which multiple values returned from user code or
  object methods are handled.  Previously, multiple values were
  treated as being ($value, $error) and the code was required to
  return a list reference in $value if it wanted to return more than
  one item.  This behaviour is still supported if the first value
  returned (i.e. $value) is undefined.  Thus, existing code can
  continue to return (undef, $error) and expect the right result.  If
  the first item returned has any defined value then all the return
  values are folded into, and returned as a list reference.
  e.g. return ('foo', 'bar', 'baz') => [ 'foo', 'bar', 'baz ].  Single
  values are returned by themselves as per usual.  Removed the
  work-around delegating AUTOLOAD code from Template::Plugin which is
  no longer needed, updated documentation and added t/cgi.t to test
  this behaviour with the CGI plugin.  Thanks to Leslie Michael
  Orchard for raising the issue and sending various patches and ideas.

* Fixed a bug concerning iterators in nested FOREACH loops, identified
  by Thiery-Michel Barral <kktos@electron-libre.com>.  The iterator
  (i.e. the 'loop' variable) in the outer loop was getting trashed by
  an inner FOREACH loop.  Nested FOREACH loops now work as expected.

* Split the Template::Cache new() constructor into new() and _init()
  methods to facilitate easier subclassing, thanks to another patch
  from Leslie.  Also fixed a minor bug which was preventing switching
  of the PARSER object.

* Added '--start--' and '--stop--' markers to Template::Test to allow
  sub-sections of tests to be run in isolation.  Updated 'BUGS' section
  of documentation to show new Template::Test module.

* Added USER_DIR and USER_BLOCK options which allow user-defined
  directives and block directives to be defined.  This is still
  experimental and subject to change.  Not yet documented for that
  reason, but see t/userdef.t if you're interested.

* Added an acknowledgements section to the Template documentation and 
  further information on other projects and related modules.  Also 
  added internal/external plugin information.


#------------------------------------------------------------------------
# Version 1.03  2000/02/01 12:35:13
#------------------------------------------------------------------------

* Added support for running under Perl 5.004 (previously required 5.005)

* Added a general purpose 'join' function which can be applied to list 
  references.  A joining string can be passed, or ' ' is used by default.
  Added test to t/list.t.  e.g. 

     [% mylist.join %]   [% mylist.join(', ') %]

* Improved the plugin interface by enhancing the Template::Plugin base
  class to act as a general delegate to other Perl modules.  The base
  class constructor can be passed an object reference to which it
  should delegate all methods.  Alternatively, pass the name of a Perl
  module as the first parameter and it will attempt to 'require' the
  module and create an object instance via it's new() constructor
  method.  Any additional parameters are passed to new().  A plugin
  object is returned which wraps the target object, providing
  delegation to its methods via an AUTOLOAD function.  This function
  checks the values returned by the delegate method and concatenates
  them if more than one is returned.  Methods may have a '_as_list'
  suffix added to them which will cause the autoloader to return them
  as a list reference.  Documented Template::Plugin, updated docs to
  note changes and included some better examples for plugins in
  general.

* Changed Context use_plugin() method to look for LOAD_PERL option and
  use the above Template::Plugin behaviour if set.  Changed CGI plugin
  to also use the new delegating base class.

* Modified handling of object references in Template::Context::_evaluate.
  When a template variable is bound to a blessed object reference, any 
  attempt to reference a member of that object (e.g. myobj.whatever) 
  translates to a method call (e.g. myobj->whatever).  If that fails 
  and the object is a blessed hash reference then the method will now 
  attempt to resolve it as a hash member (e.g. myobj->{ whatever }).
  Added test to t/object.t

* Changed Template::Plugin::Format to pass all parameters to sprintf
  rather than just the first.  Added test to t/format.t

* Added a tutorial document as Template::Tutorial.  Many other minor
  documentation updates.

* Improved the comments in the sample .ttreerc file generated 
  automatically by ttree when first run.  Added 'eval_perl' and 'load_perl'
  template options.


#------------------------------------------------------------------------
# Version 1.02  1999/12/21 14:22:04
#------------------------------------------------------------------------

* Added code to enable [% PERL %] ... [% END %] sections.  This is
  controlled by the EVAL_PERL option and is disabled by default.  When
  enabled, the Perl code contained in the block is evaluated in the
  Template::Perl package and any runtime errors are thrown as 'perl'
  exceptions.  A 'perl' exception is thrown automatically if the EVAL_PERL
  option is disabled and a PERL block is encountered.  The 'context' and 
  'stash' variables are pre-defined in the package.  e.g.

    [% PERL %]
       $stash->{'some_data'} = [ qw( foo bar baz ) ];
       $context->output('loaded data');
    [% END %]
    
    [% "$item\n" FOREACH item = some_data %]

  The PERL section is a fully-fledged block allowing it to contain other
  template directives.  These are processed first and the resulting output
  of the entire PERL block is then evaluated as Perl code.

* Changed main Template module to watch for and report errors during 
  any pre-process and post-process templates.  For some reason I thought
  it was a Good Thing to be tolerant of errors during these phases but
  I now know that it's not (i.e. when your plugins fail to load from a 
  pre-process file and you don't get any warning).  

* Modified tokeniser regex to accept a leading '-' on literal numbers.
  This is the quick fix to allow things like the following.  I'll add
  a proper unary minus to the parser RSN.

    [% FOREACH timezone = [-12..12] %]

* Added some proper documentation to the Template::Test module.  Fixed
  a minor bug in the test splitter to ignore the first '-- test --' line
  if provided.


#------------------------------------------------------------------------
# Version 1.01  1999/12/16 09:31:19
#------------------------------------------------------------------------

* Added the pseudo-reference operator '\' as an experimental feature
  to allow things like code references to be passed around without
  being pre-evaluated.  The 'reference' created is actually a closure
  which can be called from Perl code to evaluate the referred value
  (i.e. lazy evaluation).  Additional parameters may also be passed
  when calling the closure.  These are added to any parameters
  supplied when the reference was created.  A reference will be
  automatically evaluated (i.e. called) each time it is used in a
  template.  Not yet documented - see tests in t/code.t for further
  info.  e.g.

  [% sql_query(sql, \my_filter('foo')) %]

  sub sql_query {
	my ($sql, $filter) = @_;
	my $data = _do_sql_query($sql);
	&$filter($data);    #  => my_filter('foo', $data);
  }

* Modified parser to accept parameter list after an evaluated term.  e.g.
  ${foo}(bar).  Thanks to Paul Sharpe for spotting the omission.

#------------------------------------------------------------------------
# Version 1.00  1999/12/02 16:14:10
#------------------------------------------------------------------------

* Removed debugging code and bumped version number for release.

#------------------------------------------------------------------------
# Version 0.29  1999/11/26 09:11:57
#------------------------------------------------------------------------

* This is the final release candidate.  Barring any show-stoppers, this
  will be released as version 1.00.

* Added MACRO directive.  A MACRO defines some other directive which 
  can be repeatedly executed each time the macro is evaluated.  Macros
  can be passed parameters when called which may be named or mapped to 
  a variable name declared with the macro.

    [% MACRO foo INCLUDE bar %]
    [% foo %]  [% foo(title='Hello World') %]

    [% MACRO header(title) INCLUDE html/header %]
    [% header('Hello World') %]  
    [% header('Hello World', bgcol='#123456') %]

* Modified grammar to allow an anonymous BLOCK to be declared.  This can
  be used in conjunction with MACRO to create a template block for later
  evaluation without requiring you to explicitly define a block and 
  INCLUDE it.  e.g.

    [% MACRO letter BLOCK %]
       Dear [% name %]...
    [% END %]

    [% letter(name='Fred') %]

* Rationalised the grammar slightly to allow general use of the shortcut 
  operator (e.g. result = this or that, file = open or die, etc).  Also 
  added the basic binary math operators, -, +, *, div, and mod.  Added tests
  to t/binop.t.

* Changed the Template::Context::throw() method to be a little more
  intelligent about determining which exception handler to raise.  An
  exception type can now be expressed in dotted form (e.g. foo.bar) and
  a more general handler can be installed (e.g. foo) as a catch-all for
  any sub-typed exceptions that don't define their own handlers.  Failing
  all that, the 'default' handler is still used.  As SAM noted, (it was 
  his idea), this makes it much easier to handle general classes of errors
  for plugin modules (like DBI) without losing the granularity of what 
  different errors might represent.

* Fixed problem with PLUGIN_BASE when used via ttree.  The default
  plugin base, 'Template::Plugin', now gets added automatically to
  whatever value is supplied in the configuration.  This is done in
  the Template::Context constructor.  Note that this changes beta
  behaviour which didn't add 'Template::Plugin' if an array reference
  (rather than a scalar) was passed.  This is now more consistent.

* Fixed a bug in FOREACH identified by Simon Matthews where the incorrect
  loop variable was being freed (loop vs iter).

* Fixed a problem in loading files with ABSOLUTE_PATHS.  Thanks again to 
  Simon Matthews for finding and fixing.

* Moved t/texpect.pl into Template::Test module to make it easier to 
  load and use the test harness.  Modified test scripts accordingly.

* Relaxed the behaviour of redirect (in Template::Utils, called via 
  Template::Context) to accept any kind of object reference that 
  supports a 'print' method.  This includes all IO::Handle objects
  (as before) and also allows Apache::Request objects to be passed.

* Added better error reporting to the plugin loading process implemented
  in Template::Context::use_plugin().  

* Updated documentation.

#------------------------------------------------------------------------
# Version 0.28  1999/11/05 10:29:05
#------------------------------------------------------------------------

* OK, so I lied about 0.27 being the final beta release. :-)=
  The main reason is that the internal FILTER interface has been
  improved at the cost of (possibly) breaking existing filter code.
  This isn't as bad as it sounds because the filter code probably
  wasn't working properly anyway, due to the interface not being up to
  scratch.  Anyway, it's a change worthy of another beta release,
  IMHO, to allow the changes to be tested and any wrinkles ironed out.
  Interfaces should remain stable from now on so you can consider this
  version a release candidate.

* Changed the behaviour of the AND (&&) and OR (||) operators to act as 
  "short-circuit" operators as in Perl.  If the left hand side of an OR 
  evaluates true, then the right hand side will not be evaluated.  Likewise
  for an AND which will bypass evaluation of the RHS if the LHS evaluates
  false.  I thought this was going to be tricky to implement but Simon
  Matthews sat me down in the pub with a few pints of beer and a laptop 
  and it all came together quite well.  Inspirational hacking, indeed!
  Updated t/binop.t to test this behaviour.

* Added ABSOLUTE_PATHS option which allows template files to be specified 
  using absolute paths (e.g. '/foo/bar/baz.html').  Enabled by default.
  Thanks to all those who badgered me about this until I got a clue. :-)=
  Added t/abspath.t and updated documentation.  Changed the parser grammar
  to accept '/' as the first character of an unquoted INCLUDE file, e.g.
  [% INCLUDE /slash/bang/wallop %]

* Added 'perl5lib' option to ttree to allow additional Perl library 
  directories to be specified.  These are simply unshifted onto @INC.

* Changed Template::Context::_evaluate() test on ARRAY objects so that
  the generic size, max, etc., and numerical indexing operations work 
  on blessed arrays.

* Added register_filter($name, $factory) method to context to allow
  plugin modules (or whatever) to register filters for subsequent use.
  Moved the filters defined in Template::Plugin::Filter into a new
  module, Template::Filters, which defines all the "system" filters.
  This is loaded the first time a FILTER directive is encountered and
  registers all filters for subsequent use.

* Changed behaviour of Context use_filter() method so that it no longer
  passes the name of the filter to the factory method.

* Added new filters 'redirect' and 'into'.  The first redirects a block 
  into a separate file, as specified by a filename.  The file will be 
  written relative to the OUTPUT_PATH.  This can be used to generate 
  mucho pages from a list of records (see following example).  

    List of User:
    <ul>
      [% FOREACH user = myorg.userlist %]
         [% INCLUDE user_page FILTER redirect("users/${user.id}.html") %]
         <li><a href="users/${user.id}.html">[% user.name %]</a>
      [%
    </ul>

  The 'into' filter saves the output into a named variable.
 
    [% INCLUDE myfile FILTER into('myvar') %]

    [% FILTER into('description') %]
       Rhubarb, rhubard, blah, blah, cabbages.
    [% END %]

* Added a minor feature to add a 'filename' variable which stores the name 
  of the top-level template file.  This doesn't happen if a 'filename'
  variables is already defined or if the template was specified via a 
  reference (i.e. no filename available).

* Added new Template Plugin module 'Datafile'.

* Francois Desarmenien has released a new version of Parse::Yapp (0.32) 
  which includes the patch to specify an alternate grammar template file 
  (yapp -t <template>).  Removed parser/parse_yapp_patch and updated 
  parser/README. 

#------------------------------------------------------------------------
# Version 0.27  1999/10/01 16:51:46
#------------------------------------------------------------------------

* Fifth and most certainly, final, beta release.  The core toolkit is now 
  stable and there are only a few low-level interface issues left to 
  resolve (e.g. filters).  The 'ttree' utility is now fully functional
  and reliable.  
  
* Added numerical list indexing of the form 'list.n', e.g 'list.0', 'list.3'.
  Added t/listndx.t to test suite.  Examples of use:
    [% list = ['one' 'two' 'three' 'four' ] %]
    [% list.0 %] [% list.1 %] 
    [% list.${n} FOREACH n = [0..3] %] 

* Fixed a bug identified by Simon Matthews which was causing corruption 
  of the context runtime stack when an empty hash was created.  Added a 
  special case to detect empty hashes rather than blindly splicing n 
  (possibly 0) elements off the stack to construct a hash.  Added tests
  to t/hash.t.

* Fixed several bugs in ttree identified by Martin Portman; files of the 
  same name in different directories were treated as the same file and all
  received the same (cached) contents, target directories weren't always 
  being created, and a few other minor oddities were cleansed.  Also added
  -n option to do nothing.

* Modified grammar slightly to allow multiple FILTER directives to be 
  chained one after another, as suggested by Eugene Miretskiy e.g.
  [% INCLUDE foobar FILTER this FILTER that %]

#------------------------------------------------------------------------
# Version 0.26  1999/09/15 12:22:36
#------------------------------------------------------------------------

* Fourth (and hopefully final) public beta release.

* Finished writing bin/ttree.  It is now fully functional and (mostly)
  documented.  Added AppConfig (which ttree uses) as a Makefile.PL 
  pre-requisite

* Added '..' range operator for specification of simple loops:
  e.g. [% FOREACH i = [ 1..10 ] %]

* Changed parser grammar to call a factory function to generate directives.
  This can be specified as a package name or by reference to a prototype or
  factory object. 
  e.g. 
      my $t = Template->new({ FACTORY => 'MyOrg::Template::Directive' });
  or
      my $t = Template->new({ FACTORY => MyOrg::TDFactory->new() }); 

* Re-structured the intermediate code generated by the parser and wrote
  a new runtime evaluation loop in Context::_evaluate().  Re-wrote parts
  of the parser grammer accordingly.  This offers some new features, like
  named parameters described below; is simpler to understand, maintain and
  use; has smaller state and rule tables resulting in faster loading and 
  smaller footprint, generates less intermediate code resulting in faster 
  parsing and using slightly less memory.  The runtime FSM now uses a 
  double-ended queue.  Shifting/unshift opcodes and data to and from a list 
  is understandably slower than simply iterating through the list elements 
  as we previously did, but the added simplicitly seems to outweigh any 
  losses.  Rough benchmarks show it runs about 10% faster now.

* Added facility for named parameters.  These are automatically collated
  into a hash array which is then passed by reference as the last item
  in the parameter list.  e.g. foo(10, 20, name='fred', 30, age=30) is
  converted to foo(10, 20, 30, { name => 'fred', age => 30 }).  This applies
  to parameters passed to functions/methods like this example, USE and 
  FILTER parameters.

* Changed FOREACH to only localise the stash when it is expected to import
  hash members, i.e. no iterator variable is specified.  Thanks to Graham
  Barr for spotting the irregularity.

* Iterator methods first() and next() have been renamed get_first()
  and get_next(), respectively, and methods size(), max(), index(), 
  number(), first() and last() have been provided.  The FOREACH loop 
  defines a 'loop' variable which contains a reference to the iterator,
  allowing you to do things like the following.  Updated t/foriter.t.

  [% FOREACH thing = myapp.somelist %]
     [% INCLUDE thing_table_header IF loop.first %]
        #[% loop.number ]/[% loop.size %]: [% thing %]
     [% INCLUDE thing_table_footer IF loop.last %]
  [% END %]

* Added generic list methods size(), max() and sort() which can be appended
  to any list (or indeed, iterator) to return the number of elements, 
  maximum index (size - 1), or a sorted representation of the list.

  [% FOREACH name = myapp.list_of_names.sort %]
     [% name %]
  [% END %]

* Added generic keys() and values() methods for hash references.

* Added RECURSION option to allow recursion into template files.
  Added t/recurse.t to test it.

* Changed handling of output files to automatically create any 
  intermediate directories required for the destination.  This is
  implemented in Template::Utils::output_handler() by calling on
  File::Path's mkpath() function.

* Fixed bug where a PLUGIN_BASE specified as a string didn't get the 
  default Template::Plugin base added.  Thanks to Hans von Lengerke for
  the patch.

* Fixed a problem identified by Simon Matthews whereby files in local
  directories would not be processed if a file of the same name existed
  in an INCLUDE_PATH directory.  This isn't always what you want.  Added
  support for a './' prefix on a file (e.g. './header' instead of 'header')
  which causes the loader to look only in the current directory and not
  in the INCLUDE_PATH.  Caching is as per default CACHE option, with 
  leading './' left intact in the name.

#------------------------------------------------------------------------
# Version 0.25  1999/08/16 14:44:45
#------------------------------------------------------------------------

* Third public beta release.

* Added 'ttree' utility for process directory trees of template files,
  akin to the 'metapage' script in Text::MetaText.  Not yet documented 
  and missing a few features but very much working and useful.

* Added PRE_PROCESS and POST_PROCESS options to denote template files
  for processing before and after templates.  Changed organisation of
  Context module a little, adding explicit localise() and delocalise()
  methods. Added t/preproc.t.

* Change Template::process() method to accept optional third and fourth
  parameters, $output and $error, to denote output and/or error destinations
  for processing that template only.  The process() method calls the 
  context redirect() for output and/or error, processes the template file
  and then restores them to their previous values, effectively closing
  any files that may have been opened.  The destination may now also be
  a filename relative to OUTPUT_PATH which is constructed and passed 
  to output_handler() (see next item).  Added t/output.t.

* Modified Template::Utils:output_handler() to accept a string as a
  destination, treat it as a filename, open the file and return a glob,
  created by Symbol::gensym containing the file handle.

* Various minor documentation updates.

* Added t/accessor.t and made minor changes to t/texpectl.pl.

#------------------------------------------------------------------------
# Version 0.24  1999/08/12 22:04:26
#------------------------------------------------------------------------

* Second public beta release.

* Improved FILTERS configuration option which now allows filter 
  constructors (factories) to be defined.  These take responsibility
  for creating filter instances as they are required.

* Documented WHILE, PROCESS, IMPORT, TAGS, BREAK and FILTER
  directives.  Re-wrote the overview and summary sections, moved some
  bits around, generally improved various other parts of the docs.
  The Template.pod and README file are now constructed automatically 
  by the 'make dist' from source in doc/src, using bin/mkdoc.

* Removed operating-system dependant code which was detecting and
  storing path separators.  I realised that if everyone uses '/' as
  the path separator, then Perl will do the conversion automagically.  
  Much easier.  This also means that the OS, PATH_SEP and PATH_SPLIT 
  options are no longer required.  

* Deleted old and boring 'examples' directory.

* Deleted obsolete code from Template::Debug.pm

#------------------------------------------------------------------------
# Version 0.23  1999/08/10 12:12:07
#------------------------------------------------------------------------

* Interim (non-public) release.  This will become the next public 
  beta release once the documentation has been updated to reflect 
  the following changes.  For now, the best source of inspiration for 
  usage of new features can be found in the relevant test scripts.

* Added PROCESS directive which acts like INCLUDE but doesn't localise
  variables.  This allows configuration files, etc., to update non-local
  variables.  Added t/process.t to test suite.

* Added IMPORT directive to copy all members of a hash into the main 
  namespace.  Added t/import.t to test suite.

* Added WHILE directive to repeat a loop while an expression evaluates
  true.  The $Template::Directive::While::MAXITER variable defines an
  upper iteration limit and kills the loop with an error if it is exceeded.
  By default this value is set to 1000.  Added t/while.t to test suite.

* Added BREAK directive to prematurely exit FOREACH or WHILE loop.  Added 
  t/break.t to test suite and updated t/while.t and t/foreach.t.

* Added TAGS directive to allow per-file switching of the tokens that mark
  the start and end of directives.  Added t/tags.t to test suite

* Added FILTER directive to allow post-processing of output.  Filters
  are defined in the Template::Plugin::Filter module.  The Context 
  use_filter() method simply calls use_plugin(), requesting the 'filter'
  plugin module, providing he filter name and any additional parameters
  specified.  Thus "FILTER foo(bar)" is roughly equivalent to 
  "USE filter('foo', bar)".  Added t/filter.t to test suite.

* Changed Context to allow multiple PLUGIN_BASE packages to be defined.

* Added Template::OS module to autodetect operating system and return
  specific values such as path separator.  The Context creates an OS 
  object and stores it internally.

* Added OS option to Template.pm to specify operating system to override
  the autodetect.

* Changed old DIR_SEPARATOR option to PATH_SEP and old PATH_SEPARATOR to 
  PATH_SPLIT.  These are defaulted based on OS if not specified.

* Removed some old code which allowed an absolute filename to be specified
  and opened by the cache.  This isn't a bad thing, per se, but needs
  to be optional and disabled by default.  

* Added an AUTOLOAD method to Template.pm to delegate to Context object.
  Template redirect() removed, given that it is now accessible via 
  AUTOLOAD.

* Added inc() and dec() root functions to the Context object which get 
  evaluated to simple increment/decrement subs when called as root 
  variables and not otherwise defined.  This may be extended in the 
  future to provide default object/package whose methods/subs should be 
  called when root variables are requested but not defined.

#------------------------------------------------------------------------
# Version 0.22  1999/08/04 20:37:43
#------------------------------------------------------------------------

* First public beta release.

* Updated all of the documentation.  The general toolkit document, 
  Template-Toolkit.pod has been deleted and its content moved into
  Template.pm.

* Added facility to escape '$' in a document (and then have it correctly 
  unescaped) to avoid unintentionally referencing a variable when 
  INTERPOLATE is on.  Added test to t/interp.t

* Changed default tag style to be '[% blah_blah %]' whilst also supporting
  the old '%% blah_blah %%' style.  The TAG_STYLE parameter may be 
  specified as 'regular' ([% ...%]), 'percent' (%% ... %%) or 'default'
  (both of the above - [\[%]% ... %[\]%]).  The START_TAG and END_TAG 
  may still be specified and will override any values set by the TAG_STYLE.

* Added ERROR directive to allow reporting of errors via the $context->error()
  method, which by default writes to STDERR.  Changed 'error' variable as 
  passed to a CATCH block to 'e' to avoid a name clash with 'ERROR'.  Added
  t/error.t to test suite.

* Added CASE option, which by default is set to 0 to indicate non-case 
  sensitivity of *KEYWORDS* (variables are always case sensitive).
  When set off, a keyword such as 'INCLUDE' can be specified in any
  case.  When set on, all keywords must be expressed in exact, upper
  case.  Lower or mixed case versions of the same words (e.g. 'include',
  'for', 'Filter') are treated as variables.  The only exceptions are 
  'and', 'or' and 'not' which can *always* be expressed in any case.
  Added t/case.t to test.

* Added interpolation of "\n" into double-quoted text strings.

* Added THROW directive and t/throw.t to test it.  Usage is:
  %% THROW type info %%, mapping 'type' to a %% CATCH type %%.

* Improved handling of exceptions, blocking only multiple occurances
  of the same exception type.  Nested exception throwing now works OK.

* Added a catch($type, $handler) method to Template::Context for installing
  exception handlers.  Changed Template::Directive::Catch->process() to 
  call this method.

* Fixed memory leak caused by circular dependency rooted at Context.
  Template.pm DESTROY method calls context->old() to perform clearup.

* Removed ERROR_PARSE ('parse' exception) and made it a case of ERROR_FILE
  ('file').

* Removed redundant EXPAND_* constants from Template::Constants.


#------------------------------------------------------------------------
# Version 0.21  1999/07/28 16:12:58
#------------------------------------------------------------------------

* Fifth (and final?) alpha release.

* Improved Template::Iterator to allow data items to be ordered by an 
  external function or by one of the default ordering styles: 'sorted'
  or 'reverse'.  The Iterator will also accept an action parameter
  which is called on each iteration.  These can be set by passing an
  additional hash reference to the iterator constructor containing ORDER
  and/or ACTION keys.  e.g.
 
  my $iterator = Template::Iterator->new(['foo', 'bar', 'baz'], 
			{ ORDER => 'sorted', ACTION => \&format_data });

  These can also be added as named parameters in parenthesis after a 
  list constructor, e.g.

  %% FOREACH user = [ tom dick harry ] ( order => 'sorted') %%
     ...
  %% END %%

  %% iterator = [ foo bar baz ] ( order => 'reverse' ) %%
  %% INCLUDE winner FOREACH person = iterator %%

* Added the Template::Plugin::Format module which implements a very 
  simple plugin for creating sprintf-like formatting functions.  e.g. 
  %% USE format; bold = format('<b>%s</b>'); bold('foo'); bold('bar') %%
  %% FOREACH [ foo bar baz]( order='sorted' action=format('-- %s --') ) %%
  etc., etc.  See t/format.t for examples.

* Added thrown() method and internal flag to Template::Exception to 
  indicate if it has been handled by the $context->thrown() method.
  Changed Template::Directive::Block to throw any unthrown exceptions
  it recevies to the $context->throw() method.  The upshot is that 
  user code can now simply C<return (undef, Template::Exception->new(...))>
  and the calling block loop will throw the exception.  Previously, the 
  user code was required to directly call $context->throw() to raise an 
  exception.  User code is no longer passed a reference to the context 
  (although plugin objects have an internal reference they can use) so 
  this would not have been possible otherwise.  Fixed a couple of other 
  minor bugs in the exception throwing/handling in the process.

* Finalised the return protocol for user code and object methods and 
  implemented.  Code/methods may return a value and optionally, an 
  additional status.  The status code may be a Template::Exception
  (see previous item).  An undefined value returned will raise an
  'undef' exception unless the error is already defined.  If the 
  error is STATUS_OK (0) then the calue will be silently converted 
  to an empty string ''.

* Added tests t/code.t and t/object.t to test variable bindings to 
  user code and objects respectively.  Added t/private.t to test that
  members prefixed with '_' or '.' remain unexposed.

* Added OP_TOLERANT as a temporary fix to set a flag to prevent the 
  context runop() method from automatically raising an undef exception
  when it resolves a variable to an undefined value.  This is to allow
  directives such as IF to tolerate undefined values without raising 
  exceptions.  Added tests to t/if.t to test this.

* Fixed another instance of the OP_NOT bug (previously fixed in 0.18)
  which manifested itself when UNLESS was used as a side-effect, e.g. 
  %% RETURN UNLESS something_to_do %%.  Added tests to t/unless.t to 
  detect.

* Fixed minor bug in the parser which wasn't allowing a trailing comma
  in an argument or named parameter list.  Updated t/hash.t and added 
  t/list.t to test this and other related issues.

* Added public context() method to Template.pm to return internal
  context reference.


#------------------------------------------------------------------------
# Version 0.20  1999/07/27 12:59:08
#------------------------------------------------------------------------

* Fourth public alpha release.

* Fixed bug in Context throw() method which was causing re-entrancy 
  problems in CATCH handlers.  Also changed to pass a variable named 
  'error' into the CATCH block containing the members 'type' and 'info'.
  e.g. %% CATCH undef %% <!-- $error.info --> %% END %%.  Added tests
  to t/catch.t.

* Added '+' chomp option to compliment '-' option.  The '+' disables chomping
  for that directive, the '-' forces it.  Improved the PRE_CHOMP to work 
  better when POST_CHOMP is also enabled and to pre-chomp correctly on the 
  first line of the file.  And hopefully, all this without screwing up line
  numbering.

* Fixed grammar to allow literals as lvalues.

* Changed BLOCK definition grammar to allow names that contain dots and 
  slashes as per INCLUDE.  These are treated as literal.

* Fixed bug in FOREACH which was causing an undefined variable reference
  to go un-noticed.  

* Changed FOREACH to clone (localise) a stash context so that it
  doesn't trample on previously defined variables.  In addition, it
  will also automagically import the members of HASH references that
  are returned by each iteration when a target loop variable isn't
  specified.

  This now allows you to write things like:
     %% FOREACH userlist %%
        $name ($id)
     %% END %%

  Instead of:
     %% FOREACH user = userlist %%
	$user.name ($user.id)
     %% END %%

* added tests to t/foreach.t to verify the above behaviour.

* added test scripts binop.t, chomp.t, prechomp.t, postchomp.t
  and skel.t.  Extended/improved tests in if.t, predefs.t.

* Fixed bug in tokeniser that was failing to recognise '!='. 


#------------------------------------------------------------------------
# Version 0.19  1999/07/26 19:53:39
#------------------------------------------------------------------------

* Third public alpha release.

* Added Template::Plugin and engaged the USE directive to load plugin
  modules, instantiate plugin objects and bind them to variables in 
  the stash.  Modified the grammar a little to build the appropriate 
  reduction for the parenthesised parameters that may be passed from 
  the USE directive.  Wrote simple stubs for Template::Plugin::CGI and 
  Template::Plugin::DBI.

* Fixed bug in UNLESS which was using the old '!' character instead of
  OP_NOT.  Added t/unless.t to test UNLESS directive and IF directive
  with logical negation operator ('!', aka OP_NOT)

* Changed INCLUDE parameter to allow '/' as well as '.' within the name.
  This is in addition to the regular \w characters permitted.  Names 
  containing any other characters must be quoted.  Updated t/include.t
  to add test for this.

* Fixed bug that was causing the 'and' and 'or' boolean operations to 
  not be recognised unless specified in UPPER CASE.  

* Added t/direcive.t to test general directive options (e.g. chomping,
  whitespace and case insensitivity, etc.

* Fixed IMPORT option and added t/import.t test.

* Fixed EXPORT and added t/export.t test.


#------------------------------------------------------------------------
# Version 0.18  1999/07/23 11:50
#------------------------------------------------------------------------

* Second public alpha release

* Re-wrote the parser grammar and associated runtime support for the 
  very last time.  The grammar needs some polishing and there are a 
  couple of ugly/elegant hacks (depending on your perspective)  
  to manage special cases for INCLUDE, in particular.  These
  could be improved, but they work for now.

* The language now fully supports multiple namespace variables of 
  which any sub-element might be represented by a variable, hash array
  or entry, list, code reference or object.  The runtime opcode loop
  evaluates these with respect to one another where joined by '.'

* Parameters can be specified to any individual element.  e.g. foo(a).bar(b)

* An individual element may be an evaluated variable  e.g. user.${uname}

* The INTERPOLATE option now includes period as part of identifier names.
  Braces need only be used to delimit a variable against another period.
  e.g.  $user.name   ${user.id}.gif

* An assignment may now be enclosed in parentheses and used as a term, e.g.
  %% IF (users = mydb.get_userlist) %%

* Changed the calling convention for variables bound to code and
  object (methods).  A reference is no longer passed as the first 
  parameter.  This makes it easier to interface to existing code
  and marginally quicker to write new code.  The Template::Stash
  module can be sub-classed to create plug-in library modules which
  can have far greater intimacy with the Template Toolkit.

* Fixed broken parameter passing into code bound to variables.  Added
  t/call.t to test correct behaviour.  Then the whole calling convention
  got changed again, but its legacy remains...

* Re-wrote and/or cleaned up the entire test suite.  Some are still
  incomplete or missing.

* Updated Template-Toolkit.pod to remove some of the documentation that 
  was clearly obsoleted by these changes.  Added and corrected most of the
  obvious stuff, but there's still some lacking and it may include features 
  missing, changed or broken.

* Numerous minor bugs, typos, etc.


#------------------------------------------------------------------------
# Version 0.17  1999/06/24 23:55
#------------------------------------------------------------------------

* First public alpha release