Release date: 2019-08-17
Changes on the FTL side
-
Added new built-ins:
?filter(predicate),?map(mapper),?take_while(predicate),?drop_while(predicate). These allow using lambda expressions, likeusers?filter(user -> user.superuser)orusers?map(user -> user.name), or accept a function/method as parameter. Lambda expressions are also new in this release, but they can only be used in said built-ins, so they aren't like in Java for example, and also, unlike the similar Java methods, these built-ins aren't lazy in general, only in specific cases (see more here). The main goal of adding these built-ins was to allow conditionally skipping elements in thelistdirective without nestedif-s that interfere with thesepdirective, and the loop variable built-ins (see examples here). -
Added new built-ins for truncating text.
string?truncate(length)truncates the text to the given length, and by default adds[...]at the end if truncation has happened. Truncation happens at word boundaries, unless the result is too short that way, in which case it falls back to truncation mid word. There's also?truncate_wto force Word Boundary truncation, and?truncate_c(for Character Boundary) that doesn't care about word boundaries. The truncation algorithm is pluggable in the FreeMarker configuration. See the reference for more details. -
?sequencenow collaborates withseq?size,seq[index],seq[range], and with some other built-ins (filter,map,join, etc.) to spare collecting all the elements into the memory when possible. For exampleanIterator?sequence[1]will now just fetch the first 2 items, while earlier it has built a sequence that contains all the elements, only to get the 2nd element from that. Or,anIterator?sequence?sizewill now just count the elements, without collecting them into the memory. See the reference for more details. -
Extended decimal format parameter "multiplier" was incorrectly written as "multipier". Now both words are recognized.
-
?minand?maxwill now immediately stop with error when applied on a right unbounded numerical range (like1..), as that would run forever anyway.
Changes on the Java side
-
FREEMARKER-109: In JSP TLD-s, line breaks inside function parameter lists have caused
IllegalArgumentException"Invalid function signature". -
FREEMARKER-104: More helpful log and error messages (especially, no
NullPointerExceptioncause exception logged during FreeMarker XPath support initialization) if no XPath implementation is available because Java 9 modules don't allow accessing the internal Xalan that's stored undercom.sunpackages. (The messages now recommend adding Apache Xalan or Jaxen as dependency if you need XPath support.) -
The
boolean_formatconfiguration setting now can be set to"c". Then${aBoolean}will behave as${aBoolean?c}. This should only be used if you are generating output for non-human (computer) consumption only. If your output has pieces for human audience too, it's still recommended to use${aBoolean?c}wheretrue/falseoutput is needed, and either not set theboolean_formatat all, or set it to something that's appropriate for everyday users (like"yes,no"). -
New configuration setting,
fallback_on_null_loop_variable: Specifies the behavior when reading a loop variable (likeiin<#list items as i>, or in<@myMacro items; i>) that'snull(missing); iftrue, FreeMarker will look for a variable with the same name in higher variable scopes, or iffalsethe variable will be simplynull(missing). For backward compatibility the default istrue. The recommended value for new projects isfalse, as otherwise adding new variables to higher scopes (typically to the data-model) can unintentionally change the behavior of templates. -
If the result of
seq?sizeis compared to an integer literal in a template, like inseq?size != 0, orseq?size < 1, and to decide the answer it's enough to know ifseqis empty or not (i.e., the exact size isn't needed), andseqimplementsTemplateCollectionModelEx, FreeMarker will callTemplateCollectionModelEx.isEmpty()instead ofsize(). Furthermore, ifseqis the result of?filter, or of a similar built-ins that can provide lazily generated result, it will do counting to figure out the size (rather than constructing the whole sequence in memory), and will limit how far it counts based on what literal the result of?sizeis compared with. -
Added
TemplateModelUtils.wrapAsHashUnion(ObjectWrapper, List<?>)andwrapAsHashUnion(ObjectWrapper, Object...), which is useful when you want to compose the data-model from multiple objects in a way so that their entries (Mapkey-value pairs, bean properties, etc.) appear together on the top level of the data-model. -
HTMLOutputFormat,XMLOutputFormat,XHTMLOutputFormataren't final classes anymore, furthermoreXHTMLOutputFormatnow extendsXMLOutputFormat. Same applies to the respectiveTemplateOutputModel-s (TemplateHTMLOutputModelis not final anymore, etc.). This allows defining new custom markup output format classes that will work with program logic that's only prepared for the standard markup output formats, becauseinstanceof SomeStandardOutputFromatwill returntruefor them. -
When configuring FreeMarker with string values (like with a
.propertiesfile), in the settings that support the "object builder" syntax, now you can create aTemplateMarkupOutputModelvalue with the newmarkupfunction, likemarkup(HTMLOutputFormat(), "<p>Example</p>"). -
BeansWrapper.clearClassIntrospecitonCachewas deprecated as there's a typo in the method name; useclearClassIntrospectionCacheinstead.
