blog/_posts/2025-04-04-search.md
2025-04-04 11:32:17 +00:00

77 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: post
title: 最近对博客搜索功能的优化记录
tags: [博客, 搜索, 优化]
---
看看其他的博客也会有新的灵感啊~<!--more-->
# 起因
前段时间我闲来无事在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');
// 递归遍历并高亮文本节点
function highlightTextNodes(element) {
$(element).contents().each(function() {
if (this.nodeType === Node.TEXT_NODE) {
const $this = $(this);
const text = $this.text();
// 使用正则替换并保留原始大小写
if (regex.test(text)) {
const replaced = text.replace(regex, '<mark>$1</mark>');
$this.replaceWith(replaced);
}
} else if (
this.nodeType === Node.ELEMENT_NODE &&
!$(this).is('script, style, noscript, textarea')
) {
highlightTextNodes(this);
}
});
}
$('section').each(function() {
highlightTextNodes(this);
});
});
```
我测试了一下非常符合我的需求各种情况都能按照我的预期工作虽然说功能非常简单但是能正常运行AI写的还是挺不错的。
# 近期的其他修改
除了对搜索功能的优化,我还做了些别的功能:
## 随机跳转文章
前段时间我看到有其他人的博客增加了一个随机跳转文章的功能,不过他的博客是动态博客,实现也比较奇葩,是渲染页面时就已经决定好要随机的文章,也就是说无论用户想不想随便看看,程序都已经随机好了。当然用着静态博客的我来说,从原理上也做不到这一点,不过既然我之前在做[相似文章推荐功能时](/2024/10/01/suggest.html)已经对搜索功能的数据进行了缓存,那么直接用缓存的内容直接随机就好了吧……所以就随便写了写,代码也极其简单:
```html
<a href="javascript:getSearchJSON(function(data){window.location = data[Math.floor(Math.random()*data.length)].url})">Random</a>
```
## 给文章内标题添加锚链接
最近在修改我的博客的时候我更新了一下[给文章生成目录的组件](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 %}<span style="float: right;"><a href="{{ site.github.repository_url }}/tree/master/{{ page.path }}">查看原始文件</a></span>{% endraw %}
```
# 感想
多看看其他人的博客看来也挺不错,可以看看其他人的想法,说不定就有可以参考的价值呢……不只是文章内容,网站本身的一些功能也是作者的想法啊……而对于那些只套别人模版,没什么自己的改动的博客,那就没什么意思了(当然不会代码的那就没办法了~)。有些人说博客中只有文章才是最重要的,但我觉得对于技术博客来说网站的代码也是展示自己的部分,所以折腾博客本身也是很重要的!