--- layout: post title: 最近对博客搜索功能的优化记录 tags: [博客, 搜索, 优化] --- 看看其他的博客也会有新的灵感啊~ # 起因 前段时间,我闲来无事在GitHub上搜和我使用相同模板[minimal](https://github.com/pages-themes/minimal)的博客。但搜索结果中有许多人用这个模板制作的是简历或作品集,这让我有些失望。不过这倒也能理解,因为这个模版并不算博客模板,没有文章列表之类的代码,这些都只能自己写。当然多找找还是能找到一些的,毕竟这个模板在GitHub Pages中算是最受欢迎,至少符合大众的审美。像我就搜到了一个叫[Guanzhou Hu的博客](https://github.com/josehu07/josehu07.github.io),他对模板的样式做了不少的改动,而且改的还挺好看的,尤其是右上角的导航栏,看起来挺有意思,只是这个源代码……导航栏有点硬编码的感觉,我不是很喜欢这种实现方式…… # 使用标签作为关键词进行搜索 之后我又看了看其他博客,看到了[Matt Walker Blog](https://github.com/mhwalker/mhwalker.github.io)。他没有对模板做很多改动,只是把section元素变得更宽了,但是他没有改手机版自适应的样式,导致界面基本上没法在手机上查看。不过在他的首页中,我对他把文章标签放在文章列表这个操作非常感兴趣,因为每次我都有给文章打标签,但是几乎没什么用。他的标签点进去之后会跳转到该标签下的所有文章,我其实很早就想做这个功能了,但是在不用插件的情况下Jekyll基本上做不出来这种功能,因为没有插件的情况下是不能使用Liquid标签创建文件的,我看了下他的实现,原来是提前创建好的标签页面然后进行筛选的,这个实现我也不喜欢,这样的话我每次打标签都要新建一个标签对应的页面,这种事情不让程序做我会很不爽……(其实现在的GitHub Pages构建网站都是用的Actions了,完全可以自己写一个可以使用插件的Actions来进行构建,不过我也懒得折腾了🤣) 要么还有一个选择,可以单独搞一个页面,里面有所有标签对应的文章,点击文章的标签之后使用锚链接定位到对应标签所在的位置。但这样会导致一个页面有可能有一堆相同的文章链接,结果这个页面比归档页面的链接还多,那就感觉有点糟糕了…… 不过我想起来以前做的[博客全文搜索功能](/2021/07/23/search.html),如果把标签作为关键词进行查询,那也能起到筛选出标签对应文章的作用吧?而且这样即使我没给那个文章打标签也能搜出来,其实也算不错的选择,另外自从我做出来那个全文搜索的功能之后也没用过几次,没有关键词的话也一时半会想不出来搜什么比较好。于是说做就做,直接把Matt Walker Blog那段在文章列表生成标签的代码复制过来,感觉好像还不错😆? 顺便我也把文章里面的标签也加了链接到搜索的功能,不过原来的代码用的是`.join`实现的,现在加上这个功能的话就只能老老实实用循环写了😥…… # 搜索后使用高亮标记关键词 上面的标签搜索效果还不错,只是有些关键词搜完之后有点难发现。我搜索出来之后怎么证明搜到的内容里面一定有对应的关键词呢?虽然从程序的角度来说这是理所应当的事情,一定是有的数据才可能被搜到,但有时候不用Ctrl+F看一眼都不知道是哪里搜到了……所以我觉得应该像其他网站一样对搜到的内容用高亮进行标记。标记应该用什么呢?用样式也许不错,不过现在的H5标签里有一个叫mark的标签可以直接用,用这个标签包裹的内容背景颜色就会变成黄色,就像用荧光笔标记了一样,这样就不需要写样式了。 至于关键词用查询字符串传过去就好了,那我该怎么做呢?我用的搜索脚本叫[Simple-Jekyll-Search](https://github.com/christian-fei/Simple-Jekyll-Search),它的文档其实根本没有写怎么把搜索的请求传到模版里,还好它有个[关于模版的测试脚本](https://github.com/christian-fei/Simple-Jekyll-Search/blob/master/tests/Templater.test.js)里面有写,有个query关键词可以把搜索内容给模版渲染出来,既然做了这个功能怎么不写在文档里😅,不过这个项目已经停止,也没法提出什么建议了…… 这个功能听起来相当简单,我都懒得写了,这种简单的功能直接让AI写才对!于是我把需求告诉它,让它给我实现一份,于是这就是让AI给我写的高亮关键词的JS代码(经过了一点修改): ```javascript $(function () { const urlParams = new URLSearchParams(window.location.search); const keyword = urlParams.get('kw')?.trim(); if (!keyword) return; // 转义正则表达式特殊字符,避免安全问题 const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // 创建不区分大小写的正则表达式(全局匹配) const regex = new RegExp(`(${escapedKeyword})`, 'gi'); // 递归遍历并高亮文本节点 const escapeHTML = str => str.replace(/[&<>"']/g, tag => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[tag] || tag)); function highlightTextNodes(element) { $(element).contents().each(function () { if (this.nodeType === Node.TEXT_NODE) { const $this = $(this); const text = escapeHTML($this.text()); // 使用正则替换并保留原始大小写 if (regex.test(text)) { const replaced = text.replace(regex, '$1'); $this.replaceWith(replaced); } } else if ( this.nodeType === Node.ELEMENT_NODE && !$(this).is('script, style, noscript, textarea') ) { highlightTextNodes(this); } }); } $('section').each(function () { highlightTextNodes(this); }); }); ``` (2025.04.28更新:解决了一个潜在的解析问题) 我测试了一下,非常符合我的需求,各种情况都能按照我的预期工作,虽然说功能非常简单,但是能正常运行,AI写的还是挺不错的。 # 近期的其他修改 除了对搜索功能的优化,我还做了些别的功能: ## 随机跳转文章 前段时间我看到有其他人的博客增加了一个随机跳转文章的功能,不过他的博客是动态博客,实现也比较奇葩,是渲染页面时就已经决定好要随机的文章,也就是说无论用户想不想随便看看,程序都已经随机好了。当然用着静态博客的我来说,从原理上也做不到这一点,不过既然我之前在做[相似文章推荐功能时](/2024/10/01/suggest.html)已经对搜索功能的数据进行了缓存,那么直接用缓存的内容直接随机就好了吧……所以就随便写了写,代码也极其简单: ```html Random ``` ## 给文章内标题添加锚链接 最近在修改我的博客的时候我更新了一下[给文章生成目录的组件](https://github.com/allejo/jekyll-toc),在这时候我想看看它还有什么有意思的组件可以用,然后就发现了[jekyll-anchor-headings](https://github.com/allejo/jekyll-anchor-headings),它可以像GitHub展示Markdown文件一样在标题上添加点击后就可以直接跳转到对应标题的锚链接,而且示例里也给出了怎么做[可以像GitHub的风格](https://github.com/allejo/jekyll-anchor-headings/wiki/Examples#github-style-octicon-links)。看起来挺有意思,所以就给自己加上了😆。 ## 添加能跳转到原始Markdown的链接 在修改博客的时候我参考了一下Jekyll的官方文档,在这个时候发现了page.path这个变量。我想了一下这个变量可以用来链接到我的文章内容,然后就在文章标签位置的右侧加上了这个链接,为了能让它显示在右侧,我用的是`float: right`,但是这样会导致和文章标签不在同一行,查了一下才知道用了浮动就会强制将元素转换成块级元素,而文章标签用的是行内元素,所以对不齐,没办法就只能把这一整行都转换成块级元素了……于是代码如下: ```html {% raw %}查看原始文件{% endraw %} ``` # 感想 多看看其他人的博客看来也挺不错,可以看看其他人的想法,说不定就有可以参考的价值呢……不只是文章内容,网站本身的一些功能也是作者的想法啊……而对于那些只套别人模版,没什么自己的改动的博客,那就没什么意思了(当然不会代码的那就没办法了~)。有些人说博客中只有文章才是最重要的,但我觉得对于技术博客来说网站的代码也是展示自己的部分,所以折腾博客本身也是很重要的!