解释顺序

2017 年 1 月 29 日 tomjoht tomjoht

Jekyll 的主要工作是将原始文本文件转换为静态网站。它通过在生成静态 HTML 输出时渲染 Liquid、Markdown 和其他转换来实现此目的。

在此转换过程中,了解 Jekyll 的解释顺序非常重要。通过“解释顺序”,我们的意思是渲染内容、渲染顺序以及在转换内容时应用哪些规则。

如果某个元素未转换,你可以通过分析解释顺序来解决问题。

解释顺序

Jekyll 按以下顺序转换你的网站

  1. 网站变量。Jekyll 浏览你的文件并填充 网站变量,例如 sitepagepost 和集合对象。(Jekyll 从这些对象中确定永久链接、标签、类别和其他详细信息的值。)

  2. Liquid。Jekyll 处理包含 页眉 的页面中的任何 Liquid 格式。你可以按如下方式识别 Liquid
    • Liquid 标签{% 开头,以 %} 结尾。例如:{% highlight %}{% seo %}。标签可以定义块或内联。定义块的标签还将带有相应的结束标签 — 例如,{% endhighlight %}
    • Liquid 变量 以双花括号开头和结尾。例如:{{ site.myvariable }}{{ content }}
    • Liquid 过滤器 以管道字符 (|) 开头,只能在变量字符串之后的 Liquid 变量 中使用。例如:relative_url 过滤器中的 {{ "css/main.css" | relative_url }}
  3. Markdown。Jekyll 使用配置文件中指定的 Markdown 过滤器将 Markdown 转换为 HTML。文件必须具有 Markdown 文件扩展名和页眉才能让 Jekyll 转换它们。

  4. 布局。Jekyll 将内容推送到页面页眉指定的布局中(或在配置文件中指定的布局中)。每个页面的内容被推送到布局中的 {{ content }} 标签中。

  5. 文件。Jekyll 将生成的内容写入 _site目录结构 中的文件。页面、文章和集合根据其 永久链接 设置进行结构化。以 _ 开头的目录(例如 _includes_data)通常在输出中隐藏。

错误配置导致问题的情况

在构建 Jekyll 网站时,您不必考虑解释顺序。只有在某些内容未呈现时,了解这些详细信息才变得重要。

以下情况重点介绍您可能遇到的潜在问题。这些问题源于对解释顺序的误解,可以轻松修复。

页面上的变量未呈现,因为该变量是在布局中分配的

假设在您的布局文件 (_layouts/default.html) 中,您分配了一个变量

{% assign myvar = "joe" %}

在使用该布局的页面上,您引用该变量

{{ myvar }}

该变量不会呈现,因为页面的解释顺序是先呈现 Liquid,然后处理布局。当 Liquid 呈现发生时,变量分配不可用。

要使代码正常工作,您可以将变量分配放入页面的页眉。

未处理包含文件中的 Markdown

假设您在 _includes/mycontent.md 中有一个 Markdown 文件。在 Markdown 文件中,您有一些 Markdown 格式

This is a list:
* first item
* second item

您将该文件包含在 HTML 文件中,如下所示

{% include mycontent.md %}

Markdown 未处理,因为首先处理 Liquid (include 标记),将 mycontent.md 插入 HTML 文件。然后 处理 Markdown。

但由于内容包含在HTML页面中,因此 Markdown 未呈现。Markdown 筛选器仅处理 Markdown 文件中的内容。

要使代码正常工作,请在插入 HTML 文件的包含中使用 HTML 格式。

请注意,highlight 标记不需要 Markdown 处理。假设您的包含包含以下内容

{% highlight javascript %}
console.log('alert');
{% endhighlight %}

highlight 标记 Liquid。(Liquid 将内容传递给 Rouge 以进行语法突出显示。)因此,此代码实际上将转换为具有语法突出显示的 HTML。Jekyll 不需要 Markdown 筛选器来处理 highlight 标记。

与 JavaScript 混合的 Liquid 未呈现

假设您尝试将 Liquid 的 assign 标记与 JavaScript 混合,如下所示

<button onclick="someFunction()">Click me</button>

<p id="intro"></p>

<script>
{% assign someContent = "This is some content" %}
function someFunction() {
    document.getElementById("intro").innerHTML = someContent;
}
</script>

这将不起作用,因为 assign 标记仅在网站的 Liquid 渲染阶段可用。在此 JavaScript 示例中,脚本在用户点击 HTML 页面上的按钮(“单击我”)时执行。那时,Liquid 逻辑不再可用,因此 assign 标记将不会返回任何内容。

但是,您可以使用 Jekyll 的网站变量或 Liquid 来填充稍后执行的脚本。例如,假设您在前置内容中具有以下属性: someContent: "This is some content"。您可以执行以下操作

<button onclick="someFunction()">Click me</button>

<p id="intro"></p>

<script>

function someFunction() {
    document.getElementById("intro").innerHTML = "{{ page.someContent }}";
}
</script>

当 Jekyll 构建网站时,此 someContent 属性会填充脚本的值,将 {{ page.someContent }} 转换为 "This is some content"

需要记住的关键是,当 Jekyll 构建您的网站时,Liquid 会进行渲染。当用户执行事件时,Liquid 在浏览器中不可在运行时使用。

关于在 YAML 中使用 Liquid 的注意事项

还有另一个需要记住的细节:当嵌入在 YAML 文件或前置内容中时,Liquid 不会渲染。(这与解释顺序无关,但值得一提,因为这是关于元素渲染的常见问题。)

例如,假设您在 _data/mydata.yml 文件中有一个 highlight 标记

myvalue: >
  {% highlight javascript %}
  console.log('alert');
  {% endhighlight %}

在页面上,您尝试插入值

{{ site.data.mydata.myvalue }}

这将仅渲染为一个字符串,而不是带有语法高亮的代码示例。若要使代码渲染,请考虑改用 include。