乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

在线Markdown编辑器正式上线啦

发表于 2025-10-25

前言

我个人用markdown写作居多, 偶尔外出时灵感爆发需要记录一些内容, 如果使用第三方工具, 比如有道云、掘金等, 其实也能实现需求

不过最大的问题还是在于数据迁移不方便, 尤其是日积月累数量越来越多, 万一哪天平台倒闭, 这些数据我还得手动一一拷贝出来?

长痛不如短痛, 为了解决数据存储的痛点, 决定自己开发一个markdown编辑器

纯静态网站, 数据可自定义存放于本地或者第三方GIT仓库, 支持多点存储, 确保数据长久稳定

网站最终长这样:

image-20251025221102259

image-20251025221122554

功能实现

  • 数据导入导出(支持单个或者批量导出, 支持导出成html和pdf格式)

  • 数据自定义存储(本地、Github、Webdav等, 支持多点存储)

  • 文档分类(文件夹功能)

  • 数据加密存储(可文明可加密)

  • 历史版本回退(支持本地数据和远程数据的回退)

  • 配置文件的导入导出

  • 网站纯本地运行 不涉及第三方后台 安全性高

  • 自定义文档模板

  • 支持图床功能(Github、Gitee等图床)

网站部署

直接将该仓库的代码上传到你自己的静态服务器上即可使用

网站示例: 点击进入

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

密码管理工具站正式上线啦

发表于 2025-10-12

前言

互联网时代要存储的密码实在太多, 脑袋压根记不过来, 只能借助外物, 比如存到便签里, 或者建一个Excel表格, 但是存在两个问题, 那就是安全性和便捷性不够

我的要求是随时随地都能查看、编辑、保存和新增密码, 无论是外出还是在家, 也不管是使用电脑还是手机, 可以进行无缝切换

其实苹果自带的密钥就很好用, 但是局限于苹果设备, 万一哪天换安卓了, 就很尴尬, 虽然支持云端存储, 但是不能导出到本地, 安全性和便捷性还是不足

便签的话更不用说了, 明文显示, 安全性极差

既然存到第三方平台不放心, 那就存本地好了, 比如本地自建Excel表格, 然后再进行加密压缩, 这样一来多端即时同步又是一个大麻烦, 每次有更新难不成都要手动拷贝替换一下?

为了解决以上的痛点, 于是乎, 我决定自己手搓一个密码管理器, 数据还是交给自己掌控最放心

目前工具已经上线, 欢迎大家来使用, 点击使用工具

密码管理器功能

  • 纯本地编辑, 不涉及第三方, 安全性高
  • 数据加密存储, 可自定义存放到本地、Github仓库、Webdav等, 支持多点存储
  • 数据导入导出(支持密文或者明文导出, 明文json格式)
  • 数据历史版本回退
  • 数据分类功能
  • 配置文件导入导出
  • Web跨平台形式, 有网就能用, 使用便捷(后期会逐步增加本地App)
  • 浏览器书签管理功能, 支持谷歌/搜狗浏览器书签导入

密码管理器使用

  1. 开启密码管理器, 输入密码

    这个密码需要牢记在心, 用于加密和解密数据

    image-20251013215328895

  2. 添加密码

    首次进入是没有数据的, 需要新增

    image-20251013215518471

    image-20251013215603826

    image-20251013215634839

  3. 进行存储配置

    新增的密码只是临时存放在本地浏览器, 你一旦换设备数据就会丢失, 我们需要配置一个存储源用于存放我们的密码数据

    这里我推荐使用Github仓库, 借助Git, 对于历史版本管理, 有着天然的优势

    我们需要在存储配置选项中, 选择Github作为存储源, 并设置仓库地址和访问token

    image-20251013220208898

    image-20251013220332714

    关于token(访问令牌)获取, 可以到你们自己的Github设置页面中生成, 这里就不再赘述:

    image-20251013220731282

  4. 密码数据同步

    配置到存储源后, 点击同步按钮即可将数据存储到你指定的仓库中:

    image-20251013221013054

    这里同步的数据是AES加密后的数据, 配合私有仓库, 安全性大大滴有😜

  5. 历史版本回退

    这个功能目前只支持Github仓库, 具体如下:

    image-20251013222314248

  6. 密码数据的导入导出

    image-20251013222649947

    所谓马有失蹄时 狡兔三窟, 假如哪天忘记了管理器的登录密码, 或者是需要修改登录密码怎么办, 数据岂不是无法解密了

    导入导出功能为的就是解决这个问题, 一方面是为了多地存储, 万一哪天Github崩了呢, 这也不是没有可能的事, 多备份几次总是没有错的, 当然后期我也会增加多点存储功能, 这是后话

    另一方面, 当我们需要修改密码的时候, 可以提前将数据导出, 然后用新密码登录, 接着导入数据, 最后同步数据即可, 不过 这样一来历史版本的数据就无法解析了, 这个问题还没想到解决方案, 所以建议大家在使用之前先仔细斟酌好登录密码

  7. 配置导出

    网站的偏好设置以及存储源的配置信息都可以单独导出, 方便跨平台使用

网站源码

网站已开源, 大家有需要也可以自行部署

源码地址: 点击进入

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

工具百宝箱正式上线啦

发表于 2025-10-10

前言

最近开发了一个工具站点, 旨在解决自己的日常需求, 希望也能帮助到大家

网站长这样:

image-20251011113506249

image-20251011113943287

image-20251011114040623

工具百宝箱: 点击进入

工具列表

目前已经集成的工具有:

图片工具

  • 图片转Word : 将图片中的内容转换为可编辑的Word文档,支持多种图片格式。
  • 图片无损压缩 : 压缩图片大小而不损失质量,支持PNG、JPG、WEBP格式。
  • 图片尺寸调整 : 调整图片尺寸,支持保持宽高比和多种尺寸预设选项。
  • 图片添加水印 : 为图片添加文字或图片水印,保护您的版权和内容。

文本工具

  • 二维码生成 : 生成自定义二维码,支持文本、URL、联系方式等多种内容。
  • PDF工具包 : PDF合并、分割、压缩和转换工具。
  • LRC转SRT : 将LRC歌词文件转换为SRT字幕文件。
  • 文本加密解密 : 使用AES算法加密和解密文本内容。
  • HTML压缩工具 : 将HTML代码压缩成一行,减少文件大小,提高加载速度。
  • 短链生成 : 将长URL转换为短链接,方便分享和使用。

音频工具

  • 歌曲BPM计算器 : 通过敲击空格键或点击按钮计算歌曲的每分钟节拍数(BPM)。
  • 混响时间计算器 : 根据BPM计算房间、板式和厅堂混响的预延迟和混响时间参考值。
  • 释放时间计算器 : 根据BPM值计算常见乐器的压缩释放时间参考值。
  • 音乐发行查询 : 查询歌曲在全球音乐平台的发行情况。

视频工具

  • m3u8视频下载 : 下载m3u8视频流并转换为MP4格式,支持批量下载。
  • 视频转换 : 转换视频格式,支持MP4、AVI、MOV等格式。
  • 在线直播 : 输入直播链接,实时观看在线直播内容。
  • 在线看电视 : 观看国内各大电视频道的直播内容。

其他工具

  • 复利计算器 : 计算复利投资收益,帮助您做出更明智的投资决策。
  • 复利逆推计算器 : 根据本金、最终资产和时间,计算年化收益率。
  • 每日新闻 : 浏览当日最新新闻简讯,了解时事动态。
  • 工作流系统 : 创建和管理自动化工作流程,可视化任务编排。
  • FC在线游戏 : 重温经典FC游戏,包含超级玛丽、魂斗罗等多款经典游戏。

总结

网站会持续更新和优化, 希望大家多多支持~

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

小霸王在线游戏机

发表于 2025-10-09

前言

童年的回忆, 闲暇之余玩一玩

在线游戏: 点击进入

image-20251010230556650

按键说明

手机端默认触屏,电脑端按键说明如下

按键 对应的电脑键盘
上 W
下 S
左 A
右 D
A J
B K
AA Z
BB X
Start Enter
Select Ctrl

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于分布式集群的搭建

发表于 2025-09-16

前言

如果自己购买服务器搭建分布式集群, 虽然流程繁琐, 但是成本相对可控, 不过所需服务器的数量不少, 至少7台起步, 运维压力还是有的

今天本着学习的目的, 来探讨一下搭建分布式集群的些事

服务器数量估算

针对单体应用

  • 两台服务器: 用作负载均衡
  • 两台以上服务器: 用于应用业务处理
  • 三台服务器: 其中两台用于数据库集群一主一从结构, 另外一台用作监控服务器, 出现故障时自动切换

也就是总共至少七台服务器 可实现了基础的分布式集群架构

针对微服务架构应用

  • 两台服务器: 用作负载均衡(API网关集群)
  • 十台服务器: 微服务两个组件起步, 每个微服务至少配置两台应用服务器和三台数据库服务器(一主一从一仲裁)
  • 三台服务器: 用作服务注册中心

微服务架构, 至少需要15台服务器

从单体应用改成微服务架构 服务器数据暴增 主要集中在数据库和应用上

使用托管方案

如果嫌自己购买服务器搭建集群麻烦, 那么单体应用可以考虑使用现成的高可用分布式集群全托管方案 比如阿里云SAE/ECI

它内置了负载均衡器和应用集群,我们只需要再购置一台云数据库(内含主从复制机制),然后上传开发好的程序即可

如此一来,可以大大减少运维消耗,把更多精力集中在应用本身 这是省时省力的做法

微服务架构同样也可以使用SAE来托管 除了该方案外,还有一些自由度更高的方案,比如MSE等

问题汇总

  1. 有必要给每个微服务设置独立的负载均衡器吗?

    给每个微服务都配置独立的负载均衡器是传统单体架构思维的延伸,它不仅会造成巨大的资源浪费和成本飙升,更会带来运维噩梦。微服务架构通过 统一入口 和 服务发现 机制,优雅地解决了这个问题。

    下面我通过一张图来对比两种模式的根本区别:

  2. 为了节省成本 是否可以将API网关和注册中心共用在两台服务器上?

    首先, 我们来看一下两种方案的对比图:

    除非是测试环境 或者想快速验证想法 否则 必须将API网关和注册中心分开部署, 尤其是生产环境,两台服务器部署网关+三台服务器部署注册中心是个可靠的选择

  3. 关于服务器系统的选择

    负载均衡器和数据库服务器选择CentOS,以获得最高的稳定性,应用服务器可以选择ubuntu以或者更新的软件版本

    以下是最小化配置参考, 用于项目起步阶段:

    • 两台负载均衡服务器: 系统选择centos+硬盘50g+弹性公网ip
    • 两台应用服务器: 系统选择ubuntu+硬盘80g+nat网关只进不出
    • 三台数据库: 系统选择centos+硬盘100g+完全内网 无需公网ip

成本估算

这里以一次性购买五年为例, 做一个费用估算:

  • 全托管方案: 阿里云SEA 两实例 2核2g每月600万cu消耗 折后资源包, 五年10000+数据库1核2g 硬盘80g 6600元=16600元

  • 半托管方案: 阿里云负载均衡器3504元+五台ecs5075元+带宽流量包最低450最高2100元=9029-10679元

  • 自建方案一: 七台ecs 7175元+按流量计费弹性ip+流量包450-2100=7625-9275元

  • 自建方案二: 七台ecs 7175元+2M固定带宽弹性ip1380元=8558元

  • 自建方案三: 使用DNS负载均衡, 两台各带1M带宽ecs 3653元+五台ecs 5075元=8728元

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于hexo文章数量过多导致编译内存不足的解决

发表于 2025-09-10

前言

文章数量过多, 执行hexo g渲染时报错, 如下:

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
<--- Last few GCs --->

[3128:0x102d59000] 3164514 ms: Mark-sweep 9136.8 (9211.6) -> 9124.1 (9213.4) MB, 4252.7 / 0.0 ms (average mu = 0.099, current mu = 0.022) allocation failure scavenge might not succeed
[3128:0x102d59000] 3168989 ms: Mark-sweep 9138.4 (9213.5) -> 9127.1 (9215.3) MB, 4402.9 / 0.0 ms (average mu = 0.056, current mu = 0.016) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

0: ExitFrame [pc: 0x1009d5fd9]
1: StubFrame [pc: 0x1009d6ead]
Security context: 0x1032be4808d1 <JSObject>
2: formatAttrs [0x10326c532831] [/node_modules/dom-serializer/index.js:~22] [pc=0x13101fad4423](this=0x1032ffa02da1 <JSGlobal Object>,0x10333f9ef9e1 <Object map = 0x1032643d71d9>,0x1032fa08d281 <Object map = 0x1032643ffae9>)
3: /* anonymous */ [0x103256ce9201] [/Use...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0x1011c9b35 node::Abort() (.cold.1) [/usr/local/bin/node]
2: 0x10009ca99 node::Abort() [/usr/local/bin/node]
3: 0x10009cbff node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
4: 0x1001ddb37 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
5: 0x1001ddad7 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
6: 0x1003659d5 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node]
7: 0x10036724a v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/usr/local/bin/node]
8: 0x100363c7c v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
9: 0x100361a7e v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
10: 0x10036d94a v8::internal::Heap::AllocateRawWithLightRetry(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
11: 0x10036d9d1 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/usr/local/bin/node]
12: 0x10033b60a v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/usr/local/bin/node]
13: 0x10068cb88 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/usr/local/bin/node]
14: 0x1009d5fd9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/bin/node]
zsh: abort hexo g

这是由于node.js内存限制导致的, 默认堆内存上限为1024MB

解决方法也很简单, 那就是加大堆内存上限, 有四种方案

解决方案

第一种 临时性配置

比如用以下命令来替代hexo g:

1
node --max-old-space-size=16384 ./node_modules/hexo/bin/hexo generate

这里--max-old-space-size属性的数值可以自定义, 我这里选择的是16G, 你也可以设置为8G, 也就是--max-old-space-size=8192, 以此类推

第二种 系统级全局配置

修改电脑上的node配置文件

  1. 第一步 打开launchd.conf配置文件

    1
    2
    # 编辑 Node.js 全局启动配置
    sudo vim /etc/launchd.conf
  2. 添加以下内容

    1
    setenv NODE_OPTIONS "--max-old-space-size=16384"
  3. 运行配置

    1
    2
    sudo launchctl load /etc/launchd.conf
    reboot # 重启生效
  4. 验证是否生效

    1
    echo $NODE_OPTIONS  # 应显示 --max-old-space-size=8192

系统级配置, 针对所有用户生效

内存大小的设置需要根据自己电脑的实际情况来定, 避免设置过高 从而导致导致系统整体性能下降

关于Mac平台的更新

由于 /etc/launchd.conf在新版macOS 中已被弃用,推荐使用以下方式:

  1. 创建或修改 launchd plist 文件(系统级)

    1
    sudo nano /Library/LaunchDaemons/com.custom.node.env.plist
  2. 添加内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>Label</key>
    <string>com.custom.node.env</string>
    <key>ProgramArguments</key>
    <array>
    <string>/bin/launchctl</string>
    <string>setenv</string>
    <string>NODE_OPTIONS</string>
    <string>--max-old-space-size=4096</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    </dict>
    </plist>
  3. 加载配置:

    1
    sudo launchctl load /Library/LaunchDaemons/com.custom.node.env.plist

第三种 用户级配置

通过修改环境变量的方式

  1. 编辑 shell配置文件

    1
    2
    3
    nano ~/.zshrc  # macOS Catalina 及以后版本
    # 或
    nano ~/.bash_profile # macOS Catalina 之前版本
  2. 添加以下行

    1
    2
    # 设置 Node.js 内存限制
    export NODE_OPTIONS="--max-old-space-size=4096"
  3. 使配置生效

    1
    source ~/.zshrc  # 或 source ~/.bash_profile

该配置仅对当前用户生效, 适合用户配置隔离

第四种 项目级配置(更安全)

在 Hexo 项目的 package.json中修改scripts:

1
2
3
4
"scripts": {
"build": "NODE_OPTIONS='--max-old-space-size=8192' hexo generate",
"serve": "NODE_OPTIONS='--max-old-space-size=8192' hexo server"
}

之后始终使用:

1
npm run build  # 代替 hexo generate

这算是一种一劳永逸的方案, 哪怕更换电脑也不怕, 而且进行了项目隔离, 不会影响到其他nodejs工程, 缺点是如果多个工程需要配置, 则得挨个添加

注意事项

如果运行后进程被终止, 比如报错:

1
zsh: killed     node --max-old-space-size=16384 ./node_modules/hexo/bin/hexo generate

主要原因是没有足够的物理内存 + 交换空间(swap)来满足需求,

首先运行top -o mem指令检查内存占用:

image-20250910100621554

随着node编译的进行, 我们会发现它的占用内存指标在不断上升,

iShot_2025-09-10_10.08.47

此时我们可以考虑通过关闭其他应用来给node足够的空间

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

一些电脑上比较好用的骚操作

发表于 2025-09-08

Chrome浏览器

  1. 划选链接并快速跳转访问

    原来的我们 需要划选链接Ctrl+V复制, 然后打开新窗口 在地址栏上使用Ctrl+V填入复制的地址, 最后回车访问, 实在是太繁琐

    而现在只需要划选链接Ctrl+V复制, 然后快捷键Ctrl+L聚焦地址栏, 紧接着Ctrl+V粘贴, 最后Alt+Enter, 即可直接跳转到新标签页访问, 是不是快了0.03秒😂

    没有操作 只有骚, 哈哈

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Astro来搭建静态网站

发表于 2025-09-07

介绍

Astro是一个基于JavaScript的静态站点生成器, 和Hexo有点类似, 支持Markdown构建内容, 但Astro性能会更好, 它具有独特的岛屿架构,按需加载JS,能显著减少初始加载时间, 非常适合需要快速首屏加载的场景比如如博客、营销网站、企业官网等等

Astro官网: 点击进入

环境搭建

这里以MacOs平台为例:

  1. 安装npm

    1
    brew install npm
  2. 安装nodejs

    这里指定nodejs版本为v18

    1
    npm install -g n

    然后

    1
    n v18

开始

  1. 创建工程模板

    1
    npm create astro@latest 工程名称

    image-20250907114519941

    根据提示一步步往下走即可

    image-20250907114710691

    完成后会在当前目录生成工程文件夹, 目录如下:

    image-20250907114814405

  2. 运行工程

    1
    npm run dev

    开启调试, 此时在浏览器地址栏输入http://localhost:4321/即可实时访问

    image-20250907123316643

  3. 打包静态文件

    工程编写完毕后, 即可输出网站静态文件

    1
    npm run build

    执行完毕后, 在工程目录下会自动生成dist文件夹

    image-20250907123606000

    将dist目录下的所有文件上传到你的静态服务器上就可访问了

Astro与React结合

Astro不仅可以和vue结合使用 还可以和React结合, 这里做一个简单Tailwind风格的网站演示

  1. 创建项目

    1
    npm create astro@latest my-toolbox -- --template framework-react
  2. 安装依赖

    1
    2
    3
    cd my-toolbox

    npm install @astrojs/tailwind tailwindcss react-dnd react-dnd-html5-backend
  3. 初始化Tailwind

    1
    npx tailwindcss init -p
  4. 配置Tailwind.config.js

    1
    2
    3
    4
    5
    6
    7
    export default {
    content: ['./src/*/.{astro,js,jsx,ts,tsx}'],
    theme: {
    extend: {},
    },
    plugins: [],
    }
  5. 配置astro.config.mjs

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import { defineConfig } from 'astro/config';
    import react from '@astrojs/react';
    import tailwind from '@astrojs/tailwind';

    export default defineConfig({
    integrations: [
    react(),
    tailwind({
    config: {
    applyBaseStyles: false,
    },
    }),
    ],
    server: {
    port: 3000,
    },
    build: {
    format: 'file',
    },
    });
  6. 编写主页

  7. 工作流页面

  8. 工具注册中心

工程目录结构介绍

以下是示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
src/
├── components/ # 可复用的UI组件
│ ├── ToolCard.astro # (或 .vue/.jsx)
│ └── Modal.astro
├── layouts/ # 页面布局组件
│ └── BaseLayout.astro
├── pages/ # 页面路由
│ ├── index.astro # 主页
│ ├── tool/ # 独立工具页面
│ │ ├── [toolId].astro
│ │ └── image-to-word.astro
│ └── workflow.astro # 工作流构建器页面
├── core/ # 核心逻辑
│ ├── tool-registry.js
│ ├── workflow-engine.js
│ └── storage-manager.js # 本地存储管理
└── styles/
└── global.css # 全局样式
public/ # 静态资源
├── images/
└── js/lib/ # 可能需要的第三方Wasm库等

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用vscode全局正则搜索并替换解决hexo语法报错

发表于 2025-09-06

前言

之前用python从网络爬了一些引流文, 在使用hexo渲染时出现大批量的报错, 如下:

1
2
3
4
5
6
7
8
{% raw %}
Nunjucks Error: [Line 103, Column 93] expected variable end
===== Context Dump =====
=== (line number probably different from source) ===

103 | <p>在Go的模板语法中,使用<code>range</code>关键字进行遍历,其中pipline的值必须是数组、切片、map或者channel。其语法以<code>{{range pipline}}</code>开头,以<code>{{end}}</code>结尾,形式如下:</p>
{% endraw %}
===== Context Dump Ends =====

该错误是由于Nunjucks模板引擎将文档中的双花括号{{}}误解析为模板语法导致的冲突

解决方案也很简单, 那就是在双花括号前后添加raw标签包裹, 如下:

1
{% raw %}{{xxx}}{% endraw %}  <!-- raw标签包裹 -->

其目的是告诉Nunjucks将花括号当做普通文本来显示

大批量替换

如果只是一两处修改还好, 问题是大量的文章存在这样的问题, 手动一一修改肯定不现实

要不写一个python脚本自动替换一下?

可是可以, 没有办法的情况下只能这么干, 不过目前来说大可不必, 我们其实可以借助IDE的全局正则搜索替换功能, 比如vscode

具体操作

  1. 打开替换面板 快捷键Ctrl+H (Windows/Linux) 或 Cmd+Option+F (macOS)

  2. 启用正则表达式模式 (点击.* 按钮或按 Alt+R)

  3. 搜索框输入:

    1
    2
    3
    4
    5
    {% raw %}
    `(\{\{[^{}]*?\}\})`
    或者
    `(\{\{+.*?\}\}+)`
    {% endraw %}
    • [^{}] 确保只匹配非花括号字符
    • *? 非贪婪匹配任意数量字符
  4. 替换框输入:

    1
    `{% raw %}$1{% endraw %}`
  5. 执行全部替换

image-20250906152802218

优化点说明:

  1. 排除嵌套情况:[^{}]确保不会错误匹配{{a{b}c}}这类嵌套结构
  2. 精确匹配:*?比.更安全,避免过度匹配
  3. 保留原格式:$1会保持原变量的大小写和特殊字符

特殊场景处理:

  • 若需包含换行符:改为[\s\S]*?
  • 若需排除特定前缀:使用(?<!prefix)\{\{

常见语法冲突字符

除了双花括号之外, 还有类似的字符也需要进行替换, 不然hexo渲染也会报错, 下面列举一些常见的需要去除或者替换的字符

hexo标题不允许出现以下字符:

1
2
3
4
:
|
"
`

hexo内容需要进行替换的字符:

1
2
3
4
5
6
7
8
9
10
11
12
{% raw %} 这个忽略
{{}}
{{ 未闭合标签也不行
{{{}}}
{{xxx}} xxx表示任意内容
{% if ... %}
{% endif %}
{% else %}
{% elseif %}
{% xxx %}
{#xxx} 正确写法应该是{#xxx#} 不然报错expected end of comment
{% endraw %}这个忽略

对于{% xxx %}的替换, 可以使用以下搜索正则表达式:

1
\{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\}

替换内容:

1
{% raw %}{%$1%}{% endraw %}

说明:

  • 使用(?:)非捕获组同时排除raw和endraw标签
  • \s*允许标签内可能存在的空格
  • 完整保留原始URL内容(通过$1引用)

image-20250906164948702

其他报错问题

  1. 提示标签未闭合

    1
    2
    Template render error: (unknown path)
    Error: expected end of comment, got end of file

    往往是因为出现了类似于{#xxx}的语法, 正确写法应该是{#xxx#}

    如果数量比较多 可以使用正则搜索替换:

    • 在搜索框中输入:\]+)\}
    • 在替换框中输入:``

如果碰上更复杂情况, 比如{#user,#user}, 也是会报错的, 这时我们可以使用增强表达式:

1
(?:^|(?<!\{% raw %\}))\{#([^#]*(?:#(?!\})[^#]*)*)\}(?!\s*\{% endraw %\})

替换成:

1
{% raw %}{#$1}{% endraw %}
  1. 提示unexpected token

    1
    2
    3
    4
    {% raw %}
    Nunjucks Error: [Line 94, Column 162] unexpected token:
    94 | <p>要想保证双花括号初始化不会出现内存泄漏的办法也很简单,只需要被 <code>static</code> 修饰即可,但这样做还是存在潜在的风险,可能会被某人不小心删除掉,于是我们另寻它道,发现了可以使用 Java8 中的 Stream 或 Java9 中的集合工厂 <code>of</code> 方法替代"{{"。</p>
    {% endraw %}

    问题处在未闭合的{{

    解决方案就是使用raw标签对花括号进行包裹

    如果数量比较多, 则依然使用正则全局替换, 在搜索框中输入以下正则表达式:

    1
    \{\{(?!(?:[^{}]*}}))

    然后在替换框中输入:

    1
    {% raw %}{{{% endraw %}

    表达式解释:

    • \{\{- 匹配 {{字面量(转义特殊字符)
    • (?!(?:[^{}]*}}))- 负向先行断言,确保后面没有 }}闭合标签
    • (?:[^{}]*}})- 匹配任意非 {}字符后跟 }}
    • ?!- 表示后面不能跟着这个模式

    这个正则表达式只会匹配未闭合的 {{ 标签,而不会匹配已闭合的 {{...}} 标签。

总结

根据上面的探讨, 我们来做一个整合

按照以下步骤依次替换 能解决90%以上的问题, 剩下的手动改一下即可:

  1. 第一步 替换带引号的{% xxx %}

    1
    `\{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\}`

    替换:

    1
    `{% raw %}{#$1}{% endraw %}`
  2. 第二步 替换带引号{{和}}

    搜索:

    1
    2
    3
    `\{\{`
    和
    `\}\}`

    替换:

    1
    2
    3
    `{% raw %}{{{% endraw %}`
    和
    `{% raw %}}}{% endraw %}`
  3. 第三步 替换带引号{{xxx}}

    搜索:

    1
    `(\{\{+.*?\}\}+)`

    替换:

    1
    `{% raw %}$1{% endraw %}`
  4. 第四步 替换{#xxx}

    搜索:

    1
    (?:^|(?<!\{% raw %\}))\{#([^#]*(?:#(?!\})[^#]*)*)\}(?!\s*\{% endraw %\})

    替换:

    1
    {% raw %}{#$1}{% endraw %}
  5. 第五步 替换不带引号的{{xxx}}

    由于没有引号限制, 覆盖的范围会更广, 包括代码和注释

    搜索:

    1
    (\{\{+.*?\}\}+)

    替换:

    1
    {% raw %}$1{% endraw %}
  6. 第六步 替换不带引号{% xxx %}

    搜索:

    1
    \{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\}

    替换:

    1
    {% raw %}{#$1}{% endraw %}

前三步可以放心大胆替换, 后面几步按需替换, 因为有些代码里面的花括号可以保留

补充

如果你想省事, 以牺牲文章部分内容和格式的前提下, 还有一种简单粗暴且有效的方法

那就是把整篇文章进行raw标签包裹, 也就是文章开头加一个raw标签, 文章结尾加一个endraw标签

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

如果从本地git仓库中恢复已经删除的子模块

发表于 2025-09-06

前言

先看看我的操作步骤

  1. 第一步 使用git init创键本地仓库

  2. 第二步 使用git submodule add -b master xxx添加子模块

  3. 第三步 手动删除了该子模块

    此时.git目录下文件依然存在

  4. 第四步 使用git commit提交并使用git push推送到远程仓库

这时, 需求来了 我想恢复子模块, 该如何操作?

假如我先进行commit再删除, 那么我直接使用git submodule update --init --recursive就能立马从.git本地仓库中检出恢复

可偏偏我是先删除后 再进行commit, 远程仓库肯定是不包含子模块的, 这时该怎么办呢?

问题解决

不用担心, 只要.git仓库中依然占用了存储空间, 意味着本地仓库还存在之前添加的子模块代码, 那我们就能从里面抓出来

只需要换个指令即可 如下:

1
git submodule add -b master -f git@github.com:xxx.git

这个命令不是从远程仓库重新拉取代码, 而是优先从本地检出, 无论文件删除是在commit前还是后都可用, 关键一定要加上-f, 否则没有效果

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

12…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

493 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%