Synopsis
<#escape identifier as expression>
...
<#noescape>...</#noescape>
...
</#escape>
Camel case name variant: noEscape
Description
These directives are deprecated by
output-format-based
auto-escaping since 2.3.24. Furthermore, on places that use
auto-escaping (with an output format that actually does escaping)
you aren't allowed to use the escape
directive
(as you will find out from the parsing error message
anyway).
When you surround a part of the template with an escape
directive, interpolations
(${...}
) that occur
inside the block are combined with the escaping expression
automatically. This is a convenience method for avoiding writing
similar expressions all over. It does not affect interpolations in
string literals (as in <#assign x =
"Hello ${user}!">
). Also, it does not affect numerical
interpolations
(#{...}
).
Example:
<#escape x as x?html> First name: ${firstName} Last name: ${lastName} Maiden name: ${maidenName} </#escape>
is actually equivalent to:
First name: ${firstName?html} Last name: ${lastName?html} Maiden name: ${maidenName?html}
Note that it is irrelevant what identifier you use in the directive - it just serves as a formal parameter to the escaping expression.
When you are calling macros or the include
directive, it is important to understand that escape has effect only
on interpolations that occur between the <#escape
...>
and
</#escape>
in the template
text. That is, it will not escape anything that is before
<#escape ...>
in
the text, or after the </#escape>
in the
text, not even if that part is called from inside the
escape
-d section.
<#assign x = "<test>"> <#macro m1> m1: ${x} </#macro> <#escape x as x?html> <#macro m2>m2: ${x}</#macro> ${x} <@m1/> </#escape> ${x} <@m2/>
the output will be:
<test> m1: <test> <test> m2: <test>
More technically, the effects of
escape
directive are applied at template parsing
time rather than at template processing time. This means that if you
call a macro or include another template from within an escape
block, it won't affect the interpolations in the macro/included
template, since macro calls and template includes are evaluated at
template processing time. On the other hand, if you surround one or
more macro declarations (which are evaluated at template parsing
time, as opposed to macro calls) with an escape block, the
interpolations in those macros will be combined with the escaping
expression.
Sometimes there is a need to temporarily turn off escaping for one or two interpolations in an escape block. You can achieve this by closing and later reopening the escape block, but then you have to write the escaping expression twice. You can instead use the noescape directive:
<#escape x as x?html> From: ${mailMessage.From} Subject: ${mailMessage.Subject} <#noescape>Message: ${mailMessage.htmlFormattedBody}</#noescape> ... </#escape>
is equivalent to:
From: ${mailMessage.From?html} Subject: ${mailMessage.Subject?html} Message: ${mailMessage.htmlFormattedBody} ...
Escapes can be nested (although you will do it only in rare
circumstances). Therefore, you can write something like the below
code (the example is admittedly a bit stretched, as you'd probably
place item codes in a sequence and use list
to
iterate over them, but we're now doing it this way just to
illustrate the point):
<#escape x as x?html> Customer Name: ${customerName} Items to ship: <#escape x as itemCodeToNameMap[x]> ${itemCode1} ${itemCode2} ${itemCode3} ${itemCode4} </#escape> </#escape>
is actually equivalent to:
Customer Name: ${customerName?html} Items to ship: ${itemCodeToNameMap[itemCode1]?html} ${itemCodeToNameMap[itemCode2]?html} ${itemCodeToNameMap[itemCode3]?html} ${itemCodeToNameMap[itemCode4]?html}
When you use the noescape directive in a nested escape block, it undoes only a single level of escaping. Therefore, to completely turn off escaping in a two-level deep escaped block, you need to use two nested noescape directives as well.