解釋順序

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 檔案中的 include 中使用 HTML 格式。

請注意,highlight 標籤不需要 Markdown 處理。假設你的 include 包含以下內容

{% 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"

要記住的重點是,Liquid 會在 Jekyll 建置你的網站時轉譯。當使用者執行事件時,Liquid 在瀏覽器的執行階段中不可用。

關於在 YAML 中使用 Liquid 的注意事項

還有一項細節需要記住:當嵌入 YAML 檔案或前置事項時,Liquid 無法呈現。(這與解譯順序無關,但由於這是關於元素呈現的常見問題,因此值得一提。)

例如,假設你在 _data/mydata.yml 檔案中有一個 highlight 標籤

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

在一個頁面上,你嘗試插入值

{{ site.data.mydata.myvalue }}

這只會呈現為字串,而不是具有語法突顯的程式碼範例。若要讓程式碼呈現,請考慮改用 include。