Freemarker and line break white space - freemarker

I am using Freemarker to create an email template that contains a shipping address. In my my template I am using an <#if> statement that if address_2 or address_3 has content to print it - if not to not print anything in that line. The problem I am having is that I am getting a blank line break where that address would be and would like to avoid this.
I tried adding the <#compress> but that did not work. Is there an alternate way to do this?
My template below:
<#compress>
${transaction.custbody_company}
${transaction.custbody_address_1}
<#if transaction.custbody_address_2?has_content>${transaction.custbody_address_2}</#if> 
<#if transaction.custbody_address_3?has_content>${transaction.custbody_address_3}</#if>
${transaction.custbody_city_cda}, ${transaction.custbody_state_province} ${transaction.custbody_postal_code}
</#if>
</#compress> 

Put the significant line break inside the #if:
<#if transaction.custbody_address_2?has_content>
${transaction.custbody_address_2}
</#if>
The line breaks after the lonely tags will be removed (see white-space tripping: https://freemarker.apache.org/docs/dgui_misc_whitespace.html#dgui_misc_whitespace_stripping).

Related

Remove preceding or following newline if a conditional directive is empty

Suppose I have a template like this:
some long text
<#if some_condition>
more text
<#elseif another_condition>
different more text
</#if>
trailing long text
If some_condition or another_condition is true, then I get expected output:
some long text
more text
trailing long text
But if both conditions are false, then I get an extra empty line:
some long text
trailing long text
I would prefer to have only one empty line in such case:
some long text
trailing long text
I can achieve this by putting an empty line inside each branch of the condition:
some long text
<#if some_condition>
more text
<#elseif another_condition>
different more text
</#if>
trailing long text
But this makes the template really ugly.
Is there a way to make Freemarker remove an empty line before or after an empty directive block?
Nope. Generating output that's truly whitespace-sensitive (like plain-text documents that humans will read) is generally not practical in FreeMarker, unless the template is quite trivial. What you can do sometimes is post-processing the output, like in this case, remove duplicate line-breaks, but of course that only works if you know that there's never a duplicate line-break intentionally.
By the way, it's a problem with template engines in general. The intent of the template author is often not clear, as the template contains both template source code formatting, and output formatting. And the rabbit hole runs deep, if you also want proper indentation, etc.

freemarker - Retrieve value from sequences

Hoping this issue is easy enough to resolve.
I am trying to retrieve a single value from a sequence using FreeMarker via the advanced form PDF functionality in NetSuite.
Here is a snippet of code:
<#assign getOps>
<#list record.item as assembly>
{item: ${assembly.item}, op: ${assembly.operationsequencenumber}}
</#list>
</#assign>
Number of words: ${getOps?word_list?size}
${getOps}
When I print the above, the following is printed:
I want to be able to capture single values from this sequence, using something similar to ${getOps.item} but an error is fired:
For "." left-hand operand: Expected a hash, but this has evaluated to
a string (wrapper: f.t.SimpleScalar):
==> getOps[2] [in template "template" at line 126, column 3]
---- FTL stack trace ("~" means nesting-related):
Failed at: ${getOps[2].item} [in template "template" at line 126, column 1]
Can you identify the issue here?
Any help is appreciated.
Thanks
You are capturing output into a single string there. So it's unstructured, a flat string, therefore you can't traverse it anymore. If you really need to transform the original list, you need to use ?map (see in the FreeMarker Manual). But Netsuite uses a FreeMarker fork, and I'm not sure if they support ?map.

Length of Assign variable issue in freemarker

I am using freemarker ..want to find the length of assign variable ..i used size and length function ..but it fails and returns the error ..Please help me in how to find length of the assign variable
Please find the below code i have tried...
Input data --- cusID="a-1242" -- I want to split input data by - and want to store in separate variable through assign function
<#list (it.#CusID[0]!"")?split("-") as c><#if ((c?index) ==0)>
<#assign first>${c}</#assign>
<#assign firstlen = c?size>
</#if>
</#list>
Above code firstlen is used to find the length but it fails to find length
ERROR MESSAGES find below
For "?size" left-hand operand: Expected an extended-hash or sequence
or extended collection, but this has evaluated to a markup_output
(wrapper: f.c.TemplateXMLOutputModel):
As the error message says, first stores XML markup, not just a plain text string. You can't get the length of markup with ?length, as it's not obvious what that means (like if the content of which XML elements matter, what if you have an entity reference, etc.). The reason it's markup is that <#assign first>...</#assign> is not a normal assignment, it's for capturing output, and you are using XML output format. Instead, use normal value assignment: <#assign first = c>. Now first will have the same type as c, string.

How to I write a string with quotes and hash tags in yaml?

I have blocks of text that I want to import into a yaml file. The text includes special characters and I do not want to have to go line by line and escape each special character. How do I write the following as a string in Yaml without it converting anything to comments or choaking?
html: <p class='myParagraph'>The teacher said, "Use a #2 pencil."<br/>Question 1: 1\2=?</p>
There are single quotes, double quotes, angle brackets, forward and back slashes, and a hash.
Context
YAML 1.1
Problem
OlegOlaf McCoyly wishes to specify a string in YAML, where one or more embedded characters in the string could cause delimiter collision with the YAML syntax itself, thus breaking the YAML file.
Solution
Specify the block of text as a YAML multiline-string:
html: |
<p class='myParagraph'>"Use a #2 pencil."<br/>Question 1: 1\2=?</p>

Remove lines in Freemarker output

I am generating an odt file using Freemarker template.
My code is:
${(addressline1)!}
${(addressline2)!}
${(addressline3)!}
The problem is that when addresline1 or addressline2 or is empty, it generates an empty line. If all the fields are empty it generates three empty lines.
I have tried the following things:
[#if addressline2??]${(addressline2)!} [/#if]
[#if addressline2?has_content]${(addressline2)!} [/#if]
compress directive
[#compress]
${(addressline1)!}
${(addressline2)!}
${(addressline3)!} [/#compress]
but nothing seems to be working.
Do you edit the template in OpenOffice/LibreOffice or such visual editor? Because then the problem is that although you just see a ${something} there, FreeMarker sees <p>${something}</p>. As it's just a general purpose template text engine, it won't remove the <p></p> that remains there when the inserted text was empty. The application that uses it for ODT should give a way of purging empty paragraphs.
You should be able to get it working by doing this:
<#if addressline1 !== ''>${addressline1}</#if>
Just repeat the process to check for all 3 variables. Alternatively, if they don't exist rather than them just being empty, this code should do the work:
<#if addressline1?exists>${addressline1}</#if>
You can find further documentation in the Freemarker Manual website: http://freemarker.org/docs/index.html
Had the same problem. This is what I ended up with:
<#assign i2 = ""?left_pad(2*4)>
<#assign i3 = ""?left_pad(3*4)>
...
<#if dep.version??>${i3}<version>${dep.version}</version>${"\n"}</#if><#t>
...
Copied from my bug report:
I'd like to be able to have the NEW LINE generated conditionally, with 1 line of template source code.
<#if dep.classifier??><classifier>${dep.classifier}</classifier></#if>
This generates the indent spaces and the newline, no matter what.
{{#t}} and {{#rt}} and {{#lt}} apply at compile time, so they don't care about the condition. So they strip even if the content is there, which I don't want.
I could do this:
<#if dep.classifier??>${" "}<classifier>${dep.classifier}</classifier>${"\n"}</#if><#t>
So that's the request. It can also be anything what helps me achieve that.
Until then, I have to do:
<#if dep.classifier??>
<classifier>${dep.classifier}</classifier>
</#if>
Which I don't like because it makes the templates way longer.
Or
<#if dep.classifier??><classifier>${dep.classifier}</classifier>
</#if><#if dep.classifier??><classifier>${dep.classifier}</classifier>
</#if>
...
Which I don't like because it's messy.
Or
<#if dep.classifier??>${" "}<classifier>${dep.classifier}</classifier>${"\n"}</#if><#t>
Which I don't like because it adds superfluous pieces to the template.
The trick is to place starting <#compress> tag in the previous line of the line you need to remove if empty.
${keep this line always}<#compress>
${remove this line if empty}</#compress>
${keep this line always}
Works with freemarker 2.3.31

Resources