Date of release: 2004-June-15
FreeMarker 2.3 introduces numerous little new features and quality improvements compared to the 2.2.x series. The most notable improvements are the ability to define functions (methods) in templates, the ability to interpolate variables in string literals, the support for a variable number of macro parameters, and the more intelligent default object wrapper. Although none of the improvements is a drastic change, the 2.3.x series is not backward compatible with the 2.2.x series (see the list below), so you may choose to use it for new projects only.
Probably the most ``loudly promoted'' new feature is the totally redesigned XML wrapper. With the new XML wrapper FreeMarker targets a new application domain, which is similar to the application domain of XSLT: transforming complex XML to whatever textual output. Although this subproject is young, it is definitely usable in practice. See the XML Processing Guide for more details.
Non backward-compatible changes!
-
Since interpolations (
${...}
and#{...}
) now work inside string literals, the character sequence${
and#{
in string literals are reserved for that. So if you have something like<#set x = "${foo}">
, then you have to replace it with<#set x = r"${foo}">
-- beware, escapes such as\n
will not work in raw (r
) strings. -
The default (initial) value of the
strict_syntax
setting has been changed fromfalse
totrue
. Whenstrict_syntax
istrue
, tags with old syntax as<include "foo.ftl">
will be considered as static text (so they go to the output as-is, like HTML tags do), and not as FTL tags. Such tags have to be rewritten to<#include "foo.ftl">
, since only parts that starts with<#
,</#
,<@
, or</@
count as FTL tags. Or, to recover the old transitional behavior, where both legacy and new tag syntax was recognized, you have to explicitly setstrict_syntax
tofalse
:cfg.setStrictSyntaxMode(false)
. Also, for individual templates you can force the old behavior by starting the template with<#ftl strict_syntax=false>
. (For more information about why strict syntax is better than old syntax read this...) -
Several classes were moved from the
freemarker.template
package, to the newfreemarker.core
package:-
"Normal" classes:
ArithmeticEngine
,Configurable
,Environment
-
Exceptions:
InvalidReferenceException
,NonBooleanException
,NonNumericalException
,NonStringException
,ParseException
,StopException
-
Errors:
TokenMgrError
The main reason of the splitting of
freemarker.template
package was that the amount of "expert" public classes and interfaces grows too much, as we introduce API-s for third-party tools, such as debugging API. -
"Normal" classes:
-
freemarker.template.TemplateMethodModel.exec
now returnsObject
instead ofTemplateModel
. -
White-space stripping is now more aggressive as before: it always removes leading and trailing white-space if the line only contains FTL tags. (Earlier the white-space was not removed if the tag was
<#include ...>
or user-defined directive tag with empty directive syntax as<@myMacro/>
(or its equivalents:<@myMacro></@myMacro>
and<@myMacro></@>
). Now white-space is removed in these cases as well.) Also, white-space sandwiched between two non-outputting elements, such as macro definitions, assignments, imports, or property settings, is now ignored. More information: 模板开发指南/其它/空白处理/剥离空白 -
The
function
directive is now used for defining methods. You should replacefunction
withmacro
in your old templates. Note, however, that oldfunction
-s will still work if you don't use thereturn
directive in them, and you invoke them with the deprecated thecall
directive. -
The expressions
as
,in
, andusing
are now keywords in the template language and cannot be used as top-level variable names without square-bracket syntax. If, by some chance, you have top-level variables that use one of these names, you will have to rename them, or use the square-bracket syntax with the.vars
special variable:.vars["in"]
. -
The
?new
built-in, as it was implemented, was a security hole. Now, it only allows you to instantiate a java object that implements thefreemarker.template.TemplateModel
interface. If you want the functionality of the?new
built-in as it existed in prior versions, make available an instance of thefreemarker.template.utility.ObjectConstructor
class to your template. (For example:myDataModel.put("objConstructor", new ObjectConstructor());
, and then in the template you can do this:<#assign aList = objConstructor("java.util.ArrayList", 100)>
) -
Changes to the
FreemarkerServlet
:-
The
FreemarkerServlet
usesObjectWrapper.DEFAULT_WRAPPER
by default instead ofObjectWrapper.BEANS_WRAPPER
. What this means is that, by default, objects of typejava.lang.String
,java.lang.Number
,java.util.List
, andjava.util.Map
will be wrapped asTemplateModels
via the classesSimpleScalar
,SimpleNumber
,SimpleSequence
, andSimpleHash
respectively. Thus, the java methods on those objects will not be available. The default wrapper implementation in FreeMarker 2.3 automatically knows how to wrap Jython objects, and also wrapsorg.w3c.dom.Node
objects into instances offreemarker.ext.dom.NodeModel
. -
The
FreemarkerServlet
base implementation no longer deduces the locale used for templates withHttpRequest.getLocale()
. Rather, it simply delegates to the new protected method,deduceLocale
. The default implementation of this method simply returns the value of configuration thelocale
setting.
-
Changes on the FTL side
-
Interpolation in string literals. For convenience, interpolations are now supported in string literals. For example:
<@message "Hello ${user}!" />
is the same as<@message "Hello " + user + "!" />
-
Raw string literals: In string literals prefixed with
r
, interpolations and escape sequences will not be interpreted as special tokens. For example:r"\n${x}"
will be simply interpreted as the character sequence'\'
,'n'
,'$'
,'{'
,'x'
,'}'
, and not as line-feed and the value of thex
variable. -
Method variables can be defined in FTL, with the
function
directive. -
Support for a variable number of macro parameters. If the last parameter in a macro declaration ends with
...
, all extra parameters passed to the macro will be available via that parameter. For macros called with positional parameters, the parameter will be a sequence. For named parameters, the parameter will be a hash. Note that it all works with the newfunction
directive as well. -
A new header parameter,
strip_text
, that removes all top-level text from a template. This is useful for ``include files'' to suppress newlines that separate the macro definitions. Seeftl
directive -
New special variable:
.vars
. This is useful to read top-level variables with square bracket syntax, for example.vars["name-with-hyphens"]
and.vars[dynamicName]
. -
macro
and assignment directives now accept arbitrary destination variable name with quoted syntax. For example:<#macro "name-with-hyphens">...
or<#assign "foo bar" = 123>
. -
The
?keys
and?values
hash built-ins now return sequences. In practical terms this means you can access their sizes or retrieve their sub variables by index, and use all of the sequence built-ins. (Note for the programmers: TheTemplateHashModelEx
interface has not been changed. Your old code will work. See the API documentation to see why.) -
Existence built-ins (
?default
,?exists
, etc.) are now working with sequence sub variables as well. Read the documentation of thedefault
built-in for more information. -
White-space stripping is now more aggressive as before: it always removes leading and trailing white-space if the line only contains FTL tags. (Earlier the white-space was not removed if the tag was
<#include ...>
or user-defined directive tag with empty directive syntax as<@myMacro/>
(or its equivalents:<@myMacro></@myMacro>
and<@myMacro></@>
). Now white-space is removed in these cases as well.) Also, top-level white-space that separates macro definitions and/or assignments is now ignored. More information: 模板开发指南/其它/空白处理/剥离空白 -
White-space stripping can be disabled for a single line with the
nt
directive (for No Trim). -
Hashes can be concatenated using the
+
operator. The keys in the hash on the right-hand side take precedence. -
New built-ins for Java and JavaScript string escaping: j_string and js_string
-
The
replace
andsplit
built-ins now support case-insensitive comparsion and regular expressions (J2SE 1.4+ only), and some other new options. More information can be found here. -
New built-in for regular expression matching (J2SE 1.4+ only):
matches
-
New built-in,
eval
, to evaluate a string as FTL expression. For example"1+2"?eval
returns the number 3. -
New built-ins for Java and JavaScript string escaping: j_string and js_string
-
New special variables to read the value of the locale setting:
locale
,lang
. See more in the reference... -
New special variable to read the FreeMarker version number:
version
. See more in the reference... -
Tree new directives,
recurse
,visit
andfallback
, were introduced to support declarative node-tree processing. These are meant to be used typically (though not exclusively) for processing XML input. Together with this, a new variable type has been introduced, the node type. See the chapter on declarative XML processing for more details. -
The
?new
built-in, as it was implemented, was a security hole. Now, it only allows you to instantiate a java object that implements thefreemarker.template.TemplateModel
interface. If you want the functionality of the?new
built-in as it existed in prior versions, make available an instance of thefreemarker.template.utility.ObjectConstructor
class to your template. (For example:myDataModel.put("objConstructor", new ObjectConstructor());
, and then in the template you can do this:<#assign aList = objConstructor("java.util.ArrayList", 100)>
) -
Variable names can contain
@
anywhere (without using quote-bracket syntax). For example:<#assign x@@@ = 123>
is valid. -
The expressions
as
,in
, andusing
are now keywords in the template language and cannot be used as top-level variable names without square-bracket syntax (as.vars["in"]
). -
New parameter to the
ftl
directive:attributes
. The value of this attribute is a hash that associates arbitrary attributes (name-value pairs) to the template. The values of the attributes can be of any type (string, number, sequence... etc.). FreeMarker doesn't try to understand the meaning of the attributes. It's up to the application that encapsulates FreeMarker (as a Web application framework). Thus, the set of allowed attributes and their semantic is application (Web application framework) dependent. -
Other minor quality improvements...
Changes on the Java side
-
Smarter default object wrapping: The default object wrapper is now
freemarker.template.DefaultObjectWrapper
, which falls back on wrapping arbitrary objects as beans using thefreemarker.ext.beans.BeansWrapper
. Also, it will wraporg.w3c.dom.Node
objects with the new DOM wrapper. Also, it is aware of Jython objects, and will usefreemarker.ext.jython.JythonWrapper
if the object passed in is a Jython object. (We count it as a backward compatible change, since this new object wrapper wraps differently only those objects that the old wrapper was not able to wrap, so it has thrown exception.) -
freemarker.template.TemplateMethodModel.exec
now returnsObject
instead ofTemplateModel
. -
The default (initial) value of the
strict_syntax
setting has been changed fromfalse
totrue
. Whenstrict_syntax
istrue
, tags with old syntax as<include "foo.ftl">
will be considered as static text (so they go to the output as-is, like HTML tags do), and not as FTL tags. Such tags have to be rewritten to<#include "foo.ftl">
, since only parts that starts with<#
,</#
,<@
, or</@
count as FTL tags. Or, to recover the old transitional behavior, where both legacy and new tag syntax was recognized, you have to explicitly setstrict_syntax
tofalse
:cfg.setStrictSyntaxMode(false)
. Also, for individual templates you can force the old behavior by starting the template with<#ftl strict_syntax=false>
. (For more information about why strict syntax is better than old syntax read this...) -
New
CacheStorage
implementation:freemarker.cache.MruCacheStorage
. This cache storage implements a two-level Most Recently Used cache. In the first level, items are strongly referenced up to the specified maximum. When the maximum is exceeded, the least recently used item is moved into the second level cache, where they are softly referenced, up to another specified maximum.freemarker.cache.SoftCachseStorage
andStrongCachseStorage
are deprected,MruCachseStorage
is used everywhere instead. The default cache storage is now anMruCachseStorage
object with 0 strong size, and infinite soft size.Configuration.setSetting
forcache_storage
now understands string values as"strong:200, soft:2000"
. -
For
BeansWrapper
generated models, you can now use the${obj.method(args)}
syntax to invoke methods whose return type isvoid
.void
methods now returnTemplateModel.NOTHING
as their return value. -
freemarker.template.SimpleHash
now can wrap read-onlyMap
-s, such as the map of HTTP request parameters in Servlet API. -
The
TemplateNodeModel
interface was introduced to support recursive processing of trees of nodes. Typically, this will be used in relation to XML. -
New package:
freemarker.ext.dom
. This contains the new XML wrapper, that supports the processing of XML documents using the visitor pattern (i.e. with<#visit ...>
and similar directives), and to provide more convenient XML traversing as the legacy wrapper. See the XML processing guide for more details. -
New package:
freemarker.core
. Classes used by mostly power-users was moved here from thefreemarker.template
package. The main reason of the splitting offreemarker.template
package was that the amount of "expert" public classes and interfaces grows too much, as we introduce API-s for third-party tools, such as debugging API. -
New package:
freemarker.debug
. This provides a debugging API, by which you can debug executing templates through network (RMI). You have to write the front-end (client), as the API is just the server side. For more information please read the JavaDoc of thefreemarker.debug
package. -
You can query the FreeMarker version number with static method
Configuration.getVersionNumber()
. Also, theManifest.mf
included infreemarker.jar
now contains the FreeMarker version number, furthermore, executing it withjava -jar freemarker.jar
will print the version number to the stdout. -
Added a new protected
FreemarkerServlet
method:Configuration getConfiguration()
. -
Date support is now labeled as final. (It was experimental earlier.)
-
The
BeansWrapper
has been improved to prevent some security exceptions when introspecting. -
Other minor quality improvements and extensions...
Other changes
-
Fixes and improvements in the Manual and in the API JavaDoc.
The history of the releases before the final version
Differences between the final release and Release Candidate 4
-
Added a new special variable to print the FreeMarker version number:
version
. See more in the reference... -
Minor documentation fixes and improvements.
Differences between the Release Candidate 4 and Release Candidate 3
-
The
BeansWrapper
has been improved to prevent some security exceptions when introspecting. -
The
FreemarkerXmlTask
has two new sub-tasks that can be used to prepare template execution with Jython scripts:prepareModel
andprepareEnvironment
. Thejython
sub-task is now deprecated, and does the same asprepareEnvironment
. See the Java API documentation for more details. -
New special variable to read the FreeMarker version number:
version
. See more in the reference... -
Bugfix: Greater-than sign doesn't confuse the
eval
built-in anymore. -
Bugfix: The
BeansWrapper
now wrapps thenull
return values of methods appropriately. -
Bugfix: The
FreemarkerXmlTask
doesn't need Jython classes anymore, unless you really use Jython scripts. Several other bugfixes in the Jython related features. -
Bugfix: If the template exception handler has ignored the exception, errors occurring in interpolations inside FTL tags (e.g.
<#if "foo${badVar}" != "foobar">
) were handled in the same way as errors occuring in interpolations outside FTL tags. Thus, the directive call was not skipped, and the problematic interpolation was replaced with an empty string. (This was inconsistent with the behavior of<#if "foo"+badVar != "foobar">
, which should be 100% equivalent with the previous example.) -
Bugfix: The
FileTemplateLoader
is now more robust when it receives paths that are malformed according the native file system. In the earlier version such paths sometimes caused unexpectedIOException
that aborted the searching for the template in furtherFileTemplateLoader
-s when you use theMultiTemplateLoader
.
Differences between the Release Candidate 3 and Release Candidate 2
-
Bugfix: Fixing a fatal bug in the template cache that was introduced with the latest cache ``bugfix''. The template cache has always reloaded the unchanged template when the update delay has been elapsed, until the template has been actually changed, in which case it has never reloaded the template anymore.
Differences between the Release Candidate 2 and Release Candidate 1
-
Bugfix: The template cache didn't reload the template when it was replaced with an older version.
-
API JavaDoc fix: date/time related classes/interfaces were marked as experimental. They are not experimental.
-
Minor site improvements.
Differences between the Release Candidate 1 and Preview 16 releases
-
Warning! Non-backward-compatible change! The default (initial) value of the
strict_syntax
setting has been changed fromfalse
totrue
. Whenstrict_syntax
istrue
, tags with old syntax as<include "foo.ftl">
will be considered as static text (so they go to the output as-is, like HTML tags do), and not as FTL tags. Such tags have to be rewritten to<#include "foo.ftl">
, since only parts that starts with<#
,</#
,<@
, or</@
count as FTL tags. Or, to recover the old transitional behavior, where both legacy and new tag syntax was recognized, you have to explicitly setstrict_syntax
tofalse
:cfg.setStrictSyntaxMode(false)
. Also, for individual templates you can force the old behavior by starting the template with<#ftl strict_syntax=false>
. (For more information about why strict syntax is better than old syntax read this...) -
New parameter to the
ftl
directive:attributes
. The value of this attribute is a hash that associates arbitrary attributes (name-value pairs) to the template. The values of the attributes can be of any type (string, number, sequence... etc.). FreeMarker doesn't try to understand the meaning of the attributes. It's up to the application that encapsulates FreeMarker (as a Web application framework). Thus, the set of allowed attributes and their semantic is application (Web application framework) dependent. -
Bugfix:
freemarker.template.utility.DeepUnwrap
unwrapped sequences to emptyArrayList
-s. -
Bugfix: If you included/imported a template with
*/
in path (acquisition), and that template in turn itself included/imported another template with*/
in path, it may failed. -
New methods to the
freemarker.core.Environment
:importLib(Template loadedTemplate, java.lang.String namespace)
,getTemplateForImporting(...)
,getTemplateForInclusion(...)
. -
Improvements in the
java.io.IOException
related error messages of theinclude
andimport
directives. -
Minor improvements in the documentation.
Differences between the Preview 16 and Preview 15 releases
-
New package:
freemarker.debug
. This provides a debugging API, by which you can debug executing templates through network (RMI). You have to write the front-end (client), as the API is just the server side. For more information please read the JavaDoc of thefreemarker.debug
package. (The debugging API is present for a while, just I forgot to announce it in the version history. Sorry for that.) -
Bugfix: With the new XML wrapper,
@@markup
and similar special keys:-
have returned
<foo></foo>
for empty elements instead of<foo />
. Other than it was needlessly verbose, it has confused browsers if you generate HTML. -
have showed the attributes that have no explicitly given value in the original document, just a default value coming form the DTD.
-
have forgot to put space before the system identifier in the
<!DOCTYPE ...>
.
-
-
Bugfix: XPath with Jaxen has died with
NullPointerException
if the context was an empty node set. -
A bit more intelligent Xalan XPath error messages.
-
Revoked fallback-to-classloader logic from the template cache.
-
From now, if no XPath engine is available, and the hash key in an ``XML query'' can't be interpreted without XPath, an error will tell this clearly, rather than silently returning undefined variable (null).
-
Bugfix: Some templates have caused the parser to die.
-
Some other minor improvements here and there...
Differences between the Preview 15 and Preview 14 releases
-
Bugfix: The new default template cache storage (
MruCacheStorage
) has started to continually fail withNullPointerException
from a random point of time, usually when the memory usage was high in the JVM. -
Bugfix: In error messages, when the quoted FTL directive had nested content, that was quoted as well, so the quotation could be very long and expose nested lines needlessly.
Differences between the Preview 14 and Preview 13 releases
-
freemarker.template.TemplateMethodModel.exec
now returnsObject
instead ofTemplateModel
. -
Fixes and improvements for XPath with Jaxen (not Xalan). Non-node-set XPath expressions are now working. FreeMarker variables are accessible in XPath expressions with XPath variable references (e.g.
doc["book/chapter[title=$currentTitle]"]
). -
freemarker.cache.SoftCachseStorage
andStrongCachseStorage
is deprected. The more flexibleMruCachseStorage
is used instead everywhere. The default cache storage is now anMruCachseStorage
object with 0 strong size, and infinite soft size.Configuration.setSetting
forcache_storage
now understands string values as"strong:200, soft:2000"
. -
Bugfix:
freemarker.cache.MruCachseStorage
has died withClassCastException
sometimes. -
New built-ins for Java and JavaScript string escaping: j_string and js_string
-
freemarker.template.TemplateExceptionHandler.HTML_DEBUG_HANDLER
now prints more HTML-context-proof messages. -
You can query the FreeMarker version number with static method
Configuration.getVersionNumber()
. Also, theManifest.mf
included infreemarker.jar
now contains the FreeMarker version number, furthermore, executing it withjava -jar freemarker.jar
will print the version number to the stdout. -
Added a new protected
FreemarkerServlet
method:Configuration getConfiguration()
. -
Bugfix: FreeMarker has frozen on empty conditional blocks in certain contexts.
-
Bugfix: Methods called twice on an object using the
list
directive, asparent.getChildren()
with<#list parent.children as child> ...</#list>
Differences between the Preview 13 and Preview 12 releases
-
White-space stripping is now more aggressive as before: it always removes leading and trailing white-space if the line only contains FTL tags. (Earlier the white-space was not removed if the tag was
<#include ...>
or user-defined directive tag with empty directive syntax as<@myMacro/>
(or its equivalents:<@myMacro></@myMacro>
and<@myMacro></@>
). Now white-space is removed in these cases as well.) Also, top-level white-space that separates macro definitions and/or assignments is now ignored. More information: 模板开发指南/其它/空白处理/剥离空白 -
White-space stripping can be disabled for a single line with the
nt
directive (for No Trim). -
A new directive for the declarative XML processing:
fallback
-
freemarker.template.SimpleHash
now can wrap read-onlyMap
-s, such as the map of HTTP request parameters in Servlet API.
Differences between the Preview 12 and Preview 11 releases
The only change between this and the previous preview release is that Preview 11 had a bug where DOM trees would never be garbage-collected.
Differences between the Preview 11 and Preview 10 releases
-
Many XML related changes. Some of them are incompatible with the previous preview releases! For a more detailed explanation of how XML related features now work, see: XML处理指南
-
Attention! Attribute queries such as
foo.@bar
now return sequences (similarly to child element queries and XPath queries), not single nodes. Because of the rule with node sequences of size 1, it is still good to write${foo.@bar}
, but built-ins such as?exists
,?if_exists
or?default
don't work as before. For example, instead offoo.@bar?default('black')
, you now have to writefoo.@bar[0]?default('black')
. So if you have used existence built-ins with attributes, you have to find those occurrences in the templates and add that[0]
. -
Attention! XML name-space handling has been totally reworked and is absolutely incompatible with pre 10. Don't worry about this if none of your XML input documents use you use
xmlns
attributes. Worry, though, if you have utilized the ``loose mode'', where only the local name of elements were compared, because that's now gone. Sorry... -
Attention! Special-keys
@@
and@*
now return a sequence of attribute nodes instead of the hash of them. -
Several hash keys are now working for node sequences that store multiple nodes. For example, to get the list of all
para
elements of allchapter
-s, just writedoc.book.chapter.para
. Or, to get list of title attributes of allchapter
-s writedoc.book.chapter.@title
. -
New special hash keys:
**
,@@start_tag
,@@end_tag
,@@attribute_markup
,@@text
,@@qname
. -
?parent
for attribute nodes now returns the element node the attribute node belongs to. -
You can use Jaxen instead of Xalan for XPath expressions, if you call the static
freemarker.ext.dom.NodeModel.useJaxenXPathSupport()
method once. We plan to use Jaxen automatically instead of Xalan if it is available, just the Jaxen support is not fully functional yet.
-
-
New special variable:
.vars
. This is useful to read top-level variables with square bracket syntax, for example.vars["name-with-hyphens"]
and.vars[dynamicName]
. -
New built-in,
eval
, to evaluate a string as FTL expression. For example"1+2"?eval
returns the number 3. -
FreemarkerServlet
now uses the configuration'slocale
setting, rather thanLocale.getDefault()
, to set the locale of the templates. Also, the signature of thededuceLocale
method has been changed. -
We have a new (beta status)
CacheStorage
implementation:freemarker.cache.MruCacheStorage
. This cache storage implements a two-level Most Recently Used cache. In the first level, items are strongly referenced up to the specified maximum. When the maximum is exceeded, the least recently used item is moved into the second level cache, where they are softly referenced, up to another specified maximum. You can plug to try it withcfg.setCacheStorage(new freemarker.cache.MruCacheStorage(maxStrongSize, maxSoftSize))
.
Differences between the Preview 10 and Preview 9 releases
-
The special key
@@xmlns
was removed in favor of a new FTL directive for the same purpose,<#xmlns...>
. -
By default, the system is stricter about the use of namespace prefixes. In general, you must use a prefix to qualify subelements that are associated with an XML nampespace. You can do this with the new
<#xmlns...>
directive, but prefixes declared in the input XML doc will actually work with no declaration. -
Introduced a new special key called
@@text
that returns all the text nodes contained (recursively) in an element all concatenated together. -
Either Jaxen or Xalan can be used to provide XPath functionality. Prior versions only worked with Xalan.
-
The
FreemarkerServlet
usesObjectWrapper.DEFAULT_WRAPPER
by default instead ofObjectWrapper.BEANS_WRAPPER
. What this means is that, by default, objects of typejava.lang.String
,java.lang.Number
,java.util.List
, andjava.util.Map
will be wrapped asTemplateModels
via the classesSimpleScalar
,SimpleNumber
,SimpleSequence
, andSimpleHash
respectively. Thus, the java methods on those objects will not be available. The default wrapper implementation in FreeMarker 2.3 automatically knows how to wrap Jython objects, and also wrapsorg.w3c.dom.Node
objects into instances offreemarker.ext.dom.NodeModel
. -
The
FreemarkerServlet
base implementation no longer deduces the locale to use from the HttpRequest.getLocale() hook. Rather, it simply delegates to adeduceLocale()
hook that is overridable in subclasses. The base implementation simply usesLocale.getDefault()
Differences between the Preview 9 and Preview 8 releases
-
Fixed bugs introduced with Preview 8: XPath,
@@markup
and@@nested_markup
now works with the document node.
Differences between the Preview 8 and Preview 7 releases
-
macro
and assignment directives now accept arbitrary destination variable name with quoted syntax. For example:<#macro "foo-bar">...
or<#assign "this+that" = 123>
. This is important, because XML element names can contain hyphen, and it was not possible to define a handler macro for those elements, till now. -
Special key
@@content
was renamed to@@nested_markup
. -
Fixed outdated XML related Manual parts (that were outdated even in Preview 7).
-
Better parse-error messages.
-
Minor bugfixes here and there...
Differences between the Preview 7 and Preview 6 releases
-
Caching of XPath queries should lead to significant performance improvements for XML processing, at least when XPath is heavily used.
-
Refinements in handling of XML namespaces in the XML processing functionality. The new
strict_namespace_handling
setting introduced in 2.3pre6 was removed. A general-purpose solution was arrived at that should make that configuration setting unnecessary. -
Special key
@xmlns
was renamed to @@xmlns. Reserved namespace prefixdefault
was renamed to@@default
. -
The
ftl
directive now accepts non-string types. -
New special keys were introduced for XML node wrappers in the freemarker.ext.dom package. The
@@markup
key returns the literal markup that make up that element and the@@content
key returns all the element's markup excluding the opening and closing tags. -
Minor bugfixes here and there...
Differences between the Preview 6 and Preview 5 releases
-
Existence built-ins (
?default
,?exists
, etc.) now work with sequence sub variables as well. Read the documentation of thedefault
built-in for more information. -
The
matches
built-in now returns a sequence instead of a collection. -
Refinements in handling of XML namespaces in the XML processing functionality. A new setting,
strict_namespace_handling
was introduced. If this is set (it is off by default) any node-handling macro used in with the visit/recurse machinery must be from a macro library that declares in its ftl header that it handles the namespace in question. -
Minor bugfixes here and there...
Differences between the Preview 5 and Preview 4 releases
-
The
replace
andsplit
built-ins now support case-insensitive comparison and regular expressions (J2SE 1.4+ only), and some other new options. More information can be found here. -
New butilt-in for regular expression matching (J2SE 1.4+ only):
matches
-
Minor bugfixes here and there...
-
Manual: More browser-safe HTML-s. More updated content.
Differences between the Preview 4 and Preview 3 releases
-
Bugfix: with multi-type variables,
+
operator overload for hash type had higher precedence than the precedence of some older overloads. -
The API documentation was missing from the distribution
tar.gz
.
Differences between the Preview 3 and Preview 2 releases
-
XML processing: Many various bugfixes, especially with the declarative processing.
-
XML processing: the
namespace_uri
built-in, thexmlnsuri
header parameter, and theTemplateNodeModel.getNodeNamespace
method were renamed tonode_namespace
andgetNodeNamespace
respectively. -
XML processing: Better documentation. Especially, note: XML处理指南
-
A new header parameter,
strip_text
, that removes all top-level text from a template. Seeftl
directive -
Support for a variable number of macro parameters. If the last parameter in a macro declaration ends with
...
, all extra parameters passed to the macro will be available via that parameter. For macros called with positional parameters, the parameter will be a sequence. For named parameters, the parameter will be a hash. -
For
BeansWrapper
generated models, you can now use the${obj.method(args)}
syntax to invoke methods whose return type isvoid
.void
methods now returnTemplateModel.NOTHING
as their return value.
Differences between the Preview 2 and Preview 1 releases
-
The
freemarker.ext.dom.NodeModel
API changed slightly. ThesetDocumentBuilder()
method was changed tosetDocumentBuilderFactory()
because the older scheme was not thread-safe. ThestripComments
andstripPIs
methods are renamed to TheremoveComments
andremovePIs
, and are fixed now. A new method,simplify
has been added. -
The expressions
as
,in
, andusing
are now keywords in the template language and cannot be used as top-level variable names without square-bracket syntax (as.vars["in"]
). If, by some chance, you have top-level variables that use one of these names, you will have to rename them (or use the square-bracket syntax). Sorry for the inconvenience. -
The
?new
built-in, as it was implemented, was a security hole. Now, it only allows you to instantiate a java object that implements thefreemarker.template.TemplateModel
interface. If you want the functionality of the?new
built-in as it existed in prior versions, make available an instance of the newfreemarker.template.utility.ObjectConstructor
class to your template. -
The
<#recurse>
directive was broken. It did not work with ausing
clause. This is now fixed.