hexo添加站内搜索

现在还没写几篇文章,突然发现找以前的文章是非常不方便,所以今天特意添加了站内搜索功能

前言

  站内搜索大致分为:

  1. 集成百度,谷歌,搜狗,msn 等搜索引擎
  2. 使用 Swiftype
  3. 使用 hexo 自带的 Google Search 或 Search

  当初在添加站内搜索是我首先把第一种方法给 pass ,因为这几种方法的体验性不好。后来打算集成 Swiftype 因为方便,不用咋写代码。后来在 Swiftype 注册是发现我注册不了。他一直报我的邮箱非企业邮箱,所以把这种方法也给 pass 了。最后我采用了 hexo 自带的 Search

操作步骤

修改搜索框

  修改 left-col.ejs。搜索代码给修改了一下是我的搜索代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
   <!-- 搜索框相关 -->
<form id="search-form">
    <input type="text" id="local-search-input" name="q" results="0" placeholder="search..." class="search form-control" autocomplete="off" autocorrect="off"/>
     <!-- 清空/重置搜索框 -->
    <i class="fa fa-times" onclick="resetSearch()"></i>
</form>
 <!-- 搜索结果区 -->
 <div id="local-search-result"></div>
    <!-- 无匹配时显示,注意请在 CSS 中设置默认隐藏 -->
 <p class='no-result'>No results found </p

添加搜索的 js

  在主题的 themes中新建 search.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  var searchFunc = function(path, search_id, content_id) {
    'use strict';
    $.ajax({
        url: path,
        dataType: "xml",
        success: function( xmlResponse ) {
            // get the contents from search data
            var datas = $( "entry", xmlResponse ).map(function() {
                return {
                    title: $( "title", this ).text(),
                    content: $("content",this).text(),
                    url: $( "url" , this).text()
                };
            }).get();
            var $input = document.getElementById(search_id);
            var $resultContent = document.getElementById(content_id);
            $input.addEventListener('input', function(){
                var str='<ul class=\"search-result-list\">';
                var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                $resultContent.innerHTML = "";
                if (this.value.trim().length <= 0) {
                    return;
                }
                // perform local searching
                datas.forEach(function(data) {
                    var isMatch = true;
                    var content_index = [];
                    var data_title = data.title.trim().toLowerCase();
                    var data_content = data.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
                    var data_url = data.url;
                    var index_title = -1;
                    var index_content = -1;
                    var first_occur = -1;
                    // only match artiles with not empty titles and contents
                    if(data_title != '' && data_content != '') {
                        keywords.forEach(function(keyword, i) {
                            index_title = data_title.indexOf(keyword);
                            index_content = data_content.indexOf(keyword);
                            if( index_title < 0 && index_content < 0 ){
                                isMatch = false;
                            } else {
                                if (index_content < 0) {
                                    index_content = 0;
                                }
                                if (i == 0) {
                                    first_occur = index_content;
                                }
                            }
                        });
                    }
                    // show search results
                    if (isMatch) {
                        str += "<li><a href='"+ data_url +"' class='search-result-title' target='_blank'>"+ "> " + data_title +"</a>";
                        var content = data.content.trim().replace(/<[^>]+>/g,"");
                        if (first_occur >= 0) {
                            // cut out characters
                            var start = first_occur - 6;
                            var end = first_occur + 6;
                            if(start < 0){
                                start = 0;
                            }
                            if(start == 0){
                                end = 10;
                            }
                            if(end > content.length){
                                end = content.length;
                            }
                            var match_content = content.substr(start, end);
                            // highlight all keywords
                            keywords.forEach(function(keyword){
                                var regS = new RegExp(keyword, "gi");
                                match_content = match_content.replace(regS, "<em class=\"search-keyword\">"+keyword+"</em>");
                            })
                            str += "<p class=\"search-result\">" + match_content +"...</p>"
                        }
                    }
                })
                $resultContent.innerHTML = str;
            })
        }
    })
}

  在主题的 themes.js 中添加代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var search = function(){
     require([yiliaConfig.rootUrl + 'js/search.js'], function(){
         var inputArea = document.querySelector("#local-search-input");
         var $HideWhenSearch = $("#toc, [[tocButton]], .post-list, [[post-nav-button]] a:nth-child(2)");
         var $resetButton = $("#search-form .fa-times");
         var $resultArea = $("#local-search-result");
         var getSearchFile = function(){
             var search_path = "search.xml";
             var path = yiliaConfig.rootUrl + search_path;
             searchFunc(path, 'local-search-input', 'local-search-result');
         }
         var getFileOnload = inputArea.getAttribute('searchonload');
         if (yiliaConfig.search && getFileOnload === "true") {
             getSearchFile();
         } else {
             inputArea.onfocus = function(){ getSearchFile() }
         }
         var HideTocArea = function(){
             $HideWhenSearch.css("visibility","hidden");
             $resetButton.show();
         }
         inputArea.oninput = function(){ HideTocArea() }
         inputArea.onkeydown = function(){ if(event.keyCode==13) return false}
         resetSearch = function(){
             $HideWhenSearch.css("visibility","initial");
             $resultArea.html("");
             document.querySelector("#search-form").reset();
             $resetButton.hide();
             $(".no-result").hide();
         }
         $resultArea.bind("DOMNodeRemoved DOMNodeInserted", function(e) {
             if (!$(e.target).text()) {
                 $(".no-result").show(200);
             } else {
               $(".no-result").hide();
             }
         })
     });
 }

  另外需要在下面的 return 函数中添加 search();

添加搜索的 css

  在主题的 themes_partial 中新建 search.styl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 /*搜索框*/
.search {
  width: 68%;
  height: 18px;
  margin-top: 1px;
  padding: 0;
  font-family: inherit;
  border: 2px solid transparent;
  border-bottom: 2px solid [[d3d3d3]];
  border-radius: 2px;
  opacity: 0.65;
  background: none;
}
.search:hover {
  border: 2px solid [[d3d3d3]];
  opacity: 1;
  box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
/*搜索重置按钮*/
[[search-form]] .fa-times {
  display: none;
  padding: 1px 0.7em;
  box-shadow: 0 0 3px rgba(0,0,0,0.15);
  cursor: pointer;
  color: #808080;
}
[[search-form]] .fa-times:active {
  background: [[d3d3d3]];
}
[[search-form]] .fa-times:hover {
  zoom: 1.1;
  padding: 1px 0.6em;
  border: 1px solid [[d3d3d3]];
  box-shadow: 0 0 6px rgba(0,0,0,0.25);
}
/*搜索结果区*/
[[local-search-result]] {
  margin: auto -12% auto -6%;
  font-size: 0.9em;
  text-align: left;
  word-break: break-all;
}
[[local-search-result]] ul.search-result-list li:hover {
  font-weight: normal;
}
/*单条搜索结果*/
[[local-search-result]] li {
  margin: 0.5em auto;
  border-bottom: 2px solid [[d3d3d3]];
}
[[local-search-result]] .search-result-list li:hover {
  background: rgba(158,188,226,0.21);
  box-shadow: 0 0 5px rgba(0,0,0,0.2);
}
/*匹配的标题*/
[[local-search-result]] a.search-result-title {
  line-height: 1.2;
  font-weight: bold;
  color: #708090;
}
/*搜索预览段落*/
[[local-search-result]] p.search-result {
  margin: 0.4em auto;
  line-height: 1.2em;
  max-height: 3.6em;
  overflow: hidden;
  font-size: 0.8em;
  text-align: justify;
  color: #808080;
}
/*匹配的关键词*/
[[local-search-result]] em.search-keyword {
  color: [[f58e90]];
  border-bottom: 1px dashed [[f58e90]];
  font-weight: bold;
  font-size: 0.85em;
}
/*无匹配搜索结果时显示*/
p.no-result {
  display: none;
  margin: 2em 0 2em 6%;
  padding-bottom: 0.5em;
  text-align: left;
  color: #808080;
  font-family: font-serif serif;
  border-bottom: 2px solid [[d3d3d3]];
}

  然后在 themes中的 style.styl 添加一下代码

1
2
if search
  @import "_partial/search"

修改 after-footer.ejs

  文件路径 themes_partial

  把 theme.search_box 中的函数全部删除了,因为下面的样式。我这个主题也是基于 yilia 的 ,原先 Litten 大神已经集成了一个搜索引擎,但是后来已经那个引擎不能用了。所以把下面的代码删除了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
  window.onload = function(){
    document.getElementById("search").onclick = function(){
        console.log("search")
        search();
    }
  }
  function search(){
    (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
    (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
    e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
    })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
    _st('install','A1Pz-LKMXbrzcFg2FWi6','2.0.0');
  }
</script>

参考资料

  1. 高明飞

    原本是打算按照这老大哥的教程写的,但发现他的有点设计我看不懂。所以没实行

  2. MOxFIVE

  现在还没写几篇文章,突然发现找以前的文章是非常不方便,所以今天特意添加了站内搜索功能