TEMPLATES FUNDAMENTALS

Introduction to templating

模板是專案、主題或模組中 layouts 目錄中的檔案。模板使用變數函式方法來將你的內容、資源與資料轉換成發佈的頁面。

例如,這個 HTML 模板初始化了 $v1$v2 變數,然後在 HTML 段落中顯示它們以及它們的乘積。

{{ $v1 := 6 }}
{{ $v2 := 7 }}
<p>{{ $v1 }}{{ $v2 }} 的乘積是 {{ mul $v1 $v2 }}。</p>

雖然 HTML 模板是最常見的,你也可以為任何輸出格式創建模板,包括 CSV、JSON、RSS 和純文字。

上下文

在創建模板之前,最重要的概念是 上下文,也就是傳遞給每個模板的資料。這些資料可以是簡單的值,或更常見的物件及相關的方法

例如,單一頁面的模板會接收到一個 Page 物件,而這個 Page 物件提供方法來返回值或執行動作。

當前上下文

在模板中,點(.)代表當前的上下文。

layouts/_default/single.html
<h2>{{ .Title }}</h2>

在上面的例子中,點代表 Page 物件,我們調用它的 Title 方法來返回在front matter中定義的標題。

當前的上下文可能會在模板中改變。例如,在模板的開頭,上下文可能是一個 Page 物件,但我們可以在 rangewith 區塊中將上下文重新綁定為另一個值或物件。

layouts/_default/single.html
<h2>{{ .Title }}</h2>

{{ range slice "foo" "bar" }}
  <p>{{ . }}</p>
{{ end }}

{{ with "baz" }}
  <p>{{ . }}</p>
{{ end }}

在這個例子中,上下文在我們使用 range 遍歷[切片]時改變。在第一次迭代時,上下文是 “foo”,在第二次迭代時,上下文是 “bar”。在 with 區塊內,上下文是 “baz”。Hugo 會渲染出以下內容:

<h2>我的頁面標題</h2>
<p>foo</p>
<p>bar</p>
<p>baz</p>

模板上下文

rangewith 區塊內,你可以通過在點前加上美元符號($)來訪問傳遞給模板的上下文:

layouts/_default/single.html
{{ with "foo" }}
  <p>{{ $.Title }} - {{ . }}</p>
{{ end }}

Hugo 會渲染這段程式碼為:

<p>我的頁面標題 - foo</p>

動作

在上述例子中,成對的開括號和閉括號代表模板動作的開始與結束,這是一種資料評估或控制結構。

模板動作可以包含字面值(布林值字串整數、和浮點數)、變數、函式和方法。

layouts/_default/single.html
{{ $convertToLower := true }}
{{ if $convertToLower }}
  <h2>{{ strings.ToLower .Title }}</h2>
{{ end }}

在上面的例子中:

  • $convertToLower 是一個變數
  • true 是一個字面布林值
  • strings.ToLower 是一個將所有字符轉換為小寫的函式
  • TitlePage 物件上的方法

Hugo 會將上面的程式碼渲染為:

<h2>我的頁面標題</h2>

Whitespace

Notice the blank lines and indentation in the previous example? Although irrelevant in production when you typically minify the output, you can remove the adjacent whitespace by using template action delimiters with hyphens:

layouts/_default/single.html
{{- $convertToLower := true -}}
{{- if $convertToLower -}}
  <h2>{{ strings.ToLower .Title }}</h2>
{{- end -}}

Hugo renders this to:

<h2>my page title</h2>

Whitespace includes spaces, horizontal tabs, carriage returns, and newlines.

Pipes

Within a template action you may pipe a value to a function or method. The piped value becomes the final argument to the function or method. For example, these are equivalent:

{{ strings.ToLower "Hugo" }} → hugo
{{ "Hugo" | strings.ToLower }} → hugo

You can pipe the result of one function or method into another. For example, these are equivalent:

{{ strings.TrimSuffix "o" (strings.ToLower "Hugo") }} → hug
{{ "Hugo" | strings.ToLower | strings.TrimSuffix "o" }} → hug

These are also equivalent:

{{ mul 6 (add 2 5) }} → 42
{{ 5 | add 2 | mul 6 }} → 42

Line splitting

You can split a template action over two or more lines. For example, these are equivalent:

{{ $v := or $arg1 $arg2 }}

{{ $v := or 
  $arg1
  $arg2
}}

You can also split raw string literals over two or more lines. For example, these are equivalent:

{{ $msg := "This is line one.\nThis is line two." }}

{{ $msg := `This is line one.
This is line two.`
}}

Variables

A variable is a user-defined identifier prepended with a dollar sign ($), representing a value of any data type, initialized or assigned within a template action. For example, $foo and $bar are variables.

Variables may contain scalars, slices, maps, or objects.

Use := to initialize a variable, and use = to assign a value to a variable that has been previously initialized. For example:

{{ $total := 3 }}
{{ range slice 7 11 21 }}
  {{ $total = add $total . }}
{{ end }}
{{ $total }} → 42

Variables initialized inside of an if, range, or with block are scoped to the block. Variables initialized outside of these blocks are scoped to the template.

With variables that represent a slice or map, use the index function to return the desired value.

{{ $slice := slice "foo" "bar" "baz" }}
{{ index $slice 2 }} → baz

{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }}
{{ index $map "c" }} → baz

With variables that represent a map or object, chain identifiers to return the desired value or to access the desired method.

{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }}
{{ $map.c }} → baz

{{ $homePage := .Site.Home }}
{{ $homePage.Title }} → My Homepage

Functions

Used within a template action, a function takes one or more arguments and returns a value. Unlike methods, functions are not associated with an object.

Go’s text/template and html/template packages provide a small set of functions, operators, and statements for general use. See the go-templates section of the function documentation for details.

Hugo provides hundreds of custom functions categorized by namespace. For example, the strings namespace includes these and other functions:

Function Alias
strings.ToLower lower
strings.ToUpper upper
strings.Replace replace

As shown above, frequently used functions have an alias. Use aliases in your templates to reduce code length.

When calling a function, separate the arguments from the function, and from each other, with a space. For example:

{{ $total := add 1 2 3 4 }}

Methods

Used within a template action and associated with an object, a method takes zero or more arguments and either returns a value or performs an action.

The most commonly accessed objects are the Page and Site objects. This is a small sampling of the methods available to each object.

Object Method Description
Page Date Returns the date of the given page.
Page Params Returns a map of custom parameters as defined in the front matter of the given page.
Page Title Returns the title of the given page.
Site Data Returns a data structure composed from the files in the data directory.
Site Params Returns a map of custom parameters as defined in the site configuration.
Site Title Returns the title as defined in the site configuration.

Chain the method to its object with a dot (.) as shown below, remembering that the leading dot represents the current context.

layouts/_default/single.html
{{ .Site.Title }} → My Site Title
{{ .Page.Title }} → My Page Title

The context passed into most templates is a Page object, so this is equivalent to the previous example:

layouts/_default/single.html
{{ .Site.Title }} → My Site Title
{{ .Title }} → My Page Title

Some methods take an argument. Separate the argument from the method with a space. For example:

layouts/_default/single.html
{{ $page := .Page.GetPage "/books/les-miserables" }}
{{ $page.Title }} → Les Misérables

Comments

Template comments are similar to template actions. Paired opening and closing braces represent the beginning and end of a comment. For example:

{{/* This is an inline comment. */}}
{{- /* This is an inline comment with adjacent whitespace removed. */ -}}

Code within a comment is not parsed, executed, or displayed. Comments may be inline, as shown above, or in block form:

{{/*
This is a block comment.
*/}}

{{- /*
This is a block comment with
adjacent whitespace removed.
*/ -}}

You may not nest one comment inside of another.

To render an HTML comment, pass a string through the safeHTML template function. For example:

{{ "<!-- I am an HTML comment. -->" | safeHTML }}
{{ printf "<!-- This is the %s site. -->" .Site.Title | safeHTML }}

Include

Use the template function to include one or more of Hugo’s embedded templates:

{{ template "_internal/google_analytics.html" . }}
{{ template "_internal/opengraph" . }}
{{ template "_internal/pagination.html" . }}
{{ template "_internal/schema.html" . }}
{{ template "_internal/twitter_cards.html" . }}

Use the partial or partialCached function to include one or more partial templates:

{{ partial "breadcrumbs.html" . }}
{{ partialCached "css.html" . }}

Create your partial templates in the layouts/partials directory.

Examples

This limited set of contrived examples demonstrates some of concepts described above. Please see the functions, methods, and templates documentation for specific examples.

Conditional blocks

See documentation for if, else, and end.

{{ $var := 42 }}
{{ if eq $var 6 }}
  {{ print "var is 6" }}
{{ else if eq $var 7 }}
  {{ print "var is 7" }}
{{ else if eq $var 42 }}
  {{ print "var is 42" }}
{{ else }}
  {{ print "var is something else" }}
{{ end }}

Logical operators

See documentation for and and or.

{{ $v1 := true }}
{{ $v2 := false }}
{{ $v3 := false }}
{{ $result := false }}

{{ if and $v1 $v2 $v3 }}
  {{ $result = true }}
{{ end }}
{{ $result }} → false

{{ if or $v1 $v2 $v3 }}
  {{ $result = true }}
{{ end }}
{{ $result }} → true

Loops

See documentation for range, else, and end.

{{ $s := slice "foo" "bar" "baz" }}
{{ range $s }}
  <p>{{ . }}</p>
{{ else }}
  <p>The collection is empty</p>
{{ end }}

Use the seq function to loop a specified number of times:

{{ $total := 0 }}
{{ range seq 4 }}
  {{ $total = add $total . }}
{{ end }}
{{ $total }} → 10

Rebind context

See documentation for with, else, and end.

{{ $var := "foo" }}
{{ with $var }}
  {{ . }} → foo
{{ else }}
  {{ print "var is falsy" }}
{{ end }}

To test multiple conditions:

{{ $v1 := 0 }}
{{ $v2 := 42 }}
{{ with $v1 }}
  {{ . }}
{{ else with $v2 }}
  {{ . }} → 42
{{ else }}
  {{ print "v1 and v2 are falsy" }}
{{ end }}

Access site parameters

See documentation for the Params method on a Site object.

With this site configuration:

hugo.
     
baseURL: https://example.org
params:
  author:
    email: jsmith@example.org
    name: John Smith
  copyright-year: "2023"
  layouts:
    rfc_1123: Mon, 02 Jan 2006 15:04:05 MST
    rfc_3339: "2006-01-02T15:04:05-07:00"
  subtitle: The Best Widgets on Earth
title: ABC Widgets
baseURL = 'https://example.org'
title = 'ABC Widgets'
[params]
  copyright-year = '2023'
  subtitle = 'The Best Widgets on Earth'
  [params.author]
    email = 'jsmith@example.org'
    name = 'John Smith'
  [params.layouts]
    rfc_1123 = 'Mon, 02 Jan 2006 15:04:05 MST'
    rfc_3339 = '2006-01-02T15:04:05-07:00'
{
   "baseURL": "https://example.org",
   "params": {
      "author": {
         "email": "jsmith@example.org",
         "name": "John Smith"
      },
      "copyright-year": "2023",
      "layouts": {
         "rfc_1123": "Mon, 02 Jan 2006 15:04:05 MST",
         "rfc_3339": "2006-01-02T15:04:05-07:00"
      },
      "subtitle": "The Best Widgets on Earth"
   },
   "title": "ABC Widgets"
}

Access the custom site parameters by chaining the identifiers:

{{ .Site.Params.subtitle }} → The Best Widgets on Earth
{{ .Site.Params.author.name }} → John Smith

{{ $layout := .Site.Params.layouts.rfc_1123 }}
{{ .Site.Lastmod.Format $layout }} → Tue, 17 Oct 2023 13:21:02 PDT

Access page parameters

See documentation for the Params method on a Page object.

With this front matter:

content/news/annual-conference.md.
     
date: 2023-10-17T15:11:37-07:00
params:
  author:
    email: jsmith@example.org
    name: John Smith
  display_related: true
title: Annual conference
date = 2023-10-17T15:11:37-07:00
title = 'Annual conference'
[params]
  display_related = true
  [params.author]
    email = 'jsmith@example.org'
    name = 'John Smith'
{
   "date": "2023-10-17T15:11:37-07:00",
   "params": {
      "author": {
         "email": "jsmith@example.org",
         "name": "John Smith"
      },
      "display_related": true
   },
   "title": "Annual conference"
}

Access the custom page parameters by chaining the identifiers:

{{ .Params.display_related }} → true
{{ .Params.author.name }} → John Smith