Zola教程:1-内容

2023-05-30

rust zola

简介

zola用目录来管理站点结构,content目录下是所有的内容,每个子目录是一个section,子目录下的.md文件就是section中的文章。section下的子目录也可以是一个页面,目录下的文件可能是页面包含的一些资源。

section目录下的_index.md文件可以定义一些section的元数据,也可以包含section列表的一些内容。每个page文件的头部也可以定义文件的元数据。这些元数据都遵循toml文件格式,称之为front-matter

资源文件

co-location

放置在section和page目录下的非md文件可以称为资源文件,在站点build的时候会一起被复制到站点内容目录下,页面可以通过相对路径来引用这些资源。

└── research
    ├── latest-experiment
    │   ├── index.md
    │   └── yavascript.js
    ├── _index.md
    └── research.jpg

我们来看上面的目录结构,页面需要引用的资源不能放到section下,但是可以把页面放到section的子目录下。例如,latest-experiment是一个页面,index.md是页面的内容,在页面中可以引用yavascript.js,而section的_index.md可以引用research.jpg,我们可以想象在section的列表页中显示一个图片。

忽略资源文件

可以在build的时候忽略某些文件,可以在站点的配置文件config.toml里加上以下内容:

ignored_content = ["code_articles/**/{Cargo.lock,target}, *.rs"] 

静态资源

我们来看一个例子:

└── content
    └── blog
        ├── configuration
        │    └── index.md // -> https://mywebsite.com/blog/configuration/
        └── _index.md // -> https://mywebsite.com/blog/

对于上面的目录结构,可以看到第一个index.md文件对应的url是https://mywebsite.com/blog/configuration,如果想给这个页面添加一些图片,你可以有三种选择:

  • 将图片放到content/blog/configuration目录下,在md文件里用相对路径引用,参考前面的co-location
  • 将图片放到static/blog/configuration目录下,在md文件里的引用方式跟co-location一样,区别是文件是放到static目录,而不是content目录,这个根据你的内容结构规划而定
  • 也可以将图片放到专门的目录,例如static/images,不过你就不能用相对路径去引用图片了,你需要用images/[filename]的方式去引用这些图片。这适用于小型的网站,或者某个图片被多个页面引用。

Section

概念

content目录下的子目录(不管哪一级),只要有_index.md,就会被当做一个section,如果目录里没有_index.md,目录中的md文件也会被生成页面,这种页面称为『孤儿』页面。

homepage是浏览你的站点的base_url时显示的页面,它也是一个section,通常位于content目录。如果content目录没有_index.md,那么这个主section就没有内容及元数据,如果你需要给主section增加内容和元数据,可以在content下添加一个_index.md文件,就像其他section那样。

section目录中的非markdown文件被称为资源文件,可以在md文件中以相对路径的方式引用,参见前面关于资源文件的介绍。

Front matter

Front matter字面上的意思是『目录』,section的_index.md文件头部可以添加Front matter来定义一些元数据,.md页面文件的头部也可以添加Front matter,其格式都是Toml,前后以三个加号(+++)区分,下面是一个例子:

+++
title = "List of blog posts"
sort\_by = "date"
template = "blog.html"
page\_template = "blog-page.html"
+++

可以看到,Front matter是以+++开始,并以+++结束。Front matter结束后是markdown格式的内容,在渲染section的时候会显示,模板里可以用section.content变量来引用。要注意的是即使没有元数据需要添加,文件头部开始和结束的两个+++也是必须的。

Zola推荐用Toml来定义Front matter,如果你比较喜欢Yaml,也可以用Yaml来定义Front matter,相应的+++需要改成---。

下面是section的Front matter可用的一些常见的变量及其默认值,如果没有说明,这些设置通常只适用于当前级的section,而不适用于子section:

title = ""

description = ""

# 如果section设置了draft=true,则在`zola build`, `zola serve` 及 `zola check`时指定`--drafts`参数,
# 这个section才会被生成。适用于子section
draft = false

# 页面排序方式,可用值有"date", "update_date", "title", "title_bytes", "weight", "slug" 及 "none"。
sort_by = "none"

# 由上一级section来对子section排序用,值越小优先级越高。
weight = 0

# 用于section渲染的模板
template = "section.html"

# 当前section下所有页面使用的模板,包含子目录。如果子目录有嵌套的模板设置,页面会使用离自己最近的设置。页面自己的模板变量优先级最高。
page_template =

# 分页时每页的页面数量,默认0表示不分页
paginate_by = 0

# 如果设置了,其值会加到分页url中,后面跟页面数字,例如page/1
paginate_path = "page"

# 是否倒序分页
paginate_reversed = false

# 是否给header添加链接,可选值有"left", "right", "heading" 及 "none",可以在`templates`目录下
# 创建`anchor-link.html`模板来覆盖配置。
insert_anchor_links = "none"

# 当前section是否被加入搜索索引,Zola配置文件中`build_search_index`=true时生效
in_search_index = true

# 为true时会生成section页面
render = true

# 如果section页面不存在,是否重定向到其他页面,例如"documentation/content/overview"
redirect_to =

# 如果是true,当前section的页面可以传给父section,例如多个按年划分的section,显示的时候需要拼在一起
transparent = false

# section的别名,是一个数组,当内容有移动又不想改变页面地址时有用
aliases = []

# 是否为section生成feed
generate_feed = false

# 自定义数据
[extra]

草稿

draft=true可以设置section为草稿,在zola构建的时候(build、serve、check),如果不指定--drafts,那么当前section及其子section都不会被生成。

分页

paginate_by设置成大于0的数字可以让当前section支持分页,默认的分页url为page/1,你可以修改paginate_path变量来更改url。

排序

模板中经常会通过遍历section的所有页面来生成列表,例如下面的代码片段:

{% for post in section.pages %}
 <h1><a href="{{ post.permalink }}">{{ post.title }}</a></h1>
{% endfor %}

上面的代码,for循环会依据section的sort_by字段来做排序,sort_by字段可用的值包括date, update_date, title, title_bytes, weight, slug及none。如果未指定sort_by,则不关心排序,结果顺序不可预知。

如果指定了sort_by,但是section的某些页面没有设置这个字段,那么这些页面不会被生成,在build的时候会产生警告。如果有多个页面的排序字段(date/weight/order)相同,会依据它们的永久链接的字母顺序做排序。

设置了sort_by之后,页面可以用变量page.lower和page.higher 来获取排序值小于或大于自身的页面列表。例如,对于date和update_date,能取到创建或更新时间早于或晚于当前页面的列表。title和slug字段的排序依据字符串的自然顺序,参考Rust的lexical-sort库的natural_lexical_cmp排序算子的说明。title_bytes 字段的排序依据字段内容的字节码,对于英文是ascii码,中文是对应的UTF-8编码。

如果设置paginate_reversed=true,所有的排序都会倒置。

对于section列表,只能使用weight字段进行排序。与page的排序不一样,如果section没有设置weight或者有相同的weight值,其顺序会随机。

Page

概念

Content目录下的.md文件称为页面(page),除了_index.md,这个文件名用于定义section的内容,页面不能使用这个文件名。

有两个特殊的md文件名,_index.md是section的内容,index.md会生成以目录为名字的页面,例如/content/about/index.md会生成页面[base_url]/about。除了这两个md文件名,其余的md文件会创建以文件名为名字的页面,例如在content根目录下有一个about.md,则会创建页面[base_url]/about。

对于md文件名规则还有一个例外,如果文件名是以日期开头,横杠(-)或下划线(_)将日期和文件名的剩余部分分隔,日期格式是YYYY-mm-dd 或者RFC3339日期格式,那么文件名中的日期部分将作为页面的创建时间,除非在页面的Front matter中设置了创建时间,文件名除了日期的剩余部分将作为页面的名字。例如文件2018-10-10-hello-world.md,其页面地址是[base_url]/hello-world,页面的日期是2018-10-10。如果config中设置slugify.paths_keep_dates=true,则会将这个特性关闭,文件名中的日期不会做特殊处理。

安装上面的规则,文件about.md与about/index.md效果是一样的,都会生成页面about,区别是使用目录about可以让你把页面需要的资源放在同一个目录下,便于管理。

Path

页面的path规则有两种选择:

  • Front matter中的slug
  • 文件名

不管哪种情况,生成的path都会被检查,以去除可能产生问题的部分。如果config中的slugify.paths设置为on(默认设置),path会被『净化』(slugified),如果slugify.paths设置为safe,则只会处理某些字符,会移除<、>、:、/、|、?、*、#、\、(、)、[、]、回车、TAB这些字符,结尾的空格也会被移除,中间的空格会被替换成_(下划线)。如果slugify.paths设置成off,则path不做任何处理。如果需要在path中包含非ASCII字符,则需要将slugify.paths设置成safe或off。

  • 从Front matter中的slug字段读取path

页面的path首先会从页面的Front matter中的slug字段读取,例如文件content/zines/élevage-chèvre.md的内容如下:

+++
title = "L'élevage de chèvres, la carrière alternative de tous dévelopeurs'"
slug = "élevage-chèvre-carrière-alternative"
+++
This is my article.

如果slugify.paths设置成safe或off,则页面的path为[base_url]/zines/élevage-chèvre-carrière-alternative,如果slugify.paths设置成on,页面的path为[base_url]/zines/elevage-chevre-carriere-alternative。

  • 从文件名生成path

如果页面的Front matter中没有设置slug,path则会从文件的路径生成。例如对于文件content/foo/bar/thing.md,path是这样构造的:

  • 如果文件名是index.md,其父目录bar会作为path
  • 否则path会从thing(去掉.md的文件名)提取

如果文件名包含日期(YYYY-mm-dd或者 RFC3339日期格式 ),日期部分不会包含在path中,会作为页面的date字段(除非页面的Front matter设置了date字段)。然后生成的path会根据slugify.paths设置决定是否做slugfied。

例如,文件名content/blog/2018-10-10-hello-world.md生成的path为[base_url]/blog/hello-world,带有空格的文件名content/blog/2021-01-23 -hello new world.md生成的path为[base_url]/blog/hello-new-world。

Front matter

页面的Front matter格式跟section的一样,都支持toml(+++分隔)或yaml(---分隔),下面是页面的Front matter中常用的变量及默认值:

title = ""
description = ""

# 页面的日期,格式为YYYY-MM-DD (2012-10-02) 或 RFC3339 (2002-10-02T15:00:00Z).
date =

# 页面更新时间
updated =

# 如果section的sort_by=weight,则按这个字段排序
weight = 0

# 是否草稿,设置成true时,必须指定`--drafts`参数才能在`zola build`, `zola serve` 或 `zola check`时生成这个页面
draft = false

# 如果设置,页面的path由这个字段生成,否则会从文件名提取
slug = ""

# 页面的path,会覆盖slug和文件名,不能以/开头
path = ""

# 别名,当内容移动又不想改变path时起作用
aliases = []

# 页面作者列表,如果section设置了生成feed,第一个作者会在列表中显示
authors = []

# config中如果设置了`build_search_index`=true,并且section没有屏蔽搜索索引设置,当前页面会被加入搜索索引中
in_search_index = true

# 页面渲染的模板文件
template = "page.html"

# 页面分类,名字必须与`config.toml`文件中的设置一致。例如:
# tags = ["rust", "web"].
[taxonomies]

# 自定义设置
[extra]

摘要

页面的.md文件中添加可以实现摘要的功能,在这个标记之前的内容都是页面的摘要,在模板中可以通过page.summary来引用摘要。

生成的页面中相应的位置会有一个id为continue-reading的span元素,你可以直接使用它,例如Continue Reading