How to replace break lines in twig - replace

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 ;-)

Related

Stripping out Babel in Flask Jinja Template

I’m working with this tutorial which has the following lines:
{% set user_link %}
<span class="user_popup">
<a href="{{ url_for('main.user', username=post.author.username) }}">
{{ post.author.username }}
</a>
</span>
{% endset %}
{{ _('%(username)s said %(when)s',
username=user_link, when=moment(post.timestamp).fromNow()) }}
It looks this was specifically because he uses Babel translate, which he talks about on his blog.
My question is, how can I make this work when I strip all the Babel code out, because I don’t need any translation, specifically the bit after end set.
This is the sort of thing I tried but could never get the replacement correct:
{{username, username=user_link }} said {{when,when=moment(post.timestamp).fromNow())}}
{{ user_link }} said {{ moment(post.timestamp).fromNow() }}
The arguments after the string define the replacement map for the different keywords, so:
%(username)s will be replaced by user_link, because username=user_link
$(when)s will be replaced by moment(post.timestamp).fromNow(), because when=moment(post.timestamp).fromNow()
The s ending the $(placeholder)s is there to indicate that the placeholder should be considered as a string.

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

Is there a way to capture some text in a Django template as a template variable?

Here's a non-working example which illustrates what I'm trying to do. I've imagined some tags that don't really exist:
{% capture variable=my_url %}
{% url 'foo' id=x %}/blah?x={my_variable}
{% endcapture %}
{{ my_url | urlencode }}
If this were a working example, I would want it to produce a URLendcoded version of whatever text was in the "capture" tag, which in this case is a URL.
PHP Smarty Templates have a capture feature documented here:
https://www.smarty.net/docs/en/language.function.capture.tpl
Is there a Django template equivalent of this feature?
This is solved by 3rd party package django-capture-tag. You need to install it, then use template code like this:
{% load capture_tags %}
{% capture my_url silent %}{% url 'foo' id=x %}/blah?x={{ my_variable }}{% endcapture %}
{{ my_url | urlencode }}
For the specific use case of manipulating URLs, also check out django-spurl, which also supports a capture mode of building a URL without displaying it.

How to translate variables in Jinja2/Django

I use i18n in my Jinja2 templates and everything works fine for plain text.
But I can't find any info how to use translations with variables, which I can't avoid using. Here is an example:
{% set words = ["Hello", "world"] %}
{% for word in words %}
{{ _(word) }}
{% endfor %}
What should I do to get "Hello" and "world" in my .po file?
It turned out I needed to use Babel for jinja2:
http://jinja.pocoo.org/docs/2.10/integration/
Posting here, because someone can be in the same trouble

django display textfields

I have a form with textfields in Django, and users enter texts line by line.
When I look at the entries in admin side, I saw exactly how user wrote it but when I display it on my website, in Django templates, it just joins the sentences and I couldn't display the text line by line anymore.
To illustrate, user enters text as
-bla
-bla1
-bla2
However, it looks like in my page as
-bla1-bla2-bla3
This is my code in the template:
<div>
<p>
{{ rev.myTextField }}
</p>
</div>
In HTML, newlines between text don't imply a newline in display; you need to use HTML to insert the newline. The most straightforward way is with the <br /> tag, although there are other methods as well.
Django has a template filter for this: use |linebreaks. Here's the Documentation.
So, change:
{{ rev.myTextField }}
to:
{{ rev.myTextField|linebreaks }}
Try "safe" tag
{{ rev.myTextField|safe }}
using
{{ rev.myTextField|linebreaks }}
disables <small> tag, its better to use
{{ rev.myTextField|linebreaksbr }}
it just put <br> tag, not <p>