Trim whitespace (trailing newline) at the end of included Twig template - twig

I’m trying to include a Twig template inside another, but there is undesirable whitespace which is caused by the trailing newline in the included template.
My use case is that the include takes place mid-sentence, just before a comma, and I don’t want any whitespace before the comma.
Base template:
Né le {{ include("date.html.twig", {date: date}) }}, décédé le…
Included template:
<time datetime="...">
{{- date.format() -}}
</time>
Desired result :
Né le 6 mai 1977, décédé le…
Actual result :
Né le 6 mai 1977 , décédé le…
I can confirm the trailing newline is the cause of the issue, but removing it is not a viable solution to me since most tools are configured to add it if it’s missing.
Is there any way to trim this trailing newline?

I found the solution while writing the question:
Ending the included template with a Twig tag seems to be enough. So I ended up wrapping the content in a spaceless filter:
{% apply spaceless %}
<time datetime="...">
{{- date.format() -}}
</time>
{% endapply %}
Technically using {% if true %} … {%- endif %} also works, but is much less understandable.
- modifiers are still needed inside <time> because spaceless only removes whitespace between HTML tags, not inside.

Related

Displaying a link in a Twig temple

It seems easy, but I encounter a weird behavior.
In a twig file :
{% set my_html = 'Hello world' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html)|raw : ('2'~my_html)|raw) -}}
The printed part is ('2'~my_html)|raw and it works fine : I see a real link.
Output is :
2Hello world
Now, it works only because I apply the raw filter to ('1'~my_html)... Try this :
{% set my_html = 'Hello world' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html) : ('2'~my_html)|raw) -}}
And it will display : 2Hello world
I don't understand why I need to apply a filter on something else to get the expected result ? Is it a bug ?
This is a documented behavior of the raw filter. I quote the note from that page:
Be careful when using the raw filter inside expressions:
{% autoescape %}
{% set hello = '<strong>Hello</strong>' %}
{% set hola = '<strong>Hola</strong>' %}
{{ false ? '<strong>Hola</strong>' : hello|raw }}
does not render the same as
{{ false ? hola : hello|raw }}
but renders the same as
{{ (false ? hola : hello)|raw }} {% endautoescape %}
The first ternary statement is not escaped: hello is marked as being
safe and Twig does not escape static values (see escape). In the
second ternary statement, even if hello is marked as safe, hola
remains unsafe and so is the whole expression. The third ternary
statement is marked as safe and the result is not escaped.
And a comment on a github issue clarifies that the concatenation operator marks your string as unsafe. So in your case
{% set my_html = '<' %}
{# ('1'~my_html) is not safe, so the whole expression is not #}
{{ false
? ('1'~my_html)
: ('2'~my_html)|raw
}}
includes two strings: a safe one, ('2'~my_html)|raw) and an unsafe one, ('1'~my_html) (because it does not apply the raw filter), so as the note from raw documentation says, the whole expression stays unsafe and autoescaping is applied. But in the other case when both strings are marked safe, the whole expression becomes safe and the autoesaping is not applied:
{% set my_html = '<' %}
{# now both strings are safe, so is the whole expression #}
{{ false
? ('1'~my_html)|raw
: ('2'~my_html)|raw
}}
This is not a bug but, due to the fact the default settings of twig will autoescape variables.
You can read more about it in the documentation.

Output from field of type HTML prints tags verbatim (BOLT-CMS / Twig)

In Bolt CMS, I have a field defined like so:
contenttypes.yaml
details: # thats my new content type
name: (...)
(...)
fields:
(...)
contentblocks:
type: block
label: Content
fields:
freetext:
label: Formatted Text
fields:
content:
type: html
(...)
However, now when i display this in my template with ...
{% setcontent nameAddr = 'data/name-addr' %}
{% for group in nameAddr.contentblocks %}
{% if group.block == 'freetext' %}
{{group.content}}
{% endif %}
{% endfor %}
... I get output like this in the page (via view-source):
<p>a<br />
<br />
b</p>
So the tags are somehow printed verbatim.
(I am not entering the tags in WYSIWYG mode.)
Im a bit confused since everything seems identical to the documentation (1) (2).
Would be great if someone could help me out. Cheers.
{{group.content | raw}}
See https://twig.symfony.com/doc/2.x/filters/raw.html
Bolt uses the Twig template engine. As such, all default twig {{
|filters }} also work in Bolt. Most of these have a similar meaning in
plain PHP or Javascript. The available filters are: abs, batch,
capitalize, convert_encoding, date, date_modify, default, escape,
first, format, join, json_encode, keys, last, length, lower, merge,
nl2br, number_format, raw, replace, reverse, round, slice, sort,
split, striptags, title, trim, upper, url_encode.
You have to use the raw filter, as in:
{{group.content | raw}}
cf this question and documentation of raw.

Twig: Render block multiple times: parsed, escaped, verbatim

I’m building a pattern library that displays my production twig partials with some additional information. Under each pattern, I want to have two code snippets that I want to be generated from my pattern. One is the parsed HTML, the other one is my Twig code directly from the partial file, including variables and other Twig code.
Question
How do I reuse a block that I already parsed and rendered on my page, but in its unparsed form?
Files:
moduleXYZ.html (production module code), which extends…
_pattern.html (wrapper with additional informational code for pattern library), which uses…
_pattern_foot.html (in here, the block defined in _pattern.html and overwritten in moduleXYZ.html should be displayed verbatim)
moduleXYZ.html:
{% extends '_pattern.html' %}
{% block pattern %}
<h2>{{ variable|default('Some placeholder text') }}</h2>
{% endblock %}
_pattern.html:
{% block pattern %}
No pattern defined.
{% endblock %}
{% use '_pattern-foot.html' %}
{% block('patternfoot') %}
_pattern-foot.html:
{% block patternfoot %}
<h2>HTML for this pattern:</h2>
<pre><code>
{{ block('pattern')|e }} {# THIS WORKS, escaped HTML is displayed. #}
</code></pre>
<h2>Twig for this pattern:</h2>
<pre><code>
{{ block('pattern')|e }} {# THIS IS NOT WORKING, of course, because the block is already parsed. #}
</code></pre>
{% endblock %}
What didn’t work
I managed to get the result I want by wrapping the "pattern" block in moduleXYZ.html in {% verbatim %}, but then of course my logic/variables go unparsed in the module itself, too.
I understand it’s not possible to pass variables into the block() function, so I also can’t toggle verbatim conditionally for my reused block (or can I?).

Twig - Trim exact string only

I want to trim a string using twig. The documentation for trim is located here.
{{ 'I like Twig!'|trim('!') }}
{# outputs 'I like Twig' #}
The above example trims exclamation marks from the string.
Consider the following:
{{ 'ROLE_USER'|trim('ROLE_') }}
One would think this would trim ROLE_ and return USER. That's not how it works:
{# outputs 'US' #}
This is because the letters E and R are also in ROLE_, hence they are also removed.
How can I circumvent this, perhaps with a regular expression, or replacing only exactly the string I want?
What about the replace filter?
{{ 'ROLE_USER'|replace({'ROLE_': ''}) }}
//outputs
USER

Minus In twig block definition

What's the difference between this:
{%block body %}
and that
{%block body -%}
Just read something about it in the documentation, not sure if this will also apply on {% block ... %} tags.
Twig whitespace control
{% set value = 'no spaces' %}
{#- No leading/trailing whitespace -#}
{%- if true -%}
{{- value -}}
{%- endif -%}
{# output 'no spaces' #}
There's also another example given which trims the whitespace in front of the variable but doesnt't do it at the end - so the effect is only on one side.
{% set value = 'no spaces' %}
<li> {{- value }} </li>
{# outputs '<li>no spaces </li>' #}
The above sample shows the default whitespace control modifier, and how you can use it to remove whitespace around tags. Trimming space will consume all whitespace for that side of the tag. It is possible to use whitespace trimming on one side of a tag
So I think the difference in your given exmaples is that in the first block body there will be a whitespace after the block started. In your second example body - there's none after the block started.
Just read the documentation entry to see how it works.
EDIT
A simple example to demonstrate the example in the docu:
{% set value = 'NO space in source code after/before "value"' %}
<li> {{- value -}} </li>
...
outputs in Firebug in the HTML markup:
Whereas this
{% set value = 'space in source code after "value"' %}
<li> {{- value }} </li>
...
ouputs:
Notice the space between "value" and the closing </li> in the second example. So the minus - erases/trims a whitespace either before, after or on both sides of e.g. a variable.

Resources