Controlling whitespace in Pebble templates - pebble

I'm having a hard time getting the whitespace control the way that I want in a Pebble template. I'm currently generating JSON using Pebble, but this problem and my use case is not specific to JSON (or else I would use a JSON library, such as Jackson instead).
Here's my Pebble template:
"items": {
{% for item in items -%}
"{{ item.name }}": "{{ item.value }}"{% if not loop.last %},{% endif %}
{% endfor %}
},
And, here's the generated output:
"items": {
"item1": "Value 1",
"item2": "Value 2"
},
There are two problems with this:
I had to have the two blank lines in the template (one before the endfor and one after the endfor.
I still end up with the extra blank line in the output before the closing squiggly bracket, i.e. the },.
I'd like for the template to look more like the following:
"items": {
{% for item in items -%}
"{{ item.name }}": "{{ item.value }}"{% if not loop.last %},{% endif %}
{% endfor %}
},
And, I'd like for the resulting output to be:
"items": {
"item1": "Value 1",
"item2": "Value 2"
},
I have tried many combinations of the whilespace control modifier, but no luck on getting the format that I want.

Whitespace control modifier only trim lines. It doesn't remove line feed. The only solution for your use case is to remove blank lines around {% endfor %}

Related

removing more than a character using cut

So I'm trying to search for Elements using query selector, the problem is, due to the way theses IDs are generated (with the name of regions, stores, and sale type, from the context) some of then includes spaces or dots on them which don't let them be searched.
I have identified the spaces were breaking my searches before and used cut to remove the spaces from IDs.
Is there a way to use cut to remove diferent characters as if I'm using cascaded replaces (in python) or replaceAlls (in JS) to make these ids don't have any spaces or dots? I tried using pipes but it didn't work. how can I do it?
Snippet of the formation of the elements:
{% if data.nivel == "N0" %}
<tr id="family_{{ data.familia_produto|cut:" " }}" class="bu_name_line {{ data.nivel }} title0"
data-level="{{ data.nivel }}" data-family="{{ data.familia_produto }}"
data-regional="{{ data.nome_regional }}" data-segment="{{ data.segmento }}"
data-bu-name="{{ data.nome_filial }}" onclick="show_lines('N1','{{ data.familia_produto }}')">
<td id='bu_name' onmouseenter='hight_light(this)' onmouseleave='hight_light(this)'>
{{ data.familia_produto }}
</td>
{% elif data.nivel == "N1" %}
<tr id="regional_{{ data.familia_produto|cut:" " }}_{{ data.nome_regional|cut:" " }}"
class="bu_name_line {{ data.nivel }} title1 hide" data-level="{{ data.nivel }}"
data-family="{{ data.familia_produto }}" data-regional="{{ data.nome_regional }}"
data-segment="{{ data.segmento }}" data-bu-name="{{ data.nome_filial }}"
onclick="show_lines('N2A','{{ data.familia_produto }}','{{ data.nome_regional }}')">
<td id='bu_name' onmouseenter='hight_light(this)' onmouseleave='hight_light(this)'>
{{ data.nome_regional }}
</td>
Snippet of the selection I'm trying to do to catch this elements:
if (level_name[0] == 'family'){
var forecast_lines = line.parentElement.querySelectorAll(`[id*=regional_${level_name[1]}]`)
}else if (level_name[0] == 'regional'){
var forecast_lines = line.parentElement.querySelectorAll(`[id*=filial_${level_name[1]}_${level_name[2]}]`)
}else if (level_name[0] == 'filial'){
//console.log("entrei aqui 222222222")
var forecast_lines = line.parentElement.querySelectorAll(`[id*=segmento_${level_name[1]}_${level_name[2]}_${level_name[3]}]`)
error:
Uncaught DOMException: Element.querySelectorAll: '[id*=segmento_CAFES_INTERNA_GER.INT.COMERCIAL]' is not a valid selector
Don't know exactly how is your code but it will give you an idea:
should_removed_list = [" ", ".", ",", "="]
for i in should_removed_list:
if str(i) in your_content:
your_content.replace(str(i), "")

Replace function inside value not working

Maybe I'm doing it wrong (tried several ways to achieve my goal) or overlooking something here.
What I'd like to achieve is this:
When I use the Live-search function, I get categories containing the search keyword (like: Paint -> Paint buckets, Paint brushes, Paint colors etc.) which works like a charm. The one thing I need is to style the searched keyword in the presented categories like:
Paint bucket,
Paint brushes,
Color paint
This is the code I have at the moment:
{% if (products.length + categories.length + pages.length) == 0 %}
<div id="Pi56dYpB" class="undefined"> No results for:
<b>{{ query }}</b>...
</div>
{% endif %}
{% if categories.length > 0 %}
<div class="categories">
{% for category in categories %}
{% if loop.index < 7 %}
<a class="p-0" href="{{ category.url }}" style="all:inherit;">
<h3 id="bvwiyjEN" class="undefined">{{ category.name|replace({{ query }}: "<strong>"{{ query }}"<strong>"})|raw }}</h3>
</a>
{% endif %}
{% endfor %}
{% endif %}
Unfortunately this isn't working. I did check if the {{ query }} value is accessible with this simple line of code:
<h3 id="bvwiyjEN" class="undefined">{{ category.name }} - {{ query }}</h3>
No problems found here.
Did I use the wrong syntax in my code maybe? Any help would be appreciated!
replace({{ query }}) is the wrong syntax - replace(query) should work, as you don't want to echo the variable query here
As Nico Haase pointed out already, {{ ... }} is used to output variables, this translate to something like <?php echo $foo; ?> and can't/shouldn't be used inside statements
Furthermore, the filter replace expects an array of keys to replace with the values.
You would need to change your code to the following:
{% for category in categories %}
{{ category|replace({ (query): '<strong>'~query~'</strong>',})|raw }}
{% endfor %}
demo
Some notes:
The filter replace uses the PHP function strtr in the background. This mean the output will be case-sensitive. If you don't want this, I'd advice you to follow through here
Wrapping the key with parantheses is mandatory. This will force twig to evaluate/interpolate the value of the key - demo

Golang pagination

I need to implement pagination. Actually I have pages array, page param and per_page variable.
In my code:
pages_count := math.Floor(float64(len(pages)) / float64(per_page))
then in template I need something like (pseudocode):
{{ if .page - 2 > 0 }}
{{ $start_page := .page - 2 }}
{{ else }}
{{ $start_page := 1 }}
{{ end }}
{{ if .page + 2 >= .pages_count }}
{{ $finish_page := .page + 2 }}
{{ else }}
{{ $finish_page := .pages_count }}
{{ end }}
<ul>
{{ for $i := $start_page; $i <= $finish_page; ++$i }}
<li {{ if $i == .page }} class="current_page" {{ end }}>
$i
</li>
{{ end }}
</ul>
How to implement this correctly?
Thx
When I work with Java templates (e.g. Velocity), I find that the kinds of template logic you are asking about lead to over-complex templates. The same applied in Go.
My solution is to move logic into the view-model layer and keep the templates rather dumb. This means that the controller and view model have to do a bit more work precomputing the kinds of values that your template shows. The view model is consequently larger - but it's just simple data and is easy to unit-test.
In your specific example, you would keep the for-loop that builds up the <li> list. Everything above the <ul> open tag can be handled in the view model. So the template would just work with some precomputed data.

Django Template Wont Display Complex String

I've got a list in my view, and I am trying to output it to a template. The code for this is:
{% for user in list %}
<tr class="{{ user.1 }}">
{% for item in user %}
<td class="{% autoescape off %}{{item}}{% endautoescape %}">{% autoescape off %}{{item}}{% endautoescape %}</td>
{%endfor%}
</tr>
{%endfor%}
The code itself works fine, however it will not print an element in the list if it is overly complex. It has no issue printing the same element if it is "test", however when it is populated with actual data, it displays a blank field, an moves onto the next element.
I cannot show you the exact data, but it contains speech marks, slashes, various letters and sometimes a percent. the string is usually around 25 chars long,Thank you!
EDIT: Thought I'd add that playing with autoescape doesn't help
The data that i'm trying to output is:
b"\x11\xb4\xc7\xabhM#\x04\x87\x00\xb9kV\xeet\x9d'[\xfb\x7f\x9bE\xd1P"
The entire list is:
[2, '<client>', '<acc_no>', '<username>', False, b"\x11\xb4\xc7\xabhM#\x04\x87\x00\xb9kV\xeet\x9d'[\xfb\x7f\x9bE\xd1P", 0]]

How to replace break lines in twig

I want to fill a JavaScript array with values from PHP variables using TWIG.
<script type="text/javascript">
var cont=new Array();
{% for key, post in posts %}
cont[{{ key }}] = "{{ post.content }}";
{% endfor %}
</script>
The problem is that I have post variable with several lines, so the above code make JS commands separated to few lines, that is translated as several commands, and I have an error.
So I think that I need to replace all the 'new lines' to "\n".
I tried to do like this:
cont[{{ key }}] = "{{ post.content | replace({"\n":"<br>"}) }}";
But it does not help. It still stay as few lines…
For a similar problem (outputting user data into Javascript), I found the following was necessary:
post.content|replace({"\n":' ', "\r":' '})
ie. replace \r as well as \n with spaces. This is because some user-entered content (especially for users on Windows) may contain \r (carriage returns) as well as line-breaks, which it seems do still break Javascript if not removed.
For me, nl2br wasn't suitable, because I was feeding the user content into a Javascript method (for adding user-inputted addresses to a Google Map, for what it's worth), so I didn't want any line breaks, HTML or otherwise.
The best way (and good way) to write some javascript using Twig (if you don't want \r\n) is this way:
{{ example|e('js') }}
Replacing <br /> can, of course, work, but you will encounter other problems in javascript using data from your data. Using javascript escape, it will perfectly write valid javascript the way you'd expect it to do.
For more information about escape filter:
https://twig.symfony.com/doc/3.x/filters/escape.html
There is nl2br filter: http://twig.sensiolabs.org/doc/filters/nl2br.html
Use {{ post.content | nl2br }}
If you want to just remove brake lines, this is not working:
{{ post.content | replace({"\n":""}) }}
'\' is a special sign, so you need to escape it. This will work:
{{ post.content | replace({"\\n":""}) }}
You have to use a {% spaceless %}{% endspaceless %} TAG, like this,
<script type="text/javascript">
var cont=new Array();
{% for key, post in posts %}
cont[{{ key }}] = "{% spaceless %}{{ post.content }}{% endspaceless %}";
{% endfor %}
</script>
Enjoy ;-)