Assume we have a string
$mystring = "<b> Hello"
How can I display this string using twig while preventing leaking html tags? Or in other word how can I make twig to close tags automatically if they are still open?
I guess {{ mystring | raw }} just prints raw text without verifying / purifying.
sw_sanitize does this already.
{{ '<b> hello' | sw_sanitize }}
Produces:
<b> hello</b
Internally \HTMLPurifier::purify is used, which
Filters an HTML snippet/document to be XSS-free and standards-compliant.
Related
I have a page where I need to show/print the same content twice. For this, I am using drupal_view.
{{ drupal_view('product_content', 'page_1', node.id) }}
This code works only for the first position and for the second position it doesn't work. What can be done so that the content shows up in both places?
Got the solution from the Drupal community:
When something is rendered, the render system remembers what has been
rendered and won't re-render that. Assign the render output to a twig
variable and print the variable twice:
> {% set product_content = drupal_view( ... )|render %}
> {{ product_content }}
> {{ product_content }}
Here's a Twig Fiddle. There you will notice this include file:
{# include.twig #}
{{ text }}
And this main file, with several attempts to mark a text variable as safe before passing it to the include file:
{# main.twig #}
1. Pass string with HTML
{{ include('include.twig', { text: '<p>Text</p>' }) }}
2. Pass string with HTML marked safe with raw filter
{{ include('include.twig', { text: '<p>Text</p>'|raw }) }}
3. Pass variable set with string literal marked safe with raw filter
{% set text = '<p>Text</p>'|raw %}
{{ include('include.twig', { text: text }) }}
4. Pass variable set with captured chunk of text
{% set text %}<p>Text</p>{% endset %}
{{ include('include.twig', { text: text }) }}
And here are the results of rendering this template:
1. Pass string with HTML
<p>Text</p>
2. Pass string with HTML marked safe with raw filter
<p>Text</p>
3. Pass variable set with string literal marked safe with raw filter
<p>Text</p>
4. Pass variable set with captured chunk of text
<p>Text</p>
The first attempt establishes the unwanted behavior of HTML escaping. Strategies 2 and 3 attempt to use the |raw filter to avoid the escaping, but both fail. Strategy 4, using the set tag to capture a chunk of text, works perfectly.
The documentation for the |raw filter says:
The raw filter marks the value as being "safe", which means that in an environment with automatic escaping enabled this variable will not be escaped if raw is the last filter applied to it:
The documentation for the set tag says:
If you enable automatic output escaping, Twig will only consider the content to be safe when capturing chunks of text.
Unless I'm missing something, these appear to be two different definitions of "safe", with the one mentioned under the set tag meaning super-extra-safe.
Is there any way to pass super-extra-safe HTML-containing string literals into a template, without polluting my file with ugly chunk-capturing set blocks?
The answer is no, you cannot because twig does not escape static expression. The raw filter is even ignored when compiling the template.
{% set hello = "<strong>Hello</strong>" %}
{% set hello = "<strong>Hello</strong>"|raw %}
The two lines above will compile in the same sourcecode
// line 1
$context["hello"] = "<strong>Hello</strong>";
// line 2
$context["hello"] = "<strong>Hello</strong>";
source
edit:
If you really want to do this, you could either write your own include/set node or add a filter which returns a Twig\Markup
<?php
$twig->addFilter(new \Twig\TwigFilter('safe', function($v) {
return new \Twig\Markup($v);
});
{% include 'text.html' with { 'text': 'Hello <strong>World</strong>'|safe, } %}
Hello World
I would like to use the ternary operator of Twig but it shows me the HTML tags as text.
{{ (sender.firstName or sender.lastName) ? "<strong>#{sender.firstName} #{sender.lastName}</strong>" : '<strong>Unknown</strong>' }}
The result is <strong>My Name</strong> but it should be My Name.
You have to apply the raw as the output is not marked as safe when concatenating html with twig
{{ (sender.firstName or sender.lastName ? "<strong>#{sender.firstName} #{sender.lastName}</strong>" : "<strong>Unknown</strong>")|raw }}
demo
I need to print the content of a blogPost (which contains HTML content) with twig, so I have use the raw extension.
I also have to replace a part of the content by another, but how can I use the replace extension if there already is the raw one?
I have tried:
{{ blogPost.getPost()| raw | replace('[[video]]': '(your video here)') }}
{{ {{blogPost.getPost()| raw}} | replace('[[video]]': '(your video here)') }}
{{ blogPost.getPost()| raw, replace('[[video]]': '(your video here)') }}
but none of them works.
replace('[[video]]': '(your video here)')
should be
replace({'[[video]]': '(your video here)'})
That's because you need to pass an array to replace function and not a scalar value
Edit
Try with
{{ blogPost.getPost()|replace({'[[video]]': '(your video here)'})|raw }}
I have a slim/paris/twig application and I have a strange problem with the output.
This is my code:
The title: {{ share.title }}
The output is nothing.
But if I use:
The title {{ share.title | lower }}
The output is:
The title first title
{{ share.title | raw }} works too, but I don't want to use it because it shows accented characteres as weird characters.
Any idea how to solve this ?
Thanks