为 Hugo 静态网站添加全文检索功能

Hugo 是一种使用 Go 语言编写的静态网站构建工具。在其官网文章《Search for your Hugo Website》中,介绍几种为静态网站添加全文检索功能的方法。本文采用 Pagefind 为纯静态网站实现全文检索功能。

Pagefind 是一个独立的命令行工具,可以通过 npm install pagefind 来安装。其原理是:运行 Pagefind 命令,扫描所有静态网页并生成索引;用户搜索时,通过网页中内嵌的 JavaScript 脚本来访问预先生成的索引,从而实现静态全文检索。

Windows 系统下,使用 npm i pagefind 安装后,需要将 node_modules\pagefind\bin\pagefind_extended 文件重命名为 pagefind_extended.exe 才能正常使用。

实现原理

第一步,安装 Pagefind 工具。在 Hugo 项目根目录中运行:

BASHnpm i pagefind

第二步,生成 Hugo 网站的静态文件:

BASHhugo --minify

第三步,生成 Pagefind 索引:

BASHnpx pagefind --source public --bundle-dir search

此命令会扫描 public 目录下的静态文件,并将生成的索引保存到 search 目录下(默认是 _pagefind 目录)。也可以通过配置文件来实现相同的操作。

在项目根目录下新建 pagefind.yml 配置文件,保存如下内容:

YAMLsource: public
bundle_dir: search

然后直接运行:

BASHnpx pagefind

Pagefind 会自动在当前目录下查找 pagefind.yml 配置文件,使用参数或配置文件的效果是等价的。其他参数可以参考官方文档

第四步,在静态网页中添加全文搜索的入口:

HTML<link href="/search/pagefind-ui.css" rel="stylesheet">
<script src="/search/pagefind-ui.js" type="text/javascript"></script>

<div id="search"></div>
<script>
    window.addEventListener('DOMContentLoaded', (event) => {
        new PagefindUI({ element: "#search" });
    });
</script>

自定义索引

可以通过在静态网页中添加特殊的 HTML 属性来控制 Pagefind 的行为。比如,HTML 元素添加属性 data-pagefind-body 表示需要索引此处的内容,添加属性 data-pagefind-ignore 表示不要索引此处内容。

HTML<article data-pagefind-body>
    <h1 data-pagefind-meta="title">文章标题</h1>
    <p>发布时间:<span data-pagefind-meta="日期">2022/10/18</span></p>
    <p>作者:<span data-pagefind-meta="作者">Fournoas</span></p>
    <p>正文内容</p>
    <aside data-pagefind-ignore>目录</aside>
</article>

data-pagefind-meta 属性用于标记元数据。Pagefind 默认将网页中的 <h1> 元素中的文本当作标题。如果一个网页中包含多个 <h1> 标签,会导致搜索结果中的标题丢失。可以采取为元素添加属性 data-pagefind-meta="title" 指定网页的标题。

此外,还能通过 data-pagefind-filter 属性自定义搜索过滤器:

HTML<h1>文章标题</h1>
<p>分类: <span data-pagefind-filter="分类">小说</span></p>
<p>标签: <a data-pagefind-filter="标签">科幻</span> / <a data-pagefind-filter="标签">穿越</span></p>

上面的代码会让搜索结果的左侧会出现 分类标签 两个过滤器。

配置 GitHub Actions

在文章《使用 GitHub Actions 自动部署 Hugo 站点》中提供了自动部署 Hugo 站点的 Workflow 配置,在此基础上进行简单修改,即可实现自动生成索引并发布。

编辑 .github/workflows/hugo.yml 文件,在 steps 小结中的 BuildDeploy 操作之间添加如下内容:

YML  - name: Install nodejs
    uses: actions/setup-node@v3
    with:
      node-version: 18
  - run: npm i pagefind
  - run: npx pagefind --source public --bundle-dir search

最后实现效果可以查看本站的搜索页面。