Is it possible to overload Jinja2 autoescape so that it accelerates something in a user-defined way (for example, something like HTML, for example LaTeX)?
Here is an example trying to avoid TeX .
import jinja2 class MyEnv(jinja2.Environment): def __init__(self, filters={}, globals={}, tests={}, loader=None, extensions=[], **kwargs): super(MyEnv, self).__init__( autoescape = True, ) template = MyEnv().from_string("""\documentclass[{{ class }}] \\begin{document} {{ content }} \end{document} """) print template.render({ 'class':'memoir', 'content': '{bob} <-- is escaped', })
When you run above, you get:
\documentclass[memoir] \begin{document} {bob} <
The problem is that HTML escaping is used. Therefore, { and } must be escaped, but it is not, and < converted to < but it should not be.
I would like to overload the escape function that Jinja2 uses to remove variables.
My first thought is to overload finalize and disable autoescape . eg.
import jinja2 class MyEnv(jinja2.Environment): def __init__(self, filters={}, globals={}, tests={}, loader=None, extensions=[], **kwargs): super(MyEnv, self).__init__( autoescape = False, # turn off autoescape finalize = self.finalize, ) def finalize(self, s): import re if isinstance(s, jinja2.Markup): return s s = s.replace('\\', '') s = s.replace('~', '\\textasciitilde') s = re.sub(r'([#|^|$|&|%|{|}])', r'\\\1', s) s = re.sub(r'_', r'\\_', s) return jinja2.Markup(s) template = MyEnv().from_string("""\documentclass[{{ class }}] \\begin{document} {{ content }} \end{document} """) print template.render({ 'class':'memoir', 'content': '{bob} <-- is escaped', })
The result is incorrect, because the main text is not enclosed in Markup (i.e. the line is marked as safe):
documentclass[memoir] begin\{document\} \{bob\} <-- is escaped end\{document\}
If I set autoescape to True and go into finalization, it almost works (and in this example it works):
\documentclass[memoir] \begin{document} \{bob\} <-- is escaped \end{document}
Rotating autoescape works because it makes the body of the text for the Markup template (i.e. safe).
However, here is where the problem is if I change the entry to the list that join ed:
template = MyEnv().from_string("""\documentclass[{{ class }}] \\begin{document} {{ content|join(" > a & b > "|safe) }} \end{document} """) print template.render({ 'class':'memoir', 'content': ['A&B', 'C<D'], })
When I run this, I get:
\documentclass[memoir] \begin{document} A&B > a & b > C<D \end{document}
It would seem that HTML autoescape is executed for "content" elements, not finalize . The simplest solution, provided that Jinja2 and its auto-security are loosely coupled, would seem to overload the autoescape function. I can't figure it out, and the best I came up with is the finalize function.
Is there a better way to handle TeX escaping than overloading the finalize function? Can I reload autoescape ?
For example, is it possible to install a custom markup package? (a choice I'd rather avoid)
Thanks for reading.