diff --git a/qutebrowser/completion/completiondelegate.py b/qutebrowser/completion/completiondelegate.py index 2a0c29bc2..c59d81022 100644 --- a/qutebrowser/completion/completiondelegate.py +++ b/qutebrowser/completion/completiondelegate.py @@ -194,7 +194,8 @@ class CompletionItemDelegate(QStyledItemDelegate): color: {{ conf.colors.completion.match.fg }}; } """ - template = jinja.environment.from_string(stylesheet) + with jinja.environment.no_autoescape(): + template = jinja.environment.from_string(stylesheet) self._doc.setDefaultStyleSheet(template.render(conf=config.val)) if index.parent().isValid(): diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 9cdf7f32c..75c669eb9 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -585,7 +585,8 @@ def _render_stylesheet(stylesheet): """Render the given stylesheet jinja template.""" # Imported here to avoid a Python 3.4 circular import from qutebrowser.utils import jinja - template = jinja.environment.from_string(stylesheet) + with jinja.environment.no_autoescape(): + template = jinja.environment.from_string(stylesheet) return template.render(conf=val) diff --git a/qutebrowser/utils/jinja.py b/qutebrowser/utils/jinja.py index f6d9499a5..e7b536b60 100644 --- a/qutebrowser/utils/jinja.py +++ b/qutebrowser/utils/jinja.py @@ -21,6 +21,7 @@ import os import os.path +import contextlib import traceback import mimetypes import html @@ -82,21 +83,19 @@ class Environment(jinja2.Environment): def __init__(self): super().__init__(loader=Loader('html'), - autoescape=self._guess_autoescape, + autoescape=lambda _name: self._autoescape, undefined=jinja2.StrictUndefined) self.globals['resource_url'] = self._resource_url self.globals['file_url'] = urlutils.file_url self.globals['data_url'] = self._data_url + self._autoescape = True - def _guess_autoescape(self, template_name): - """Turn auto-escape on/off based on the file type. - - Based on http://jinja.pocoo.org/docs/dev/api/#autoescaping - """ - if template_name is None or '.' not in template_name: - return False - ext = template_name.rsplit('.', 1)[1] - return ext in ['html', 'htm', 'xml'] + @contextlib.contextmanager + def no_autoescape(self): + """Context manager to temporarily turn off autoescaping.""" + self._autoescape = False + yield + self._autoescape = True def _resource_url(self, path): """Load images from a relative path (to qutebrowser). diff --git a/tests/unit/utils/test_jinja.py b/tests/unit/utils/test_jinja.py index 40f9c12bf..c2a72de1a 100644 --- a/tests/unit/utils/test_jinja.py +++ b/tests/unit/utils/test_jinja.py @@ -146,14 +146,12 @@ def test_attribute_error(): jinja.render('attributeerror.html', obj=object()) -@pytest.mark.parametrize('name, expected', [ - (None, False), - ('foo', False), - ('foo.html', True), - ('foo.htm', True), - ('foo.xml', True), - ('blah/bar/foo.html', True), - ('foo.bar.html', True), -]) -def test_autoescape(name, expected): - assert jinja.environment._guess_autoescape(name) == expected +@pytest.mark.parametrize('escape', [True, False]) +def test_autoescape(escape): + if not escape: + with jinja.environment.no_autoescape(): + template = jinja.environment.from_string("{{ v }}") + assert template.render(v='