修复了 Firefly 隔离坏图文章的脚本,顺手填了五个坑
实在不知道写什么,水一篇之前修复的脚本吧~
Firefly 仓库里有个 scripts/quarantine-bad-posts.mjs,作用挺直接:扫一遍 src/content/posts,把引用了不存在图片的文章挪到 _quarantine/。下划线开头的目录 Astro 不构建,裂图文章就进不了站点。我加它原本是图省事——文章越写越多,有回重构了资源目录,老文章里的相对图路径断了,构建出一堆裂图,我不想手动翻。
脚本大概是这么条流水线:
结果它自己先出问题。第一次是我刚挪完图片目录,跑脚本想隔离坏图文章,构建完裂图还在,它报「0 篇隔离」,我没当回事。第二次更离谱:写了篇插图教程,正文拿代码块演示插图语法,跑完那篇教程直接被挪进隔离目录,没了。
这时候我才反应过来是脚本本身有毛病,不是我图片的锅。于是从头读了一遍,五个坑挨个填,提了上游 PR #564。
walk 只收 index.md
原递归判断 f === "index.md" 才收。可 Firefly 的文章目录三种形态混着用:专题子目录下的 index.md、顶层直接丢的 xxx.md、还有 .mdx。后两种全漏了——裂图要是出在顶层 .md 或任意 .mdx 上,脚本永远发现不了,还跟你报「一切正常」。我改成 md/mdx 都收,目录结构也留着,后面算相对路径还指着它。
api 随机封面和远程图被当坏图
data.image 可能是主题内置的 "api"(随机封面,根本不是文件路径),也可能是 https:// 外链。原代码只要 typeof 是 string 就当本地路径去 existsSync,这些全被判成图没了,文章白隔离。我抽了个 isExternalUrl,把 http(s)、协议相对的 //、data:/mailto: 这类 scheme 都算外链,frontmatter 和正文共用一份判断,api 单独跳过。
协议相对的 //cdn.x/img.png 在 Node 里既不是 http 也不是 https,但浏览器加载时是外链,这个得单独算,不然又会误判。
正文里的示例代码被算成引用图
扫正文用的是  正则,可教程文章经常拿示例路径演示语法,那段在行内代码里,路径根本不存在。原脚本不分青红皂白全提,这类文章全被误隔离。我加了个 stripCode,先把围栏块、行内代码、还有「前面是空行的缩进块」删掉再提图。
一篇 frontmatter 写崩,整轮跟着死
matter(raw) 原本写在外层,某篇 frontmatter 有重复 key 或 date 格式不对就抛错,整个脚本 process.exit。这比漏扫还难发现:一篇炸了后面全没扫,你以为跑完了其实只跑一半,裂图照样漏进构建。我包了层 try/catch,解析失败的这篇打印告警、照样隔离,然后继续跑下一轮。
Windows 上文件其实没挪走
移动用的是 file.replace(POSTS_DIR, QUARANTINE_DIR)。Linux 上 POSTS_DIR 是正斜杠,没问题;Windows 上 path.join 出来反斜杠,而 POSTS_DIR 字面量是正斜杠,replace 匹配不上,target 变成错路径,renameSync 要么抛异常要么挪到奇怪地方——看着像处理了,源文件其实还在原位,下次跑又隔离一遍。改成 path.relative 算相对路径、再 path.resolve join 回去,跨平台都能用了。
修完我把这脚本接进本地构建前的自检,顺手让它隔离时多打印一份缺失图清单,我能直接照着补图,而不是干删。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!











