Hugo的站内搜索有很多方案,Hugo官网了列出了7种,大家用的应该是hugo-lunr-zh吧,这里我们不引入任何第三方库,另辟蹊径地解决Hugo站内搜索功能。

思路

Hugo会默认生成index.xml文件,里面包含全站内容,以此文件进行内容搜索。这种方法不需要引用第三方库,在前端进行搜索,简洁且速度快!

步骤

  1. 在主题的layouts/_default目录下新建search.html模板文件
  2. 在站点的content目录新建search.md文章
  3. 分别在站点的header中添加css样式,在footer中添加js脚本
  4. 搜索页面的url为http://localhost:1313/search/,可以添加到站点菜单中

实现代码

js代码:

 1  // search
 2  function search() {
 3    key = document.getElementById("search-key").value;
 4    if (key === "") {
 5      return;
 6    }
 7    document.getElementById("search-key").value = "";
 8
 9    // tip
10    document.getElementById("search-tip").innerText = "搜索中,请稍后 ...";
11    document.getElementById("search-tip").style.display = "block";
12
13    // clear
14    var el = document.getElementById('result');
15    var childs = el.childNodes;
16    for (var i = childs.length - 1; i >= 0; i--) {
17      el.removeChild(childs[i]);
18    }
19
20    // xml
21    xmltext = new XMLHttpRequest;
22    xmltext.open("GET", "/index.xml", false);
23    xmltext.send();
24    resp = xmltext.responseXML;
25    items = resp.getElementsByTagName("item");
26    // search
27    var i = 0;
28    haveResult = false;
29    while (i < items.length) {
30      txt = items[i].getElementsByTagName("title")[0].innerHTML + items[i].getElementsByTagName("description")[0].innerHTML
31      if (txt.toLowerCase().indexOf(key.toLowerCase()) > -1) {
32        haveResult = true;
33        title = items[i].getElementsByTagName("title")[0].innerHTML;
34        link = items[i].getElementsByTagName("link")[0].innerHTML;
35        time = items[i].getElementsByTagName("pubDate")[0].innerHTML;
36        mark = items[i].getElementsByTagName("description")[0].innerHTML;
37        addItem(title, link, time, mark)
38      }
39      i++;
40    }
41    if (!haveResult) {
42      document.getElementById("search-tip").innerText = "搜索完毕,未发现结果 ...";
43      document.getElementById("search-tip").style.display = "block";
44    }
45  }
46
47  // add
48  function addItem(title, link, time, mark) {
49    document.getElementById("search-tip").style.display = "none";
50    tmpl = "<article class=\"post\" style=\"border-bottom: 1px solid #e6e6e6;\" >" +
51      "<header class=\"post-header\">" +
52      "<h1 class=\"post-title\"><a class=\"post-link\" href=\"" + link + "\" target=\"_blank\">" + title + "</a></h1>" +
53      "<div class=\"post-meta\">" +
54      " <span class=\"post-time\">" + time + "</span>" +
55      "</div>" +
56      " </header>" +
57      "<div class=\"post-content\">" +
58      "<div class=\"post-summary\">" + mark + "</div>" +
59      "<div class=\"read-more\">" +
60      "<a href=\"" + link + "\" class=\"read-more-link\" target=\"_blank\">阅读更多</a>" +
61      "</div>" +
62      " </div>" +
63      "</article>"
64    div = document.createElement("div")
65    div.innerHTML = tmpl;
66    document.getElementById('result').appendChild(div)
67  }
68/*********************search.js end***************** */

css样式如下:

 1  /* 手机适配 */
 2  @media screen and (max-width: 500px) {
 3     .search{
 4       padding-right: 25px;
 5     }
 6
 7     .search input{
 8       width: 100%;
 9     }
10
11     .search button{
12       display: none;
13     }
14  }
15  /* 电脑适配 */
16  @media screen and (min-width: 500px) {
17      .search{
18        width: 500px;
19      }
20
21      .search input{
22        width: 444px;
23      }
24  }
25
26  /* 通用样式 */
27  .search{
28    margin: auto;
29	width: 70%;
30    padding-top: 10%;
31  }
32
33  .search input{
34    outline: none;
35    border: 2px solid var(--accent);
36    height: 50px;
37    padding: 10px;
38  }
39  .search button{
40    outline: none;
41    border: 0px;
42    height: 50px;
43    width:59px;
44    position:absolute;
45    background-color:var(--accent) ;
46    display: inline-block;
47  }
48  .search .icon{
49    width: 28px;
50    height: 28px;
51  }

search.html模板:

 1{{ define "main" }}
 2<!-- All of the site's posts grouped by year -->
 3<section id="main">
 4  <div class="container">
 5    <section id="archives" >
 6   <div class="search">
 7  <input type="text" placeholder="请输入搜索内容..." id="search-key" />
 8  <button onclick="search()">
 9    <svg t="1583982313567" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1271"
10      width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink">
11      <defs>
12        <style type="text/css"></style>
13      </defs>
14      <path d="M694.857143 475.428571q0-105.714286-75.142857-180.857142T438.857143 219.428571 258 294.571429 182.857143 475.428571t75.142857 180.857143T438.857143 731.428571t180.857143-75.142857T694.857143 475.428571z m292.571428 475.428572q0 29.714286-21.714285 51.428571t-51.428572 21.714286q-30.857143 0-51.428571-21.714286l-196-195.428571q-102.285714 70.857143-228 70.857143-81.714286 0-156.285714-31.714286t-128.571429-85.714286-85.714286-128.571428T36.571429 475.428571t31.714285-156.285714 85.714286-128.571428 128.571429-85.714286T438.857143 73.142857t156.285714 31.714286 128.571429 85.714286 85.714285 128.571428T841.142857 475.428571q0 125.714286-70.857143 228l196 196q21.142857 21.142857 21.142857 51.428572z"
15        p-id="1272" fill="#ffffff"></path>
16    </svg>
17  </button>
18</div>
19<h1 id="search-tip" style="color: #c05b4d;text-align: center;display: none;">搜索中,请稍后 ...</h1>
20<br />
21<div id="result" style="padding-left: 10px;"></div>
22    </section>
23
24  </div>
25</section>
26{{ end }}

search.md文章内容:

1---
2title: "Search"
3date: "2019-07-10"
4author: "joe"
5layout: search
6type: search
7---