配置

三种配置。一个是config页面的全局配置,一个是每篇文章头的单页配置。格式接受toml,yaml,json。

文章头配置的part有名字,叫front matter。

还有一个是archetypes/文件夹,设置.md文章的样式,尤其是头部front matter的样式。

结构

hugo结构有两个概念,模版和页面,模版就是html,页面就是文档.md,这两者是一一对应的。

页面内容存在content/中,在此写出内容,通过存在layout/下的默认或指定模版,渲染成最终展示在浏览器的页面,存在public/中。

类型,英文名kind。又分模版类型,和页面类型。

模版

模版,通常有通用的样式,也可以单独定制,就是写前端代码的意思。写的html模版都存在layout/文件夹里。

layout/_default/文件夹存基础的、一类的页面模版。

其中的layout/_default/baseof.html 定义页面最基本结构。

模版类型

hugo将模版分成两种类型,一种是正常的文章单页,叫signal.html,一种是文章的集合页,好比归档、首页,不展示文章内容,叫list.html。相当于定义世界,需要物品本身,和装物品的框。

此外还有一个特殊的单页,首页,叫home。

layout/_default/signal.html 就定义了单页的结构,将来渲染每一篇博文。layout/_default/list.html定义了文章集合页的结构,将来渲染归档列表页,只要没单独设置,list.html 的渲染范围还包括tags、pages、tags集合下每个tag的页面,因为它们都是一个“类”,装此类文章的框。

当然也可以指定渲染模版。比如想开一页,全是图片的,图片.md,可以单独写个模版,比如叫layout/partials/image.html,在图片.md的头部注释处可以设置 layout: layout/partials/image.html,以后渲染图片.md页面就指定用这个模版。

如何识别哪个页面是单页用signal,哪个是集合用list渲染呢,带_index.md的(文件夹页)就是集合,不带的文件夹下的每篇文章就是单页。

term模版

在list.html和term.html都存在的基础上,**kind为taxonomy类型的才会用term.html渲染,比如总tags页,而类型为term(即具体莫哥tag)和section的都会用list.html渲染。

页面

页面就是写的文章,存在content/中,要配合类型说。

页面类型

页面类型可以用 {{ .Kind }} 查看,kind类型有:home, page, section, taxonomy, taxonomyTerm, RSS, sitemap, robotsTXT 以及 404。

后面的先不看,第一个就唯一页面,也不看。page,就是正常的单页面,section是自己定义的按模块的list类型页面(框),taxonomy是按标签、系列、话题等方式分类的list类型页面(框)。

taxonomy是属性,这种分类方式的名字,它的值统称做term,具体可能有tags、category这些分类。

如何生成section,有两种方式。1是content的一级目录,都是section,2是带 _index.md的文件夹,则为section。

如何生成taxonomy,定义在config中,可以自己指定。

[taxonomies]
  tag = "tags"
  series = "series"
  category = "categories"
  year = "years"

分级是 taxonomy(类)— [ tags, series 等项目] — [ css,redis 等值]

具体讲,即,基础知识是一个tag,它的kind是term,type是tags;而tags是一个种类,它的kind是taxonomy,type是tags。

相应的页面分配,点开基础知识这个tag,默认通用模版是baseof/list.html(即便有baseof/term.html),它的url是 域名/tags/基础知识;点开tags这个大类,如有term.html则用,如果没有就用list.html,它的url是 域名/tags

此外,进入content/,有posts文件夹,当posts/有_index.md(注意带 _ )时,posts本身(而不是它里面的单篇文章)的kind成为section,type为posts,它的url(被我在 _index.md 的头部设置了 url: archive重定向了)为域名/archive(没有懂为什么在menu处设置没用,非要在 _index.md 头部改)。

带 _index.md的文件夹里(即 一个section下)的正常文章,type为此文件夹名字(即section名),kind为page。比如content/posts/试试就试试.md的url默认为content/posts/mytitle,mytitle为 _index.md头部设定的title。当然也可以自定义,like:

[permalinks]
  posts = "/posts/:slugorfilename"

如果文件夹下不带 _index.md,比如content/posts/建站记/index.md,则此时建站记的type则为posts,kind不为section而是page,即index.md 为此文件夹同名正常文件,而建站记/下其它文章都不是正常文章,消失了。

此特性可以用来存.jpg,即将文章变成同名文件夹,正文放index.md,旁边放点此文配图,方便归档。

各种分类的区别

section我理解的意思,比按tag分类大,相当于,想开发不同的大类,不一定是文章,比如搜集书影音,新闻?之类别的大类的东西,也需要写字和页面,或者在文章中分为技术/非技术,就这两大类,而分出的东西。type意思就是某一个section名字。每个section有单独的url分支。

.kind是页面展现的类型,单页,还是列表集合,还是tags分类。

.Type 是当前页所属 Section

简单看了一下douban和bilibili的设置。只有很大类才set进path里。比如豆瓣单栏有group/,相当于一个section,各个组首页为 group/topic/组名,相当于一个子section。但各个组都不会在组名后面拼贴帖子id,而是越过组名,直接统一设为group/topic/帖子id。而和topic并列的是explore,探索页。b站也是一样,所有视频都在video下,不分各个区。这里各个区,各个组有点按taxonomy分的意思。

这样做的好处是只要知道帖子/视频id就可以搜到内容,不用知道它在哪个组、哪个区。

路由和url设置

定义

  • baseURL:
    在config首段设置的路径。默认为/, 一般设为服务器地址,比如要用github page架博客,就设为baseURL = "https://<your github name>.github.io/"

然后开发的时候,默认就是去掉baseURL后开始的。
也可以用相对路径。

  • permalinks:
    config里的 [permalinks]可以动态配置每个页面的路径。
    参数有 section、title、slug。

  • url:
    单页头部注释的url,指除baseURL以外的path

  • aliases:
    aliases:[‘a’, ‘b’] 可以把链接a重定向为链接b。

各名词关系

url = section + slug

permalink = baseurl + url = baseurl + section + slug

                               url ("/posts/my-first-hugo-post/")
                   ⊢------------^----------⊣
       baseurl     section     slug
⊢--------^--------⊣⊢-^--⊣⊢-------^---------⊣
                 permalink
⊢--------------------^---------------------⊣
https://example.com/posts/my-first-hugo-post/index.html

* config设置permalink中动态的section是动态的,比如有很深的section文件夹嵌套,设一个就可以展示全部

* slug默认为title,具体输出可以在archetypes里设置

疑惑点

hugo有一些默认设置:

  • 直接的css、js默认路径就是static,所以在html的head定义的时候,路径可以直接省略static名字,从static内开始。
  • 默认压缩路径为assets,所以想用管道,或者用ts、scss写路径同样可以省略assets,从assets内开始。
  • hugo识别路径挺智能的,末尾有没有/都可以识别

Go Template

变量

组合按层的,全站变量为.Site,当前页为.Pages,所以全部页就是.Site.Pages。

下面就只介绍单级的,要变成全站就自动加.Site在前面

.Pages 是指所有类型的页面,包括列表页,tags,这种

.RegularPages (当前section的)正常页面,是指所有单页,即kind=page,不包括列表页

.RegularPagesRecursive 所有section的正常单页,包括它descendant的section里的单页。

.Paginator.Pages 分页器组织下的页,如果使用这个变量,就会翻页,即便不设置翻页间隔,也会默认按10条一翻页。

之前首页和归档页用的遍历代码

/*此选择器意思是,设定type为文件夹名字。因为之前把posts/改成了blog/ */
{{- $paginator := .Paginate (where .Site.RegularPages "Type" $.Site.Params.folder) }} 
{{- range $page := $paginator.Pages }}
内容
{{ end }} {{ end }}

.Section 当前内容属于的section。如果是一个nested sections(即嵌套的多层),这个值会是第一层path,posts下面的section里的文章的section会始终是posts

link: Permalink = BaseURL + RelPermalink

找了一下没有 nested section 多层section下,子section的定义方法,只能拿.CurrentSection.RelPermalink

注释

  1. Go 注释 {{/* {{ add 0 + 2 }} */}}
  2. HTML 注释 {{ “” | safeHTML }}

注意:Hugo 首先加载的 Go 代码,然后渲染 HTML

如果HTML注释包含了 Go 模板代码,可能导致构建失败

参数

可以使用两种参数:

  1. 页面参数,这是定义在 头部注释 里的
  2. 全局参数,这是定义在 站点配置 params 里的

具体页面的头部注释,只能写死,不能写函数。本来想动态将title关联至文件夹名,起名废就不用不停改名字还要改两次了。但是不能写成动态的。

全局 & 单页参数调用

之前疑问,如果在全局定义了参数,在单页又覆盖,怎么调用怎么区分?

  • 全局和单页变量似乎不相干,不是复制关系,调用的代码也不同。
  • 全局没定义的参数,单页前面可以直接定义。调用的时候用{{ .Params.myValue }}。多层的我还没研究。这时候单页没设置的此参数不存在,但可以用{{ if .Params.myValue }}判断。
  • 全局定义参数,只能放在[params]下面,其它地方不能自己初始化参数。调用全局参数用{{ .Site.Params.myValue }}

高级功能

见下一篇

链接

Hugo 静态网站建站手册

lucide

hugo的toc

Hugo添加文章目录toc

官网 模版选择顺序

Hugo博客添加自动编号

雨临Lewis