Escape strings pour JavaScript en utilisant Jinja2?

Comment puis-je échapper au HTML avec Jinja2 pour qu'il puisse être utilisé comme une chaîne dans JavaScript (jQuery)?

si J'utilisais le système Templier de Django, je pourrais écrire:

$("#mydiv").append("{{ html_string|escapejs }}");

Django |escapejs filtre échapperait à des choses en html_string (par exemple citations, caractères spéciaux) qui pourrait briser l'utilisation prévue de ce bloc de code, mais Jinja2 ne semble pas avoir un filtre équivalent (est-ce que je me trompe ici?).

Existe-t-il une solution plus propre que la copie / le collage le code de Django?

18
demandé sur fragilewindows 2012-09-09 18:12:57

4 réponses

je suis face à un problème similaire l'année dernière. Pas sûr de savoir si vous utilisez bouteille, mais ma solution ressemblait à ça.

import json

def escapejs(val):
    return json.dumps(str(val)) # *but see [Important Note] below to be safe

@app.route('/foo')
def foo():
    return bottle.jinja2_template('foo', template_settings={'filters': {'escapejs': escapejs}})

(j'ai enveloppé le template_settings dict dans une fonction helper puisque je l'ai utilisé partout, mais je l'ai gardé simple dans cet exemple.)

malheureusement, ce n'est pas aussi simple qu'un filtre Jinja2 intégré, mais j'ai pu le supporter avec joie--surtout si l'on considère que j'avais plusieurs autres filtres personnalisés à ajouter, trop.

Note Importante: Hat tip to @medmunds's pour son commentaire astucieux ci-dessous, nous rappelant que json.dumps n'est pas XSS-safe. IOW, vous ne voudriez pas l'utiliser dans une production, un serveur Internet. La recommandation est d'écrire un plus sûr json échapper à la routine (ou voler de django reinhardt,--désolé OP, je sais que vous vous attendiez à éviter) et de l'appel qu'au lieu d'utiliser json.dumps.

8
répondu ron rothman ℝℝ 2013-03-09 05:48:55

Ceci est un escapejs filtre, basé sur Django, que j'ai écrit pour une utilisation dans Jinja2 modèles:

_js_escapes = {
        '\': '\u005C',
        '\'': '\u0027',
        '"': '\u0022',
        '>': '\u003E',
        '<': '\u003C',
        '&': '\u0026',
        '=': '\u003D',
        '-': '\u002D',
        ';': '\u003B',
        u'\u2028': '\u2028',
        u'\u2029': '\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\u%04X' % z) for z in xrange(32))
def jinja2_escapejs_filter(value):
        retval = []
        for letter in value:
                if _js_escapes.has_key(letter):
                        retval.append(_js_escapes[letter])
                else:
                        retval.append(letter)

        return jinja2.Markup("".join(retval))
JINJA_ENVIRONMENT.filters['escapejs'] = jinja2_escapejs_filter

exemple d'utilisation sûre dans un modèle:

<script type="text/javascript">
<!--
var variableName = "{{ variableName | escapejs }}";
…
//-->
</script>

quand variableName est un str ou unicode.

13
répondu Tometzky 2013-09-19 17:07:29

je viens de faire des recherches sur ce problème, ma solution est de définir un filtre:

from flask import Flask, Markup
app = Flask(__name__)
app.jinja_env.filters['json'] = lambda v: Markup(json.dumps(v))

et dans le modèle:

<script>
var myvar = {{myvar|json}} ;
</script>

C'est la fonctionnalité intéressante que mavar peut être quelque chose qui peut être JSON-sérialisés

1
répondu Mike Richardson 2013-10-09 10:11:12

vous pouvez aussi utiliserautoescape. Ainsi, par exemple, vous pouvez ajouter autoescape à votre environnement jinja2 en Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    autoescape=True)

alternativement, vous pouvez utiliser L'Extension Autoescape ajoutée dans Jinja 2.4 pour avoir plus de contrôle sur l'endroit où l'autoescaping est utilisé dans le HTML. Plus d'informations sur ce ici et l'exemple (Google App Engine) ici.

Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'])

HTML:

{% autoescape true %}
    <html>
        <body>
            {{ IWillBeEscaped }}
        </body>
    </html>
{% endautoescape %}
-1
répondu Tony Wickham 2013-07-06 23:05:05