为(La)TeX重载Jinja2自动视图

Bri*_*unt 9 markup jinja2

是否有可能重载Jinja2,autoescape以便以用户指定的方式(即除了HTML之外的其他东西,如LaTeX)逃脱?

这是一个试图逃避的例子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',
    })
Run Code Online (Sandbox Code Playgroud)

运行上面的内容时,它会输出:

 \documentclass[memoir]
     \begin{document}
     {bob} &lt;-- is escaped
     \end{document}
Run Code Online (Sandbox Code Playgroud)

这里的问题是使用HTML转义.所以{,}应该被转义,但它们不是,并且<被转换为&lt;但它不应该被转换.

我想重载Jinja2用来转义变量的转义函数.

我的第一个想法是超载finalize和禁用autoescape.例如

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',
    })
Run Code Online (Sandbox Code Playgroud)

输出不正确,因为主文本没有被生成Markup(即标记为安全的字符串):

documentclass[memoir]
     begin\{document\}
     \{bob\} <-- is escaped
     end\{document\}
Run Code Online (Sandbox Code Playgroud)

如果我设置autoescape为True,并在最终确定它几乎可以工作(在这个例子中,它确实有效):

\documentclass[memoir]
     \begin{document}
     \{bob\} <-- is escaped
     \end{document}
Run Code Online (Sandbox Code Playgroud)

谈到autoescape对作品,因为它使文本的主体为模板Markup(即安全的).

但是,问题出在哪里,如果我将输入更改为以下列表join:

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'],
    })
Run Code Online (Sandbox Code Playgroud)

当我运行这个时,我得到:

\documentclass[memoir]
     \begin{document}
     A&amp;B  > a & b > C&lt;D
     \end{document}
Run Code Online (Sandbox Code Playgroud)

似乎HTML autoescape正在"内容"的元素上运行,而不是finalize.最简单的解决方案,如果Jinja2及其自动绑定松散耦合,似乎会使autoescape函数超载.我似乎无法弄清楚这一点,我提出的最好的是finalize功能.

是否有更好的方法来处理转义而TeX不是重载finalize函数?可以一个超负荷autoescape

例如,可以安装自定义标记包吗?(我宁愿避免的选择)

谢谢你的阅读.