Search code examples
pythonpython-3.xflaskjinja2

Jinja2 mark specific HTML tag as safe


I'm aware of both safe and escape filters in jinja, but I couldn't find a solution for my problem.

I have the following string :

mystring = """<script>alert('I'm unsafe')</script>

I just entered a new line


Two new lines now!"""

I want to use it in a <p> tag showing the newlines properly :

<p>{{mystring | replace('\n', '<br>')}}</p>

This doesn't work as Jinja2 automatically escapes HTML tags, but if I do :

<p>{{mystring | replace('\n', '<br>') | safe }}</p>

It will then be unsafe.

What I have tried is :

<p>{{mystring | escape | replace('\n', '<br>') | safe }}</p>

But the above doesn't work, the <br>s are still escaped for some reason

How can I have the <br> tags not be escaped?


Solution

  • to mark <br> tag as safe, the solution is to use a custom filter as described here

    Here a small example filter that breaks a text into HTML line breaks and paragraphs and marks the return value as safe HTML string if autoescaping is enabled:

    with some customization, you can adapt the logic to your case:

    create filters.py (to make the application modular)

    import re
    from jinja2 import evalcontextfilter, Markup, escape
    
    _paragraph_re = re.compile(r'(\n)')
    
    @evalcontextfilter
    def nl2br(eval_ctx, value):
    
        result = ''.join('%s' % p.replace('\n', Markup('<br>'))
            for p in _paragraph_re.split(escape(value)))
    
        if eval_ctx.autoescape:
            result = Markup(result)
    
        return result
    

    and then in app.py

    from flask import Flask
    
    from .filters import nl2br
    
    app = Flask(__name__)
    [..]
    app.jinja_env.filters['nl2br'] = nl2br
    

    and then in you template

    <p>{{ mystring | nl2br }}</p>