内容适配器
概述
内容适配器是一个模板,它在构建站点时动态创建页面。例如,使用内容适配器从远程数据源(如 JSON、TOML、YAML 或 XML)创建页面。
与位于 layouts
目录中的模板不同,内容适配器位于 content
目录中,每个语言的每个目录最多一个。当内容适配器创建页面时,页面的逻辑路径将相对于该内容适配器。
content/
├── articles/
│ ├── _index.md
│ ├── article-1.md
│ └── article-2.md
├── books/
│ ├── _content.gotmpl <-- content adapter
│ └── _index.md
└── films/
├── _content.gotmpl <-- content adapter
└── _index.md
每个内容适配器都命名为 _content.gotmpl,并使用与 layouts
目录中的模板相同的语法。您可以在内容适配器中使用任何模板函数,以及下面描述的方法。
方法
在内容适配器中使用这些方法。
AddPage
向站点添加页面。
{{ $content := dict
"mediaType" "text/markdown"
"value" "The _Hunchback of Notre Dame_ was written by Victor Hugo."
}}
{{ $page := dict
"content" $content
"kind" "page"
"path" "the-hunchback-of-notre-dame"
"title" "The Hunchback of Notre Dame"
}}
{{ .AddPage $page }}
AddResource
向站点添加页面资源。
{{ with resources.Get "images/a.jpg" }}
{{ $content := dict
"mediaType" .MediaType.Type
"value" .
}}
{{ $resource := dict
"content" $content
"path" "the-hunchback-of-notre-dame/cover.jpg"
}}
{{ $.AddResource $resource }}
{{ end }}
然后使用如下方法检索新页面资源
{{ with .Resources.Get "cover.jpg" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
Site
返回将向其中添加页面的 Site
。
{{ .Site.Title }}
Store
返回一个持久的“暂存区”,用于存储和操作数据。它的主要用例是在设置 EnableAllLanguages 时在执行之间传输值。请参阅示例。
{{ .Store.Set "key" "value" }}
{{ .Store.Get "key" }}
EnableAllLanguages
默认情况下,Hugo 为 _content.gotmpl 文件定义的语言执行内容适配器。使用此方法激活所有语言的内容适配器。
{{ .EnableAllLanguages }}
{{ $content := dict
"mediaType" "text/markdown"
"value" "The _Hunchback of Notre Dame_ was written by Victor Hugo."
}}
{{ $page := dict
"content" $content
"kind" "page"
"path" "the-hunchback-of-notre-dame"
"title" "The Hunchback of Notre Dame"
}}
{{ .AddPage $page }}
页面映射
在传递给 AddPage
方法的映射中设置任何前言字段,但不包括 markup
。 不要设置 markup
字段,而是按如下所述指定 content.mediaType
。
下表描述了最常传递给 AddPage
方法的字段。
键 | 描述 | 必需 |
---|---|---|
content.mediaType |
内容媒体类型。默认为 text/markdown 。有关示例,请参阅内容格式。 |
|
content.value |
内容值,为字符串。 | |
dates.date |
页面创建日期,为 time.Time 值。 |
|
dates.expiryDate |
页面过期日期,为 time.Time 值。 |
|
dates.lastmod |
页面上次修改日期,为 time.Time 值。 |
|
dates.publishDate |
页面发布日期,为 time.Time 值。 |
|
kind |
页面类型。默认为 page 。 |
|
params |
页面参数的映射。 | |
path |
相对于内容适配器的页面的逻辑路径。 不要包含前导斜杠或文件扩展名。 | ✔️ |
title |
页面标题。 |
资源映射
使用以下字段构建传递给 AddResource
方法的映射。
键 | 描述 | 必需 |
---|---|---|
content.mediaType |
内容的 媒体类型。 | ✔️ |
content.value |
作为字符串或资源的内容值。 | ✔️ |
name |
资源名称。 | |
params |
资源参数的映射。 | |
path |
资源相对于内容适配器的逻辑路径。不要包含前导斜杠。 | ✔️ |
title |
资源标题。 |
示例
从远程数据创建页面,其中每个页面代表一本书评。
- 步骤 1
- 创建内容结构。
content/
└── books/
├── _content.gotmpl <-- content adapter
└── _index.md
- 步骤 2
- 检查远程数据,以确定如何将键值对映射到 front matter 字段。
- 步骤 3
- 创建内容适配器。
{{/* Get remote data. */}}
{{ $data := dict }}
{{ $url := "https://gohugo.com.cn/shared/examples/data/books.json" }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $data = . | transform.Unmarshal }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
{{ end }}
{{/* Add pages and page resources. */}}
{{ range $data }}
{{/* Add page. */}}
{{ $content := dict "mediaType" "text/markdown" "value" .summary }}
{{ $dates := dict "date" (time.AsTime .date) }}
{{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }}
{{ $page := dict
"content" $content
"dates" $dates
"kind" "page"
"params" $params
"path" .title
"title" .title
}}
{{ $.AddPage $page }}
{{/* Add page resource. */}}
{{ $item := . }}
{{ with $url := $item.cover }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
{{ $params := dict "alt" $item.title }}
{{ $resource := dict
"content" $content
"params" $params
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
}}
{{ $.AddResource $resource }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
- 步骤 4
- 创建单个模板以呈现每个书评。
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ with .Resources.GetMatch "cover.*" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}">
{{ end }}
<p>Author: {{ .Params.author }}</p>
<p>
ISBN: {{ .Params.isbn }}<br>
Rating: {{ .Params.rating }}<br>
Review date: {{ .Date | time.Format ":date_long" }}
</p>
{{ with .GetTerms "tags" }}
<p>Tags:</p>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }}
{{ .Content }}
{{ end }}
多语言站点
对于多语言站点,您可以
- 使用
EnableAllLanguages
方法,如上所述,为所有语言创建一个内容适配器。 - 创建每个语言唯一的内容适配器。请参阅以下示例。
按文件名翻译
使用此站点配置
languages:
de:
weight: 2
en:
weight: 1
[languages]
[languages.de]
weight = 2
[languages.en]
weight = 1
{
"languages": {
"de": {
"weight": 2
},
"en": {
"weight": 1
}
}
}
在内容适配器的文件名中包含语言指示符。
content/
└── books/
├── _content.de.gotmpl
├── _content.en.gotmpl
├── _index.de.md
└── _index.en.md
按内容目录翻译
使用此站点配置
languages:
de:
contentDir: content/de
weight: 2
en:
contentDir: content/en
weight: 1
[languages]
[languages.de]
contentDir = 'content/de'
weight = 2
[languages.en]
contentDir = 'content/en'
weight = 1
{
"languages": {
"de": {
"contentDir": "content/de",
"weight": 2
},
"en": {
"contentDir": "content/en",
"weight": 1
}
}
}
在每个目录中创建一个内容适配器
content/
├── de/
│ └── books/
│ ├── _content.gotmpl
│ └── _index.md
└── en/
└── books/
├── _content.gotmpl
└── _index.md
页面冲突
当两个或多个页面具有相同的发布路径时,它们会发生冲突。由于并发性,已发布页面的内容是不确定的。考虑以下示例
content/
└── books/
├── _content.gotmpl <-- content adapter
├── _index.md
└── the-hunchback-of-notre-dame.md
如果内容适配器也创建了 books/the-hunchback-of-notre-dame,则已发布页面的内容是不确定的。您无法定义处理顺序。
要检测页面冲突,请在构建站点时使用 --printPathWarnings
标志。