Hugo 自定义分页导航条(基于 Discuz 分页导航条改编)

Hugo 自带的分页导航功能其实也不错,但是它有一个很让人不舒服的地方,就是它生成了太多的空行(blank lines),这个问题已经很多年了,貌似官方也不关注这块儿,到目前为止最新版的 Hugo(v0.62.0)依然如此。

按理说,在大括号内侧加上 - ,像这样:{{- -}},可以自动清理掉代码块前后多余的空行,但是不知为什么,自带的 pagination 模板貌似没这么做。从源代码来看,这个 pager 有多少省略掉的页面,就会产生多少空行,这样在看源代码时太丑了,如果只有几页,那感觉不出来,但是如果是几十上百页的话,就会有大片的空白,让人很不舒服,问题的关键是你还不能消除,因为 pager 是被调用的,你在外面包裹再多的 - 也白搭,影响不大它内部。

那能不能自己写一个 pager 呢?当然可以,稍微熟悉 Hugo 模板应该就能照着文档自己写一个分页导航条(pager)。但是转念一想,其他 CMS 有没有现成的比较好的呢?看了看 WordPress 的,也不太喜欢,无意中发现了 Discuz 论坛的分页导航条,感觉正合适,Discuz 的分页导航条功能可以说是非常完备了,而且能看出它的作者肯定考虑的非常周全,对于导航条的各种需求,作者非常清楚,这个真的是大赞。

于是我就照着 Discuz 的分页 Function(DiscuzX 3.4,位于 /uc_server/model/base.php)自己用 Hugo 模板语言来实现了一下,因为自己对于 Go template 也不是很熟悉,过程中遇到很多问题,花了很长时间,不过最终还是翻版过来了😄,实际测试好像也没什么问题。

需要注意的几点:

  • variable 需要在用之前先声明好,也就是代码前面那几行。
  • Go template 没有 for loop,需要用 range
  • Hugo 本身与 Discuz 的区别,导致某些页面,比如 taxonomy 的首页,url 规则$contextURL)是不一样的,所以额外多出了一些替换
  • 另外,Discuz 的代码是直接 concatenate 的,而因为上面的原因以及两者语法的不同,我直接把每条(代码中的 chain 部分)依次罗列下来了。

好了,下面是 Hugo 版的自定义分页导航条(custom pager)代码,水平有限,博主不保证 100% 正确和可移植 🙃,(pager 的具体样子可见本站分页部分):

{{- $num := len (where .Site.RegularPages "Type" "post") -}}
{{- $perpage := 7 -}}
{{- $curpage := .Paginator.PageNumber -}}
{{- $contextURL := "" -}}
{{- $to := 1 -}}
{{- $from := 1 -}}

{{- if eq .Kind "taxonomy" -}}
  {{- if eq .Data.Singular "category" -}}
    {{- $contextURL = printf "%s%s%s" "/categories/" (.Title | urlize | lower ) "/page/" -}}
  {{- else -}}
    {{- $contextURL = printf "%s%s%s" "/tags/" (.Title | urlize | lower ) "/page/" -}}
  {{- end -}}
{{- else -}}
  {{- $contextURL = "/page/" -}}
{{- end -}}

{{- if ge .Paginator.TotalPages 2 -}}
{{- if gt $num $perpage -}}
  {{- $span := 5 -}}
  {{- $offset := 2 -}}
  {{- $pages := .Paginator.TotalPages -}}
  {{- if gt $span $pages -}}
    {{- $from = 1 -}}
    {{- $to = $pages -}}
  {{- else -}}
    {{- $from = sub $curpage $offset -}}
    {{- $to = sub (add $from $span) 1 -}}
    {{- if lt $from 1}}
      {{- $to = sub (add $curpage 1) $from -}}
      {{- $from = 1 -}}
        {{- if lt (sub $to $from) $span -}}
          {{- $to = $span -}}
        {{- end -}}
    {{- else if gt $to $pages -}}
      {{- $from = add (sub $pages $span) 1 -}}
      {{- $to = $pages -}}
    {{- end -}}
  {{- end -}}

  {{- $chain1 := cond (and (gt (sub $curpage $offset) 1) (gt $pages $span )) (printf "%s%s%d%s" "<li class=\"page-item\"><a class=\"page-link\" href=" $contextURL 1 ".html>&#10096;&#10096; 1 ...</a></li>" | safeHTML) "" -}}
  {{- if eq $contextURL "/page/" -}}
    {{- $chain1Replaced := replace $chain1 "/page/1.html" "/" | safeHTML -}}
    {{- $chain1Replaced -}}
  {{- else -}}
    {{- $chain1Replaced := replace $chain1 "/page/1.html" ".html" | safeHTML -}}
    {{- $chain1Replaced -}}
  {{- end -}}

  {{- if .Paginator.HasPrev -}}
    <li class="page-item"><a class="page-link" href="{{- .Paginator.Prev.URL -}}">&#10094; 上一页</a></li>
  {{- end -}}

  {{- if le $from $to}}
    {{- range $i, $sequence := last (add (sub $to $from) 1 ) (seq $to) -}}
      <li class="page-item">
        {{- $chain3 := cond (eq $sequence $curpage) (printf "%s%s%d%s%d%s" "<a class=\"page-link\" id=\"active\" href=" $contextURL $sequence ".html>" $sequence "</a>" | safeHTML) (printf "%s%s%d%s%d%s" "<a class=\"page-link\" href=" $contextURL $sequence ".html>" $sequence "</a>" | safeHTML) -}}
        {{- if eq $contextURL "/page/" -}}
          {{- $chain3Replaced := replace $chain3 "/page/1.html" "/" | safeHTML -}}
          {{- $chain3Replaced -}}
        {{- else -}}
          {{- $chain3Replaced := replace $chain3 "/page/1.html" ".html" | safeHTML -}}
          {{- $chain3Replaced -}}
        {{- end -}}
      </li>
    {{- end -}}
  {{- end -}}

  {{- if .Paginator.HasNext -}}
    <li class="page-item"><a class="page-link" href="{{- .Paginator.Next.URL -}}">下一页 &#10095;</a></li>
  {{- end -}}

  {{- $chain5 := cond (lt $to $pages) (printf "%s%s%d%s%d%s" "<li class=\"page-item\"><a class=\"page-link\" href=" $contextURL $pages ".html>... " $pages " &#10097;&#10097;</a></li>" | safeHTML) "" -}}
  {{- $chain5 -}}

{{- end -}}
{{- end -}}