当前位置: 首页 > article >正文

Hexo 博客无法复制 Markdown 本地图片?我写了一个插件

不知道现在大家写博客、文章还多不多我一直在用 Obsidian Markdown 写文章然后用 Hexo 生成静态站点发布到 GitHub Pages绑定到域名 xiaoming.io。几年前我写过一篇文章分享我是怎么构建笔记和博客系统的。构建自己的笔记博客系统程序员版 | 搬砖的小明遇到问题最近我在 Obsidian 里面用了一个新插件它会把我本地的图片转成 WebP 格式保存。这样能大大节省存储空间图片画质也还不错。用了 WebP 之后我发现原先那套发博客的代码只支持JPG、PNG、GIF没有正常把 WebP 图片复制到发布目录里。我的第一反应是让 Codex 直接帮我解决这个问题它 Debug 了半天没有什么进展看来还是需要我人工参与一下。我又重新研究了一下 Hexo已经很多年没研究它了。之前它有个问题在本地写 Markdown 时如果用相对路径引用本地图片在有些情况不会把图片复制到public目录。几年前为了解决这个问题我魔改了 Markdown 的渲染器也就是hexo-renderer-markdown-it。在它解析完图片以后我会把每一张图片都复制到固定目录同时修改渲染的图片 URL 让其对应上。当时之所以这么做是因为我发现 Hexo 本身的 API 不会把每个 post 里的图片都暴露给我。为了拿到一篇 Markdown 里所有图片的路径我就不得不在渲染器里插一段自己的代码来实现这个效果。但这种实现思路非常不好耦合性太强。我改了现有渲染器以后只要渲染器一更新我又得重新改。这么多年来我一直用的都是旧版本渲染器没有更新。最近我又看了一下时隔多年Hexo 还是没有原生很好的解决这个问题。尽管它有一个post_asset_folder参数但这个参数只支持和 Markdown 文件同名的文件夹里的图片上传也就是推荐在 Hexo 里面创建 Markdown这太局限了。https://hexo.io/zh-cn/docs/asset-folders我也尝试在网上找现成插件确实有一些插件支持这个功能例如hexo-asset-image但这个项目已经无效并且不维护了。有人Fork了一个版本修复但是看起来和我想要的效果不太一样。决定重新开发第一版所以我决定让 Codex 帮我开发一个。我本来不知道这件事会不会很复杂没想到 Codex 直接帮我写了一个不到 100 行的 script放进项目里以后图片确实就能复制了比我原先的实现优雅很多。Codex 的实现思路很直接就是拿到 Markdown 源文件然后用几个正则表达式去找里面所有图片再把它们复制到目标目录。其实当年我一开始想到的也是这种方式。正则表达式比较难写担心写错识别出错误图片或者漏掉所以当时就直接走了魔改 Markdown 渲染器这条路快速把问题解决了。但在今天AI 写代码已经这么强了让 Codex 直接实现一个新的插件反而是一个更快、更简单的办法。于是我把这个插件发布到了 NPM 上也把我原来那个魔改插件去掉了重新改回原版的 Markdown 渲染器并且升级到了最新版。后来我又去 Hexo 的 GitHub 主页看了一下到现在还是一直有人提这个问题。我把这个插件网址回复在了那个 GitHub Issue 里。不知道这些提 Issue 的人现在还在不在用 Hexo 写博客还是已经迁移到别的工具上了。发现更多问题第二版当我实际用这个插件时发现它对图片的判断还是太简单了。Markdown 里引用图片有很多种情况。大概有这么几类相对路径比如当前目录、子目录或者父目录里的图片绝对路径比如以斜线开头的 Linux 路径或者 Windows 上带盘符的路径不是本地文件路径的情况比如data:这种 Base64 形式、#开头的路径或者http、https这种链接我去和 Codex 讨论它只处理了https链接等场景还有一些场景都没有处理。于是我就和 Codex 继续讨论把我想到的场景都补充进去了也写了针对这些场景的测试代码。写 test 也有一些细节。因为这是一个 Hexo 插件理论上最彻底的测试方式应该是端到端测试准备一个真实的 Hexo 环境放一些测试用的 Markdown 文件运行插件和编译过程再判断处理结果对不对。但 Codex 认为这样做会依赖 Hexo 的版本太重了比较容易出现兼容问题。所以它建议我用集成测试Mock 一个假的 Hexo 环境调用整个插件判断它是不是按照设计的方式工作有没有准确复制 Markdown 文件里引用的图片。当时我觉得 Codex 说的有道理集成测试也就够了因为主要是测试这些格式的解析逻辑。于是第二版就发出来了。更全面系统的设计第三版在我写这篇文章的时候又去网上搜了一些相关的资料包括 Hexo 官方文档我发现事情没有这么简单。例如 Hexo 里relative_link的配置选项可能会导致渲染不一样还有些用户可能会在图片文件名里有特殊字符等。我觉得有必要用更系统化的方式去实现这个工具。在之前我用 AI 做过好多个小工具说实话这个应该是真实解决现实问题当中功能最简单的一个项目。但是正因为它是最简单的一个我反而可以更清晰地学习如何用 AI 开发项目。因为它每一个步骤都相对简单我可以把重点放在思考开发流程上而不是让注意力陷入过多设计实现细节里出不来。同时它也不是简单到完全不需要思考的程度它也在解决一个有多种可能分支的现实问题有一定的研究价值。1、确定核心目标首先是理清这个项目的核心目标。核心目标的重点不只是这个项目要做什么还要关注这个项目不做什么。这个项目的名字叫hexo-relative-post-image顾名思义它的核心目标应该是只处理相对路径引用的图片文件。如果是绝对路径我们直接不处理并且在 log 里面报一个 warning通知用户自行处理。我们的设计思路是只做图片复制不去干涉 Markdown 渲染成 HTML 的过程。2、确定调研方向并调研确定了这个核心目标以后我们需要对 Markdown 有关的东西进行足够深入、系统的调研。这里面包括 CommonMark 对 Markdown 语法的规定是什么样的、支持什么样的图片引用方式。现有的 marked 和 markdown-it 这两个渲染器是怎么实现 Markdown 图片渲染的这两个渲染器在 Hexo 上又有什么样的图片相关的配置参数。目前已有的 Hexo 渲染器用户都报了什么样的 Issue能从这个 Issue 里面学习到哪些兼容性问题。我让 AI 把这些调研来源和结果都放在了 Reference 文件中。3、Spec 开发在这个调研完成以后就需要做一个详细的需求文档一般称为 Spec (Specification产品规格)。这个 Spec 里面除了有项目的核心目标还有从调研结果学来的东西有哪些语法格式需要考虑有哪些可能的兼容性问题需要处理。根据我们前面定的核心目标有些兼容问题是可以在插件里处理的而有些兼容问题则是和我们的设计目标冲突的应该不做处理而是直接报错抛给用户例如绝对路径引用图片。一开始我并没有把这个项目当成一个正经项目去做只是从一个 100 行的小脚本慢慢补全了所以前面的版本也没有 Spec。但是现在既然要更系统地实现这个项目Spec 就是必要的。一开始都是跟 AI 用几句话来描述需求但是当需求的边界条件、各种分支越来越多几句话就描述不清楚了。如果下次需要 AI 修改维护Spec 就是最重要的依据。聊天结束了上下文就没了而 Spec 是以文件形式保存在项目里的一直在。4、代码实现有了这个 Spec 以后才是写代码代码分为插件本身的实现代码和测试代码两块。实际上这个插件本身的代码量并不是很大只有一个几百行的文件。但它的文档以及它的测试代码反而比实现代码更复杂。5、测试在测试代码的实现上之前的集成测试也满足不了需求了因为现在已经明确发现了不同的渲染插件可能也会有兼容性问题。所以我让 AI 又加了真正的端到端测试直接调用 Hexo 去验证兼容性问题。6、README 文档最后还有一个精简的 README是中英双语版的为了更加国际化默认英文版。README 分为两块。1、给普通用户看的要告诉用户怎么配置这个项目支持什么场景什么是不支持的。2、给想要参与开发项目的人和 AI 看的。会介绍环境配置、开发约定、具体的发布流程。实际上我的开发和发布都是让 AI 完成的这个时候文档就非常重要了如果没有文档AI 没办法每次都按照固定的流程开发和发布项目到时候就乱了。一点思考这是一个很简单的小项目用 AI 帮忙写也很轻松。但你会发现即使是这样的小项目也还是需要人工参与而且人工参与的程度并不低。这不是我不会用 AI而是很多实际问题本身就带着一堆隐性的背景知识。比如 Markdown 引用图片这件事由于Markdown编辑器五花八门用户真的会用各种奇奇怪怪的方式去写不只是标准语法还可能有 HTML 标签、文件名有特殊字符、不同语法格式、网络图片甚至不同渲染器还有自己的扩展。这些东西本身就没有一个固定范围。AI 默认不会把这些情况全都想一遍它一般只会给你一个“常见写法”的方案而不会一上来就帮你把所有边界情况都覆盖掉。如果要让 AI 自主探索所有可能的情况复杂度可能会指数级增加。这时候人的作用就体现出来了。我会用自己的经验去引导 AI比如我会想到要看现有生态比如 CommonMark 语法规范Marked、Markdown-it 这些主流渲染库相似插件以及它们的 Issue 里别人踩过的坑。这些东西 AI 不是查不到而是如果你不说它通常不会主动意识到“这一步是必要的”也不会自己把这些上下文串起来。本质上就是有些问题需要很大的上下文才能想清楚而这些上下文很多是隐性的不是直接搜就能出来的。人能做的是主动把这些上下文补上确定问题范围AI 更擅长的是在这个范围里面把事情做快、做全。那么利用 AI 开发项目的过程就是这样的1、我会利用我的知识经验引导 AI 去做调研确定问题范围让 AI 写 Spec写完了我再核查再让它修改直到 Spec 达到我比较满意的程度。2、让 AI 根据 Spec 把代码实现出来。理论上只要 Spec 写得足够完备代码实现就已经不重要了不需要太多人工参与就能被 AI 自动完成。甚至可以把 AI 当成编译器来看待AI 把 Spec 编译成代码就像过去编译器把高级语言编译成机器码一样。3、在编译过程中如果由于 Spec 写的有硬性的逻辑问题导致编译报错或者最终运行出来的效果和设想的不一样我不会单独去干预代码而是去完善 Spec然后重新编译成代码可以是增量编译的过程不用全部重写。整个项目的维护核心从过去的代码开始转向 Spec。用 AI 的话来说Spec 是 Single Source of Truth。Spec 可能需要花很长的时间去开发并且它是人工参与程度最高的文件。之后无论是实现代码还是测试代码还是 README只要有不对的就应该从 Spec 里面找参考依据。每次修改项目的时候都应该先改 Spec然后才是代码和 README。项目链接如果你也在用 Hexo遇到类似问题没解决可以留意一下这个插件。我发现似乎还有人在用我以前开发的那个版本的 Markdown 渲染器因为我看到 NPM 上还有下载量。我把原先那个项目标记成了 Deprecated也链接到了这个新项目。如果你是单纯想了解这个项目的 Reference、Spec 和 Test 是怎么写的也可以在项目中看到。这个项目的 GitHub 主页在这里https://github.com/jzj1993/hexo-relative-post-images如果觉得文章有帮助欢迎分享转发也欢迎关注我的公众号“搬砖的小明”及时获取更新

相关文章:

Hexo 博客无法复制 Markdown 本地图片?我写了一个插件

不知道现在大家写博客、文章还多不多,我一直在用 Obsidian Markdown 写文章,然后用 Hexo 生成静态站点发布到 GitHub Pages,绑定到域名 xiaoming.io。 几年前我写过一篇文章,分享我是怎么构建笔记和博客系统的。 构建自己的笔记…...

王杨安企cms:批量3000个游戏下载指定链接导入方法!

我只做游戏下载站和其他管道项目,今天就简单讲解一下如何用安企cms下载站模板,批量导入几千个游戏指定下载链接!其他老站长一般都是用api接口,但是接口对于入门的新手有难度,我也是入门级的新手,所以只说入…...

mysql主从配置作业 一主一次

一、环境要求主:192.168.211.138从:192.168.221.139二、配置主1.添加vim /etc/my.cnflog-binmysql-bin server-id12.重启数据库生效systemctl restart mysqld3.建立同步账号【1】创建用来传输数据的账号create user repl192.168.211.% identified by rep…...

打造优雅的园艺社交互动界面:基于 Vue 的小程序开发实践

在园艺类小程序的开发过程中,互动反馈模块是提升用户体验的核心环节。点赞记录、关注列表、评论详情作为用户高频查看的内容,其界面设计和交互逻辑直接影响用户留存。本文将分享基于 Vue(uni-app)开发这三类互动界面的实践思路&am…...

计算机毕业设计 | vue+SpringBoot凌云在线阅读平台 图书借阅管理系统(附源码)

1, 概述 1.1 课题背景 随着现在科学技术的进步,人类社会正逐渐走向信息化,图书馆拥有丰富的文献信息资源,是社会系统的重要组成部分,在信息社会中作用越来越重要,在我国图书馆计算机等 信息技术的应用起步…...

为什么你的HR数字化项目总失败?AGI原生架构 vs 传统RPA的5维能力对比(附Gartner最新评估矩阵)

第一章:AGI的人力资源管理应用 2026奇点智能技术大会(https://ml-summit.org) AGI(通用人工智能)正从理论探索加速迈向组织级落地,人力资源管理成为首批实现深度价值转化的核心场景之一。不同于传统AI在HR中的单点应用&#xff0…...

如何从图表图像中提取精确数据:WebPlotDigitizer的完整指南

如何从图表图像中提取精确数据:WebPlotDigitizer的完整指南 【免费下载链接】WebPlotDigitizer Computer vision assisted tool to extract numerical data from plot images. 项目地址: https://gitcode.com/gh_mirrors/we/WebPlotDigitizer 你是否曾面对一…...

5G流量卡科普与避坑指南:如何选择正规号卡

在日常使用中,很多人都会用到备用流量卡、副卡,尤其是经常外出、多设备联网的用户。但市面上流量卡种类繁杂,虚量、限速、合约坑、售后不稳等问题层出不穷。本文做一次全面科普,帮助大家分清类型、避开陷阱,理性选择适…...

HarmonyOS原子化服务:轻量化应用的未来形态

这里写自定义目录标题HarmonyOS原子化服务:轻量化应用的未来形态引言:移动应用范式的第三次革命第一章:原子化服务的哲学思辨与技术演进1.1 从“应用商店”到“服务生态”的范式转移1.2 原子化服务的技术架构演进第二章:服务卡片&…...

避开这些坑!CMOS环形振荡器版图设计与LVS匹配实战心得

CMOS环形振荡器版图设计避坑指南:从LVS匹配到61反相器布局实战 在集成电路后端设计的深水区,环形振荡器的版图实现往往成为区分"理论正确"与"生产可用"的关键门槛。当你的原理图仿真曲线完美无瑕,却在物理实现阶段遭遇LV…...

从电赛到实战:基于OpenMV与STM32的视觉追踪小车系统设计

1. 视觉追踪小车的核心设计思路 第一次接触视觉追踪小车是在大三的电赛备赛期间,当时看到学长做的自动跟随机器人特别酷,就决定自己动手做一个。经过两个月的折腾,终于实现了基于OpenMV和STM32的视觉追踪系统。这个项目的核心在于让机器像人眼…...

LangChain学习笔记--Model I/O 模块部分 1.5 Prompt Template(提示词模板)

LangChain学习笔记–Model I/O 模块部分 1.5 Prompt Template(提示词模板) ‍ 介绍 ​Prompt Template​ 可以理解为一种“提示词模板”。来自langchain_core.prompts中 它的核心是:把固定的提示内容先写好,并预留几个…...

STTN算法研究

STTN(Spatial-Temporal Transformer Network,空间-时间变换网络)是一种前沿的深度学习架构,专为视频修复任务设计,特别在处理动态场景下的字幕去除、物体移除等应用中展现出卓越性能。与传统专注于静态图像修复的算法不同,STTN通过联合建模空间和时间维度的信息,有效解决…...

5G/4G流量卡技术原理与合规选购实战(2026最新)

随着移动互联网、物联网、远程办公的普及,流量卡(数据卡、上网卡)成为很多用户的刚需。但市面上产品鱼龙混杂,虚量、限速、封卡、售后失联等问题频发。本文从技术原理、合规标准、选购要点、平台选择四个维度,做一次完…...

Wan2.2-I2V-A14B与Dify集成:打造无需编码的AI视频工作流

Wan2.2-I2V-A14B与Dify集成:打造无需编码的AI视频工作流 1. 引言:让业务人员也能玩转AI视频生成 想象一下这样的场景:电商运营团队需要为上千款商品制作短视频,传统方式需要设计师逐一手动制作,耗时耗力。而现在&…...

【IdraScriptsParker】软件启动报错“Run-time error ‘429‘ :ActiveX component can‘ t create object”解决方案

IdraScriptsParker软件启动报错429解决方案IdraScriptsParker软件IdraScriptsParker软件存放位置打开注册表注册到电脑复制GEM.dll文件并且注册相关资料下载地址IdraScriptsParker软件 一款意德拉IDRA压铸机厂家在旧系统使用的一款数据采集、状态监控、数据接收的一个通讯框架…...

单片机c语言入门

本书是一本专为单片机初学者设计的入门教材,内容详实且易于理解。书中通过丰富的实例和时亮困此施丝圆织改通俗易懂的语言,帮助来自读者快速掌握单片机C语言的基础知识。 360百科书中首先介绍了MCS-51单片机的基本概念,随后详细讲解了C51语言…...

CentOS 7 解决每次开机需手动执行 【dhclient ens33】才能联网问题(永久方案)

一、问题现象 在使用 CentOS 7 虚拟机时,你可能会遇到这样的困扰: 每次重启系统后,执行 ip addr 查看网卡信息,ens33 网卡没有 IPv4 地址,无法联网。 必须手动执行 dhclient ens33 命令,才能临时获取IP地址…...

C语言环境搭建指南

学习计算机的人大多接触过C语言,它常被视为编程入门的首选语言,经典的Hello World程序便是许多人的第一段代码。掌握一门语言前,首先需要搭建合适的开发环境。对于C语言而言,选择合适的编译器和编辑工具尤为关键。通过安装集成开发…...

Paper 深读 | LLM驱动的多智能体分层决策新范式

**🔑 关键词:**分层决策、LLM规划、Bandit探索、多智能体导航 **🔥 一句话标签:**首创"LLMBandit分布式RL"三层自治体系,显著提升多智能体复杂任务的规划、探索与协作效率 02 一句话核心思想 针对多智能体…...

基于Simulink的开关磁阻电机(SRM)非线性转矩脉动抑制

目录 手把手教你学Simulink ——基于Simulink的开关磁阻电机(SRM)非线性转矩脉动抑制 一、引言:为什么SRM需要“脉动抑制”? 二、SRM非线性特性与脉动根源 1. 转矩产生机理 2. 非线性电感模型(核心!&a…...

OneNet平台生成token注意事项

1、如果生成的是设备级鉴权 设备级鉴权时,res字段为products/{产品id}/devices/{设备名},key为设备级key key里面填的应该是设备的密钥生成token的工具截图2、如果生成的是产品/用户级鉴权 产品级鉴权时,res字段为products/{产品id}&#xff…...

学Simulink——基于Simulink的轴向磁通电机多物理场耦合仿真​

目录 手把手教你学Simulink——基于Simulink的轴向磁通电机多物理场耦合仿真​ 摘要​ 一、背景与挑战​ 1.1 为什么轴向磁通电机的仿真让人“头秃”?​ 1.2 核心痛点与设计目标​ 二、系统架构与核心控制推导​ 2.1 整体架构:跨越维度的“降阶打击”​ 2.2 核心数学推…...

关于application.yml不起效或者文件图像变了

右击resource文件夹...

基于安卓的 WAV 音频采集方案_含工具

基于安卓的 WAV 音频采集方案_含工具 一、目的 采集16k 采样率 pcm 的音频; WAV / 16bit / 16000 Hz / 1ch (单通道)安卓手机不会直接给3路原始信号,系统内部已经做了降噪和波束成形,以及AGC, 我们一般只能拿到单通道或伪双通二、…...

C++运行时多态深度解析:从原理到实践

引言在上一篇文章中,我们介绍了虚函数的基本概念和规则。今天,我们将深入到底层,探究运行时多态的实现原理——虚函数表(vtable)和虚函数指针(vptr),以及与之密切相关的静态联编与动…...

简历怎么写:我做了什么,取得了什么成果,凸显JD 关键词

简历怎么写:我做了什么,取得了什么成果;凸显JD 关键词 这里写目录标题 简历怎么写:我做了什么,取得了什么成果;凸显JD 关键词 一、先搞清楚:HR到底是做什么的? 二、HR是怎么筛选简历的?说出来你可能不信 1. 关键词!关键词!关键词! 2. 这些信息,写了反而减分 3. 一…...

手把手教你用VMware Workstation 17 Pro给笔记本装个华为openEuler(附UKUI桌面安装避坑指南)

在VMware Workstation 17 Pro上体验openEuler:从安装到UKUI桌面的完整指南 最近两年,国产操作系统的发展势头越来越猛,不少技术爱好者都想亲自体验一下这些系统。作为华为推出的开源操作系统,openEuler凭借其出色的性能和丰富的生…...

D3KeyHelper暗黑3技能连点器:从零开始掌握智能自动化战斗

D3KeyHelper暗黑3技能连点器:从零开始掌握智能自动化战斗 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 想要在暗黑破坏神3中轻松实现技…...

AI Native 时代的 CI/CD:从“手工流水线”到“智能驾驶舱”的范式演进

引言:流水线的“幽灵” 如果把软件交付比作造汽车,很多团队目前的现状是:虽然用上了最先进的零件(AI 辅助编程、云原生架构),但他们的流水线(CI/CD)却依然停留在“老解放牌机床”的水平。 你可能深有体会: Jenkins 脚本如乱麻,各路工具拼凑出的流水线像打满了补丁的…...