Hugo 在非相关页面调用特定分类或标签下的文章

【注:本文最终要实现的是在任意页面或者非相关页面调用某个 taxonomy 下的文章】

【具体到例子,下面都是以在任意页面调用 Web 分类下的 2 篇文章为例

{{ range first 2 (where .Site.RegularPages ".Params.categories" "intersect" (slice "Web")) }}

================= 上面是可行的调用方法,下面是说明 =================

【说明:】要想实现分类目录显示,在 WordPress 或者其他的 CMS 都很容易,但是对于 Hugo 这样的静态网站来说,可有点 tricky,虽然,Hugo 自带 taxonomy 列表,但是有时我们实际需要的是在任意页面或者非相关页面(我自创的一个词,也就是除了自带的 taxonomy 列表页之外的页面)调用想要的 taxonomy 下的文章。

其实,如果对 Hugo template 熟悉的话,应该非常容易就能想出来,应该是类似于下面这几种:

{{ range first 2 (where .Site.RegularPages ".Params.categories" "Web" }}

{{ range first 2 (where .Site.RegularPages ".Params.categories" eq "Web" }}

{{ range first 2 (where .Site.RegularPages ".Params.categories" "eq" "Web" }}

根据 gohugo.io 官网上的文档,我们一般能想到上面这三种,可是实际呢,这三种无论哪一种都不行。那么是为什么呢?

如果我们把 .Params.categories 在前端显示出来,就明白了,它其实是一个 array,显示出来像这样 [Web Life 备忘 旅行],所以,问题很明了,我们怎么能把一个 array 和 string 放在一起比较呢,所以最终没有结果。

知道问题所在后,解决方法也基本上就出来了,我们用 in 或者 union 或者 intersect 来比较就好了。

但是呢,前两个是不行的。

首先,in 的使用方式是 in SET ITEM,所以用 in 不行,没法操作,当然,网上有网友使用 in 来实现 category 文章列表,但是它这个看上去复杂了一层,如果只想要 2 篇文章的话,它外层的 range 不能直接写 first 2,另外,gohugo.io 官网上有 where 结合 in 使用的例子,比如下面这个

where .Site.RegularPages "Type" "in" (slice "page" "about")

它们能用,估计是因为这个 "Type" 直接是一个 string,而不像我们的例子,是一个 array,所以如果用到我们的例子,是没有结果的。

union 也不行,显而易见,因为 union 是组合两者,另外还有 uniq,看着好像可以,其实不是的,uniq 也是组合两者,只不过返回的是剔除重复 ITEM 后的 array。

最终可行的就只有 intersect 了,它就是找两者的交集,乍看很奇怪,跟谁的交集?我们可以自己创造一个啊,比如我们的文章分类有 [Web Life 备忘 旅行],而我们只想调用 Web 分类下的文章(也就是只需要 [Web]),那么我们手动给一个 (slice "Web") 让它来对比,交集肯定就是 [Web] 了,也就实现了我们的目的!同理,如果我们想显示 Web旅行 这两个分类下的文章,给定 (slice "Web" "旅行") 来比较就行了。

综上,这个思路还是有点 tricky 和 hack 的,不过可以说还是比较简单高效的一种分类文章调用方式,网上还有一些看起来非常复杂,太多行,我也没细看😄,目前就用这个吧。如果您有更好的实现方式,还望不吝赐教。

【P.S.】不知不觉又是一年,在 2019 年最后一天的最后几分钟里,我想还是更新上一篇吧,好歹凑个双数😂,爱瞎折腾却不爱动笔,依旧如此。2020,我们来了!

【Update: 2020-01-14】关于 intersect 取交集之前说反了,繁琐,已更正。