我最近在不同的地方看到了这个问题,无论是与 Jinja 还是 Django 模板有关。对于模板系统如何工作以及它与呈现为 HTML 并插入模板的 Markdown 文本的关系,似乎存在一个基本的误解(在一些用户中)。我会尽力解释清楚。请注意,虽然下面的答案适用于大多数模板系统(包括 Jinja 和 Django),但示例使用 Jinja 是为了说明目的(毕竟,原始问题专门询问 Jinja)。只需调整代码以匹配您选择的模板系统的 API,它应该也能正常工作。
首先,Markdown 对模板语法一无所知。事实上,Markdown 比 Jinja、Django 或其他各种流行的模板系统存在的时间更长。此外,Markdown Syntax Rules 没有提及模板语法。因此,您的模板语法不会简单地通过 Markdown 解析器传递一些包含模板语法的 Markdown 文本来处理。模板语法需要由模板引擎单独处理。例如:
from jinja2 import Environment
# Set up a new template environment
env = Environment()
# Create template with the markdown source text
template = env.from_string(text_from_markdown_editor)
# Render that template. Be sure to pass in the context (post in this instance).
template_processed_markdown = template.render(post=post)
# Now pass the Markdown text through the Markdown engine:
post_body = markdown(template_processed_markdown)
请注意,上面首先处理模板语法,然后解析 Markdown。换句话说,模板处理的输出仍然是 Markdown 文本,其标签被替换为适当的值。只有最后一行是由 Markdown 解析器转换为 HTML 的 Markdown 文本。如果您希望颠倒处理顺序,则需要切换代码以首先运行 Markdown 解析器,然后将其输出传递给模板处理器。
我认为某些混淆来自于人们通过模板系统传递 Markdown 文本。这不应该导致模板语法得到处理吗?总之,没有。
模板系统的核心是一个模板和一个上下文。然后它会在模板中找到各种标签,并用上下文中提供的匹配数据替换这些标签。但是,模板不了解上下文中的数据,也不处理该数据。例如这个模板:
Hello, {{ name }}!
还有这个上下文:
output = template(name='John')
会产生以下输出:
Hello, John!
但是,如果上下文是这样的:
output = template(name='{(some_template_syntax)}')
那么输出将是:
Hello, {{some_template_syntax}}!
请注意,虽然上下文中的数据包含模板语法,但模板并未处理该数据。它只是将其视为一个值并将其按原样插入到适当位置的模板中。这是正常且正确的行为。
但有时,您可能需要模板来对传递给模板的某些数据进行一些额外的处理。出于这个原因,模板系统提供了过滤器。当在上下文中给定一个变量时,过滤器将处理该变量中包含的数据,然后将处理过的数据插入到模板中。例如,为确保我们前面示例中的名称大写,模板应如下所示:
Hello, {{ name|capatalize }}!
在上下文中传递output = template(name='john')(注意名字是小写的),然后我们得到如下输出”
Hello, John!
注意,name 变量中的数据是通过首字母大写处理的,这是 Jinja 内置过滤器capitalize 的功能。但是,该过滤器不处理模板语法,因此将模板语法传递给该过滤器不会导致模板语法被处理。
同样的概念适用于任何markdown 过滤器。这样的过滤器仅将提供的数据解析为 Markdown 文本并返回 HTML 文本,然后将其放入模板中。在这种情况下,不会发生模板语法处理。事实上,这样做可能会导致安全问题,尤其是当 Markdown 文本是由不受信任的用户提供时。因此,任何包含模板语法的 Markdown 文本都必须单独处理模板语法。
但是,请注意。如果您正在编写包含模板语法示例作为代码块的文档(例如此答案的 Markdown 源),则模板系统不会知道其中的区别,并且会像处理代码中没有的任何模板语法一样处理这些标签堵塞。如果首先完成 Markdown 处理,以便将生成的 HTML 传递给模板系统,则该 HTML 仍将在代码块中包含未更改的模板语法,该代码块仍将由模板系统处理。这很可能不是这两种情况所期望的。作为一种解决方法,可以想象创建某种 Markdown 扩展,它将语法处理添加到 Markdown 处理器本身。但是,这样做的机制会有所不同,具体取决于所使用的 Markdown 处理器,并且超出了此问题/答案的范围。