快轉到主要內容

基礎語法


計算和比較

Hugo 沒有 +< 這些符號,比較需用函式呼叫。

{{ add 1 1 }}
{{ sub 2 1 }}
{{ mul 2 2 }}
{{ div 4 2 }}
{{ eq 1 1 }}
{{ ne 1 2 }}
{{ lt 1 2 }}
{{ le 2 2 }}
{{ gt 3 2 }}
{{ ge 2 2 }}
2
1
4
2
true
true
true
true
true
true

if / else if / else

基本的 if-else 語法。false、空字串、0nil、空 slice、空字典都是 falsy value。

layouts/home.html
{{ $x := 7 }}
{{ if eq $x 6 }}
  eq 6
{{ else if eq $x 7 }}
  eq 7
{{ else }}
  ...
{{ end }}
eq 7

with / else with

if 只判斷條件,不改變上下文,with 判斷條件之外,還把上下文換成該值本身。

layouts/home.html
{{ $v1 := "" }}
{{ $v2 := "橘子" }}
{{ with $v1 }}
  {{ . }}
{{ else with $v2 }}
  {{ . }}
{{ else }}
  都不是
{{ end }}
橘子

and / or / not

邏輯判斷。

{{ and true false }}
{{ or true false }}
{{ not false }}
false
true
true

range

range 等同於 for loop,Hugo 只有 for loop 沒有 while loop。

layouts/home.html
{{ range slice "蘋果" "香蕉" "橘子" }}
  {{ . }}<br>
{{ end }}
蘋果<br>
香蕉<br>
橘子<br>

或是包含計數索引

layouts/home.html
{{ range $idx, $val := slice "蘋果" "香蕉" "橘子" }}
  {{ $idx }}: {{ $val }}<br>
{{ end }}
0: 蘋果<br>
1: 香蕉<br>
2: 橘子<br>

break / continue

continue 讓迴圈跳過該次循環,break 終止迴圈。

layouts/home.html
{{ range slice "蘋果" "香蕉" "橘子" }}
  {{ if eq . "香蕉" }}
    {{ continue }}
  {{ end }}
  {{ if eq . "橘子" }}
    {{ break }}
  {{ end }}
  {{ . }}
{{ end }}
蘋果

slice

slice 是一個列表,使用 index 取出元素,使用 len 取出長度。

{{ $s := slice 1 2 3 4 5 6 7 8 9 10 }}
{{ index $s 0 }}
{{ len $s }}
1
10

如要取範圍區間,可以使用 after/first 方式

{{ $s | first 5 | after 2 }}
[3 4 5]

seq

建立列表,seq N 產生 1N 的整數列表,seq A B 產生 AB

{{ range seq 3 }}{{ . }}{{ end }}
{{ range seq 2 5 }}{{ . }}{{ end }}
123
2345

dict

dict(map)是一個鍵值對(key-value pair),鍵可以用點語法直接取值,效果跟 index 相同。

{{ $person := dict "name" "John" "age" 20 }}
{{ index $person "name" }}
{{ $person.name }}
John
John

取用不存在的鍵不會報錯。

cast

變數型別轉換。

{{ $s := "42" }}
{{ $n := cast.ToInt $s }}
{{ add $n 8 }}
50

add "42" 8 會拋出型別錯誤,因為 add 要求兩個運算元都是數字,字串必須先用 cast.ToInt 轉型。

partial 與 return

partial 呼叫模板檔案。

語法

{{ partial LAYOUT CONTEXT }}

描述

partial 是獨立的模板檔案。用 partial 函式呼叫模板(LAYOUT)時,CONTEXT 會成為該檔案裡的 .

layouts/_partials/price-tag.html
{{ if lt . 100 }}
  <span>特價</span>
{{ else }}
  <span>原價</span>
{{ end }}
{{ partial "price-tag.html" 80 }}
<span>特價</span>

若模板中沒有 return,Hugo 會將模板渲染為 HTML。若有 return,Hugo 則回傳該值:

layouts/_partials/is-cheap.html
{{ return lt . 100 }}
{{ $cheap := partial "is-cheap.html" 80 }}
{{ print $cheap }}
true

v0.166.0 之前只支援一個 return

傳入多個值

partial 只接收一個 CONTEXT 參數。若需要同時傳入重量和城市,用 dict 將兩者包成一個值:

layouts/_partials/shipping-note.html
{{ if ge .weight 5 }}
  {{ .city }}:超重加收運費
{{ else }}
  {{ .city }}:一般運費
{{ end }}
{{ partial "shipping-note.html" (dict "weight" 6 "city" "TX") }}
TX:超重加收運費

.weight.city 對應呼叫時 dict 裡的鍵。

就地定義

define 可將 partial 直接寫在呼叫它的模板裡:

{{ partial "inline" 21 }}

{{ define "_partials/inline/double" }}
  {{ mul . 2 }}
{{ end }}
42

Hugo 在渲染前會先掃描所有可用模板,因此就地定義沒有先後順序的限制。就地定義的模板全站皆可呼叫。

模板間傳值

模板之間只能透過 {{ partial "foo.html" CONTEXT }} 傳遞的 CONTEXT 傳值,或是使用 .Store:用 .Store.Set 設定值,用 .Store.Get 取值。

partialCached 快取模板

partialCached 呼叫模板並快取其輸出結果。

語法

{{ partialCached LAYOUT CONTEXT [KEY1 KEY2 KEY3 ...] }}

描述

當 LAYOUT 的輸出結果重複,且渲染該模板已構成效能瓶頸時,可用 partialCached 取代 partial,將輸出結果快取起來,避免重複計算。

KEY1、KEY2、KEY3……為選填的額外快取鍵(cache key),用來讓同一個 LAYOUT 依不同條件產生多組快取結果。額外的快取鍵不參與模板本身的計算,僅作為區分快取結果之用;其數量可為零個或多個。

若未指定任何額外快取鍵,快取鍵即為 LAYOUT 本身(也就是該 partial 的名稱)。

平行渲染

Hugo 平行渲染多個頁面。第一次呼叫某個快取鍵時,Hugo 尚未完成該快取鍵的儲存,因此在此之前平行執行的其他頁面仍會各自重新渲染同一個模板。快取鍵儲存完成後,後續呼叫才會直接使用快取結果。

資訊

每個 site 的快取各自獨立。

.Store

前面介紹的都是函式 function,.Store 則是方法 method,方法是需要綁定在物件上的,因此可以看到有 . 存在。

.Store 用於將內容儲存在目標物件上,用於在模板間傳值。.Store 可以在以下幾個物件中被呼叫:

作用域使用方式
全站hugo.Store
當前站1SITE.Store
當前頁面PAGE.Store
短碼SHORTCODE.Store
區域變數collections.NewScratch

.Store 有順序關係,若呼叫 .Get 之前尚未呼叫過 .Store.Get 就沒有值。

.Store 內容的生命週期是整個程式週期,不會因為當前頁面渲染結束就被回收。

.Store 本身有眾多 method 可調用,所有 .Store 的方法都相同,只是 .Store 綁定的物件不同。

Example: 頁面初始化

若頁面有繁瑣的初始化,且多個模板都需要用到初始化後的結果,可以在 baseof.html 最前面初始化,並且以 .Page.Store 儲存,就能在每個 partial 模板取用 .Store 結果。

layouts/baseof.html
<!doctype html>
{{- partial "init.html" . -}}
<html>
  ...
</html>
layouts/_partials/init.html
{{- with resource.Get "..." -}}
  {{- ... -}}
  {{- .Page.Store.Set "key" ... -}}
{{- end -}}
layouts/_partials/foo.html
{{ with .Page.Store.Get "key" }}
  {{ ... }}
{{ end }}
layouts/_partials/bar.html
{{ with .Page.Store.Get "key" }}
  {{ ... }}
{{ end }}

Example: 呼叫計數

在同一個頁面中記錄 shortcode 被呼叫了多少次。

layouts/_shortcodes/figure.html
{{ $count := .Page.Store.Get "imageCounter" | default 0 }}
{{ $count = add $count 1 }}
{{ .Page.Store.Set "imageCounter" $count }}
<figure id="img-{{ $count }}">
  <img src="{{ .Get "src" }}" alt="{{ .Get "alt" }}">
</figure>

如果不需要計數,只需要查詢是否被呼叫,則可以用 .Page.HasShortcode 方法,此方法和 .Store 不同,沒有順序問題,因為 Hugo 會提前掃描一次 Markdown 文件,因此無須等到 shortcode 真的被渲染之後才使用 .Page.HasShortcode

Example: 資源載入

一個常見的範例是呼叫 .Page.Store.Set,在該頁面記錄某功能被呼叫,就可以在該呼叫之後使用 .Page.Store.Get 執行對應邏輯。經典的使用範例如官方文檔中的 Mermaid 圖表


  1. 當前站的意思請見 Sites Matrix 說明。 ↩︎

無障礙設定

字體大小