正在加载...

更新博客的过程记录

2026/2/7 博客 开发 2.6k 字 12 分钟

最近觉得自己博客太单调,想加点新内容,过程稍微有点波折,故记录一下

首先是更新了markdown渲染器

原本自带的渲染器部分语法是渲染不了的,现在换成了hexo-renderer-markdown-it-plus

什么,你说为什么不是hexo-renderer-markdown-it?

由于我是在termux上写博客并推送的,其中难免遇到奇奇怪怪的问题,比如用hexo-renderer-markdown-it时,在配置文件里:

plugins:
    - markdown-it-github-alerts

hexo s一下,啪!立马报错
所以采用了hexo-renderer-markdown-it-plus

骗你的,hexo-renderer-markdown-it-plus对我现在hexo用的主题也没多好

我目前hexo用的主题是ParticleX Theme,这个主题自带语法高亮,必须禁用hexo自带的,然后我在配置文件里禁用了,依然会渲染错误代码块,根据hexo-renderer-markdown-it-plus在github上别人反馈的问题,需要手动更改库的代码更改内容如下:

// 在53-64行的开头和结尾加注释,例如这样
/*var pre_class = config['pre_class'];
    if(!pre_class) pre_class = 'highlight';
    checkValue(config, _res, 'highlight', function(str, lang) {
        if (lang && hljs.getLanguage(lang)) {
            try {
                return '<pre class="' + pre_class + '"><code class="' + lang + '">' + hljs.highlight(str, {language: lang, ignoreIllegals: true }).value + '</code></pre>';
            } catch (__) {}
        }
        return '<pre class="' + pre_class + '"><code class="' + lang + '">' + utils.escapeHtml(str) + '</code></pre>';
    }, function(str, lang) {
        return '<pre class="' + pre_class + '"><code class="' + lang + '">' + utils.escapeHtml(str) + '</code></pre>';
    });*/

这样对于我这主题就不会渲染出错了

为博客添加了live2d小人

这个倒是挺简单,运行下面命令:

npm install hexo-oh-my-live2d

也许有人要问,为什么不用hexo-helper-live2d

太老了,并且小人不会跟你说话,所以选择hexo-oh-my-live2d
配置文件如下,在_config.yml里:

OhMyLive2d:
  enable: true
  CDN: https://registry.npmmirror.com/oh-my-live2d/latest/files
  # CDN: https://registry.npmmirror.com/oh-my-live2d/0.13/files/dist/index.min.js
  option:
    # importType: 'cubism2' #  导入类型, 默认使用全量导入: complete , 可选值: complete, cubism2, cubism5
    libraryUrls: # 自定义 Cubism SDK 外部资源地址
      complete: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/complete.js
      cubism2: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/cubism2.js
      cubism5: https://registry.npmmirror.com/oh-my-live2d/latest/files/lib/cubism5.js
    # menus:
    # items: |
    #   (defaultItems)=>{
    #    return [
    #      ...defaultItems,
    #      {
    #        id: 'github',
    #        icon: 'github-fill',
    #        title: '我的github',
    #        onClick: ()=>window.open('https://github.com/hacxy')
    #      }
    #    ]
    #   }

    # items:
    #   - id: 'github'
    #     icon: 'github-fill'
    #     title: '我的github'
    #     onClick: ()=>window.open('https://github.com/k4641321')

    mobileDisplay: true # 是否在移动端显示
    models:
      - path: /live2d_models/chino/chino.model.json
        mobilePosition: [-10, 23] # 移动端时模型在舞台中的位置。 默认值: [0,0] [横坐标, 纵坐标]
        mobileScale: 0.1 # 移动端时模型的缩放比例 默认值: 0.1
        mobileStageStyle: # 移动端时舞台的样式
          width: 180
          height: 166
        motionPreloadStrategy: IDLE # 动作预加载策略 默认值: IDLE 可选值: ALL | IDLE | NONE
        position: [-10, 35] # 模型在舞台中的位置。 默认值: [0,0] [横坐标, 纵坐标]
        scale: 0.15 # 模型的缩放比例 默认值: 0.1
        # showHitAreaFrames: false # 是否显示点击区域 默认值: false
        stageStyle:
          width: 250
          height: 250
    parentElement: document.body #为组件提供一个父元素,如果未指定则默认挂载到 body 中
    primaryColor: 'var(--btn-bg)' # 主题色 支持变量
    sayHello: false # 是否在初始化阶段打印项目信息
    tips:
      style:
        width: 230
        height: 120
        left: calc(50% - 20px)
        top: -100px
      mobileStyle:
        width: 180
        height: 80
        left: calc(50% + 50px)
        top: -100px
      idleTips:
        interval: 1000
        message:
          - 你好呀~
          - 欢迎来到我的小站~
          - 要来点咖啡吗~
          - 你复制了什么内容呢?记得注明出处哦~
        # 自定义提示语 需要 引入 axios 库 ,也可以使用其他方法
        # message: |
        #   function(){
        #     return axios.get('https://v1.hitokoto.cn?c=i')
        #       .then(function (response) {
        #         return response.data.hitokoto ;})
        #       .catch(function (error) {
        #         console.error(error); });
        #   }
        wordTheDay: |
          function(wordTheDayData){
            return `${wordTheDayData.hitokoto}    by.${wordTheDayData.from}`;
          }
    then: |
      (oml2d)=>{
        setTimeout(() => {
          oml2d.tipsMessage('hello world', 3000, 10);
        }, 8000);
      }

模型来自这里

为文章加了字数统计和阅读时间

这个也挺简单,运行下面命令:

npm install hexo-wordcount

接着在主题文件的post.ejs里的第41行后面加上:

<!-- 添加字数统计 -->
        <span class="word-count">
            <span class="icon">
                <i class="fa-solid fa-file-word fa-fw"></i>
            </span>
            <%= wordcount(page.content) %> 字
        </span>
        <span class="reading-time">
            <span class="icon">
                <i class="fa-solid fa-clock fa-fw"></i>
            </span>
                <%= min2read(page.content) %> 分钟
        </span>

为博客增加了离开和返回的标题更改与点击效果

随便网上找个模版,新建一个js文件,放在 主题文件source/js下:

var OriginTitle = document.title;
 var titleTime;
 document.addEventListener('visibilitychange', function () {
     if (document.hidden) {
         // $('[rel="icon"]').attr('href', "/img/trhx2.png");
         document.title = '别走啊,再多看看呗(*´I`*)';
         clearTimeout(titleTime);
     }
     else {
         //$('[rel="icon"]').attr('href', "/img/trhx2.png");
         document.title = '欢迎回来ᴖᗜᴖ' //+ OriginTitle;
         titleTime = setTimeout(function () {
             document.title = OriginTitle;
         }, 2000);
     }
 });

点击效果同理:

(function() {
    var a_idx = 0;
    window.onclick = function(event) {
        var a = new Array(
            "Perfect",
            "Great",
            "Good",
            "Bad",
            "Miss"
        );

        // 创建元素并防止选中
        var heart = document.createElement("b");
        heart.onselectstart = new Function('event.returnValue=false');

        // 添加元素到页面
        document.body.appendChild(heart).innerHTML = a[a_idx];
        a_idx = (a_idx + 1) % a.length;
        heart.style.cssText = "position: fixed; left: -100%;";

        // 初始化动画参数
        var f = 16,                     // 字体大小
            x = event.clientX - f / 2,  // 横坐标
            y = event.clientY - f,      // 纵坐标
            c = randomColor(),          // 随机颜色
            a = 1,                      // 透明度
            s = 1.2;                    // 缩放比例

        // 动画定时器
        var timer = setInterval(function() {
            if (a <= 0) {
                document.body.removeChild(heart);
                clearInterval(timer);
            } else {
                heart.style.cssText = `
                    font-size: 16px;
                    cursor: default;
                    position: fixed;
                    color: ${c};
                    left: ${x}px;
                    top: ${y}px;
                    opacity: ${a};
                    transform: scale(${s});
                `;
                y--;          // 垂直位移
                a -= 0.016;   // 透明度衰减
                s += 0.002;   // 持续放大
            }
        }, 15);  // 15ms帧间隔
    };

    // 生成随机RGB颜色
    function randomColor() {
        return "rgb(" +
            ~~(Math.random() * 255) + "," +
            ~~(Math.random() * 255) + "," +
            ~~(Math.random() * 255) + ")";
    }
})();

layout.ejs第87行后面加上:

<script src="<%- url_for("/js/title.js") %>"></script>
<script src="<%- url_for("/js/click.js") %>"></script>

更改了加载动画,加载文字更改成故诗

layout.ejs中加了与更改:

<div id="loading" v-show="loading">
                <div id="loading-circle">
                    <div id="dynamic-saying">
                        <span class="default-text">正在加载...</span>
                    </div>
                    <!-- <p>加载过慢请开启缓存 浏览器默认开启</p> -->
                    <img style="width:75%;height:75%" src="<%- url_for(theme.loading) %>" />
                </div>
            </div>
<script>
        // 在页面加载时获取诗词并更新显示
        document.addEventListener('DOMContentLoaded', function() {
            const sayingElement = document.getElementById('dynamic-saying');
            
            // 从API获取诗词
            fetch('https://v1.jinrishici.com/rensheng.txt')
                .then(response => response.text())
                .then(data => {
                    if (sayingElement) {
                        sayingElement.innerHTML = `<span class="poem-text">${data}</span>`;
                    }
                })
                .catch(error => {
                    console.error('获取诗词失败:', error);
                    if (sayingElement) {
                        sayingElement.innerHTML = '<span class="poem-text">人生如逆旅,我亦是行人。</span>';
                    }
                });
        });
        
        // 额外的CSS样式,确保诗词显示效果
        const style = document.createElement('style');
        style.textContent = `
            .poem-text {
                font-size: inherit;
                font-weight: inherit;
                color: inherit;
            }
            .default-text {
                font-size: inherit;
                font-weight: inherit;
                color: inherit;
            }
        `;
        document.head.appendChild(style);
    </script>

评论系统恢复,使用了gitalk

这样避免免费的数据库因为没用给我收回去了
但配置好遇到了一个问题,如果lable标签超过50个字符,无法评论,网上查了使用md5编码以解决,但有人反馈还有问题
test3文章中,测试了评论发现标签为/2025/11/20/test3/,对于我来说,只有知道文章标题就够了
我直接问deepseek

我想id只保留文章标题,不要前面路径

ai还是太好用了
deepseek给出了如下方案:

  • 使用文章标题
<script>
    const gitalk = new Gitalk({
        clientID: "<%- theme.gitalk.clientID %>",
        clientSecret: "<%- theme.gitalk.clientSecret %>",
        repo: "<%- theme.gitalk.repo %>",
        owner: "<%- theme.gitalk.owner %>",
        admin: "<%- theme.gitalk.admin %>".split(","),
        language: "<%- theme.gitalk.language %>",
        id: "<%- page.title %>", // 直接使用文章标题
        <% if (theme.gitalk.proxy) { %>
        proxy: "<%- theme.gitalk.proxy %>",
        <% } %>
    })
    gitalk.render("gitalk-container");
</script>
  • 使用slug 我也不知道这是啥,能用就行
<script>
    const gitalk = new Gitalk({
        clientID: "<%- theme.gitalk.clientID %>",
        clientSecret: "<%- theme.gitalk.clientSecret %>",
        repo: "<%- theme.gitalk.repo %>",
        owner: "<%- theme.gitalk.owner %>",
        admin: "<%- theme.gitalk.admin %>".split(","),
        language: "<%- theme.gitalk.language %>",
        id: "<%- page.slug || page.title %>", // 优先使用slug
        <% if (theme.gitalk.proxy) { %>
        proxy: "<%- theme.gitalk.proxy %>",
        <% } %>
    })
    gitalk.render("gitalk-container");
</script>
  • 清理路径获取纯标题
<script>
    // 从路径中提取标题
    function getTitleFromPath(path) {
        // 去除路径中的日期部分(如:/2024/01/01/title/)
        const pathSegments = path.split('/').filter(segment => segment);
        // 返回最后一个非空段,通常是标题
        return pathSegments[pathSegments.length - 1] || 'default';
    }
    
    const gitalk = new Gitalk({
        clientID: "<%- theme.gitalk.clientID %>",
        clientSecret: "<%- theme.gitalk.clientSecret %>",
        repo: "<%- theme.gitalk.repo %>",
        owner: "<%- theme.gitalk.owner %>",
        admin: "<%- theme.gitalk.admin %>".split(","),
        language: "<%- theme.gitalk.language %>",
        id: getTitleFromPath(location.pathname), // 使用处理后的标题
        <% if (theme.gitalk.proxy) { %>
        proxy: "<%- theme.gitalk.proxy %>",
        <% } %>
    })
    gitalk.render("gitalk-container");
</script>
  • 使用文章的唯一标识
<script>
    // 使用日期+标题的组合确保唯一性
    function getArticleId() {
        // 如果有页面元数据,使用日期+标题
        <% if (page.date && page.title) { %>
            return "<%- page.date.format('YYYY-MM-DD') %>-<%- page.title %>";
        <% } else { %>
            return "<%- page.title %>";
        <% } %>
    }
    
    const gitalk = new Gitalk({
        clientID: "<%- theme.gitalk.clientID %>",
        clientSecret: "<%- theme.gitalk.clientSecret %>",
        repo: "<%- theme.gitalk.repo %>",
        owner: "<%- theme.gitalk.owner %>",
        admin: "<%- theme.gitalk.admin %>".split(","),
        language: "<%- theme.gitalk.language %>",
        id: getArticleId(), // 生成唯一的id
        <% if (theme.gitalk.proxy) { %>
        proxy: "<%- theme.gitalk.proxy %>",
        <% } %>
    })
    gitalk.render("gitalk-container");
</script>

我选择了slug的方案,最后评论的标签像这样:
APlayer配置留存
能用👍🏻

至此,博客更新结束