这几天都在折腾hexo博客,喜欢markdown。。

现在博客功能差不多完成了,有计数,评论,最重要的是搜索功能,基于php的搜索引擎。

效果图

来看看我的博客搜索图:
http://7xibui.com1.z0.glb.clouddn.com/2015/11/screenshot-window-2015-11-20-195426.png

是不是感觉眼前一亮。。

由于是静态博客所以搜索功能比较麻烦。

之前找的搜索方案都是依赖于第三方搜索引擎,像GoogleSwiftype这些,而这些需要sitemap辅助,搞起来比较费时,况且在墙外不得不放弃。最近找到了一个类似于Swiftype的国内站内搜索引擎,叫Tinysou,刚开始用感觉还行,过了一天就503错误,不得不换方案。

Github找了一下,发现这个项目Tipue/Tipue-Search,可以支持站内静态搜索,依赖一个content.js文件,用来记录文章相关信息。无奈我没学过js,折腾不成放弃了。

因为用的是SAE托管的,支持php,最后吃老本用php解析xml的方法写了一个站内搜索引擎(姑且叫搜索引擎好了),自我感觉良好

下面是重点:

必要插件

  1. hexo-generator-search (生成search.xml)
  2. hexo-filter-fenced-code (在md中插入代码)
npm install hexo-generator-search -s
npm install hexo-filter-fenced-code -s

修改插件

因为原生插件生成的内容太多了,还会包含代码行数、html标签,所以有必要阉割+改造

改造index.js

在插件目录下(node_modules/hexo-generator-search),在index.js中加入

stripe_code_line_num = function(str) { // 去除代码行数,根据自己的主题修改
    return str.replace(/<span class="line">[0-9]*<\/span>/ig, '');
}

stripe = function (str) { // 去除html标签
    return str.replace(/(<([^>]+)>)/ig, '');
}

minify = function (str) { // 压缩成一行
    return str.trim().replace(/\n/g, ' ').replace(/\s+/g, ' ');
}
阉割模板search.ejs

然后修改模板文件search.ejs,只保留链接、标题、内容就好了,可以根据需要保留。精简成下面这个样子就好了。

<?xml version="1.0" encoding="utf-8"?>
<search>
  <% var url = config.url + config.root %>
  <% if(posts){ %>
    <% posts.each(function(post){ %>
    <entry>
      <title><%-: post.title | cdata %></title>
      <url><%- encodeURI(post.permalink) %></url>
      <content type="html"><%-: minify(stripe(stripe_code_line_num(post.content))) | cdata %></content>
    </entry>
    <% }) %>
  <% } %>
  <% if(pages){ %>
    <% pages.each(function(page){ %>
    <entry>
      <title><%-: page.title | cdata %></title>
      <url><%- encodeURI(page.permalink) %></url>
      <content type="html"><%-: minify(stripe(stripe_code_line_num(page.content))) | cdata %></content>
    </entry>
    <% }) %>
  <% } %>
</search>

hexo-filter-fenced-code

先提下为什么要这个插件,主要是为了能在md中插入代码不被渲染,(PS:不知道为什么{% raw %}...{% endraw %}标签怎么没用…)。

为什么要这么做是因为方便修改搜索引擎的php代码以及和主题融为一体,如果直接写搜索引擎的话没法和主题连接起来,就像下面这样
http://7xibui.com1.z0.glb.clouddn.com/2015/11/screenshot-window-2015-11-20-115411.png

iframe框架的方式嵌入主题中效果不太好(是严重不太好。。)

所以有必要在md中插入php代码,然后让hexo渲染成页面即可和主题融为一体,也就是和现在的效果。

事与愿违的是该插件只支持html/css/js,主要是用来快速构建demo。。

node_modules/hexo-filter-fenced-code/lib中修改extra-syntax.js

langMap数组中加入php变量
var langMap = {
'css': 'css',
'htm': 'html',
'html': 'html',
'javascript': 'javascript',
'js': 'javascript',
'json': 'javascript',
'php': 'php'
};
injectFn函数表中加入php部分代码
var injectFn = {
'javascript': function (code) {
    return '<script>' + code + '</script>';
},
'php': function(code) {
    return '<script language=php>\n' + code + '\n</script>';
},
'css': function (code) {
    return '<style type="text/css">' + code + '</style>';
},
'html': function (code) {
    return '<div class="hexo-insert-code">' + code + '</div>';
}
};
canInject函数中加入php部分代码
function canInject(lang) {
return ['javascript', 'css', 'html', 'php'].indexOf(lang) !== -1;
}

搜索引擎核心代码(/search/index.md)

这部分是重头戏。。首先确定你有没有search页面。。没有的话

hexo new page search

然后修改博客配置文件_config.yml,更改search.xml生成路径,最好和生成的index.html目录一致。(可以自己修改)

# 搜索
search:
    path: search/search.xml

source/search中写入下面核心代码index.md,因为无法正常渲染代码,这里直接上传index.md好了。

然后hexo g生成博客,上传到服务器即可。由于SAE服务器不能直接运行.html嵌入的.php代码,需要在/search/index.md的文件夹中新建一个空文件index.php,然后在生成的public目录中删掉这个/search/index.php,由index.html硬连接一下即可,这样就不用担心每次hexo g后会删除index.php了。最后在服务器中设置url重写/search/index.html/search/index.php