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

时间:2011-11-03 21:18:05

标签: markup jinja2

是否可以重载Jinja2的autoescape,以便以用户指定的方式(即除了LaTeX等HTML之外的其他东西)转义某些内容?

以下是试图逃离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',
    })

运行上述内容时,输出:

 \documentclass[memoir]
     \begin{document}
     {bob} &lt;-- is escaped
     \end{document}

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

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

我的第一个想法是重载finalize并禁用autoescape。 e.g。

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',
    })

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

documentclass[memoir]
     begin\{document\}
     \{bob\} <-- is escaped
     end\{document\}

如果我将autoescape设置为True,并在最终确定几乎工作(并且在此示例中,它确实有效):

\documentclass[memoir]
     \begin{document}
     \{bob\} <-- is escaped
     \end{document}

启用autoescape有效,因为它使模板的主体文本为Markup(即安全)。

但是,问题出在哪里,如果我将输入更改为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'],
    })

当我跑步时,我得到:

\documentclass[memoir]
     \begin{document}
     A&amp;B  > a & b > C&lt;D
     \end{document}

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

有没有比重载TeX函数更好的方法来处理finalize的转义?可以重载autoescape吗?

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

感谢您的阅读。

0 个答案:

没有答案