next主题优化(bug修复)

搜索bug修复、友链新增、waline评论

在我换了新主题之后,我发现有一个非常影响我个人使用的bug,就是搜索功能缺陷。打个比方,我有200篇文章,但是他貌似是只能检索前100篇,去年写的100篇就完全搜索不到了,并且每个主题好像都有bug是说搜索关键词之后,文章内容和文章标题优先级是等同的,这个非常不好,因为大部分技术就这样了,比方说php,在绝大多数文章里面都会有,这个要修复。

再者就是经典的友链环节了,这次我新增会和往常不一样,其他时候我是修改、增加主题的源文件。显而易见的问题就是现在的主题更新还挺勤快,一更新就要重新来,前几日 3a0-Eminem师傅给我提及到了一个关键点,就是markdown是支持html语法的。(把这事给忘了),那我们就可以直接嵌入一个页面,而且也不会和主题之间也不会有明显的嵌入感

安装插件

1
npm install hexo-generator-searchdb --save

在博客根目录的__config.yml中增加

1
2
3
4
5
6
search:
  # path: search.xml
  path: search.json
  field: post
  content: true
  format: html

注意,是jsonxml有部分影响对于本次bug产生,这样子已经能搜索部分文章了,但是并没把bug修复,还有一个重要的点就是修改插件函数,打开D:\blog\node_modules\hexo-generator-searchdb\lib\json_generator.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
"use strict";

module.exports = function (locals) {
  var config = this.config;
  var database = require("./database")(locals, config);

  // ---------------------------------------------新增修改
  function reconvert(str) {
    str = str.replace(/(\\u)(\w{1,4})/gi, function ($0) {
      return String.fromCharCode(
        parseInt(escape($0).replace(/(%5Cu)(\w{1,4})/g, "$2"), 16)
      );
    });
    str = str.replace(/(&#x)(\w{1,4});/gi, function ($0) {
      return String.fromCharCode(
        parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"), 16)
      );
    });
    str = str.replace(/(&#)(\d{1,6});/gi, function ($0) {
      return String.fromCharCode(
        parseInt(escape($0).replace(/(%26%23)(\d{1,6})(%3B)/g, "$2"))
      );
    });

    return str;
  }
  database.forEach(function (item) {
    item.content = reconvert(item.content);
  });
  // -----------------------------------------------
  return {
    path: config.search.path,
    data: JSON.stringify(database),
  };
};

首先在md文件里面加type: links,然后写文件的时候注意里面的html是会被Nunjucks解析的,为了防止解析可以加raw

 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
{% raw %}
<div id="links-root"></div>
<style>
  #links-root{--gap:16px;--radius:14px;--card-bg:rgba(255,255,255,0.7);--card-border:rgba(0,0,0,0.06);--card-hover-bg:rgba(0,0,0,0.04);--shadow:0 6px 18px rgba(0,0,0,0.06);margin:0 auto;max-width:1100px}
  #links-root .links-category{margin:28px 0 22px}
  #links-root .links-category h2{margin:0 0 12px;font-size:1.25rem;font-weight:700;line-height:1.2}
  #links-root .links-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gap)}
  @media (max-width:768px){#links-root .links-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
  #links-root .friend-card{display:block;text-decoration:none;color:inherit;border-radius:var(--radius);border:1px solid var(--card-border);background:var(--card-bg);padding:10px;transition:transform .15s ease,box-shadow .15s ease,background .2s}
  #links-root .friend-card:hover{background:var(--card-hover-bg);transform:translateY(-2px);box-shadow:var(--shadow)}
  #links-root .avatar-wrap{position:relative;border-radius:12px;overflow:hidden;aspect-ratio:1/1}
  #links-root .avatar-wrap img{width:100%;height:100%;object-fit:cover;display:block}
  #links-root .avatar-wrap .desc{position:absolute;left:0;right:0;bottom:0;transform:translateY(100%);padding:10px 12px;background:rgba(0,0,0,.72);color:#fff;font-size:.875rem;line-height:1.35;transition:transform .2s ease;pointer-events:none}
  #links-root .avatar-wrap.reveal .desc{transform:translateY(0)}
  #links-root .meta{padding-top:8px}
  #links-root .name{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .post-title{display:none!important}
</style>
<script>
  const LINKS_DATA=[{links_category:"Team",list:[{name:"su-team",link:"https://su-team.cn/",description:"不止是CTF!",avatar:"https://baozongwi.xyz/images/su_logo/SU4.jpg"}]},{links_category:"friends🤩",list:[{name:"fushuling",link:"https://fushuling.com/",description:"带我进SU的好哥哥",avatar:"https://fushuling-1309926051.cos.ap-shanghai.myqcloud.com/2022/08/QQ%E5%9B%BE%E7%89%8720220812001845.jpg"},{name:"Y4tacker",link:"https://y4tacker.github.io/",description:"Y4师傅诶~",avatar:"https://y4tacker.github.io/images/me.jpeg"}]}];
  const escapeHTML=(s)=>String(s).replace(/[&<>"']/g,(m)=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
  function shuffle(arr){for(let i=arr.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[arr[i],arr[j]]=[arr[j],arr[i]]}return arr}
  function createCard(item){
    const a=document.createElement('a');
    a.className='friend-card';
    a.href=item.link;
    a.target='_blank';
    a.rel='noopener noreferrer';
    a.setAttribute('aria-label',`${item.name} - ${item.description||''}`);
    a.innerHTML=`
      <div class="avatar-wrap">
        <img src="${escapeHTML(item.avatar)}" alt="${escapeHTML(item.name)} avatar" loading="lazy" referrerpolicy="no-referrer">
        <div class="desc" aria-hidden="true">${escapeHTML(item.description||'')}</div>
      </div>
      <div class="meta">
        <div class="name" title="${escapeHTML(item.name)}">${escapeHTML(item.name)}</div>
      </div>
    `;
    const wrap=a.querySelector('.avatar-wrap');
    let shownOnce=false;
    wrap.addEventListener('mouseenter',()=>{if(!shownOnce){wrap.classList.add('reveal');shownOnce=true}});
    wrap.addEventListener('mouseleave',()=>{wrap.classList.remove('reveal');shownOnce=false});
    wrap.addEventListener('touchstart',(e)=>{e.preventDefault();const willShow=!wrap.classList.contains('reveal');wrap.classList.toggle('reveal',willShow);shownOnce=willShow},{passive:false});
    a.querySelector('img').addEventListener('error',(ev)=>{ev.target.src='data:image/svg+xml;utf8,'+encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400"><rect width="100%" height="100%" fill="#ddd"/><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="#555" font-size="22">${escapeHTML(item.name)}</text></svg>`)});return a}
  (function(){
    const root=document.getElementById('links-root');if(!root)return;
    LINKS_DATA.forEach(cat=>{
      const section=document.createElement('section');
      section.className='links-category';
      section.innerHTML=`<h2>${escapeHTML(cat.links_category)}</h2><div class="links-grid"></div>`;
      const grid=section.querySelector('.links-grid');
      shuffle(cat.list.slice()).forEach(item=>grid.appendChild(createCard(item)));
      root.appendChild(section);
    });
  })();
</script>
{% endraw %}

直接把上面的代码放进去就可以了,页面就做好了,再自己把收集的友链信息放进去,效果图如下(非常满意)

1

不过我发现了这样子之后博客加载速度会慢一些,所以我选择学习陆队,简约一点,直接放,用python脚本处理yml文件生成md表格

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import sys,yaml
from pypinyin import lazy_pinyin
p=sys.argv[1]if len(sys.argv)>1 else"_data/links.yml"
d=yaml.safe_load(open(p,encoding="utf-8"))
e=lambda s:(s or"").replace("|",r"\|").strip()
k=lambda n:(1,s)if(s:=''.join(lazy_pinyin((n or"").strip())).lower())[0].isdigit()else(0,s)
print("| Group | Name | Link |\n| --- | --- | --- |")
for b in d or[]:
    g=e(b.get("links_category",""));f=1
    for i in sorted(b.get("list",[]),key=lambda x:k(x.get("name",""))):
        print(f"| {g if f else''} | {e(i.get('name',''))} | {e(i.get('link',''))} |");f=0

waline评论

最经典的了,每次我都会弄这个,next主题的话需要安装一个插件,再直接把配置项加到next/_config.yml

1
npm install @waline/hexo-next
 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
# Multiple Comment System Support
comments:
  # Available values: tabs | buttons
  style: tabs
  # Choose a comment system to be displayed by default.
  # Available values: disqus | disqusjs | changyan | livere | gitalk | utterances
  active:
  # Setting `true` means remembering the comment system selected by the visitor.
  storage: true
  # Lazyload all comment systems.
  lazyload: false
  # Modify texts or order for any naves, here are some examples.
  nav:
    #disqus:
    #  text: Load Disqus
    #  order: -1
    #gitalk:
    #  order: -2
   
   
# 添加的部分   
waline:
  enable: true
  serverURL: 'https://waline.baozongwi.xyz/'
  avatar: 'mm'
  meta: ['nick','mail']
  pageSize: 10
  lang: 'zh-CN'
  visitor: false
  comment_count: true
  requiredFields: ['nick','mail']

赞赏支持

Licensed under CC BY-NC-SA 4.0