没有不值得去解决的问题,也没有不值得去学习的技术!

WordPress 历史文章迁移终于收尾:全量审计 1438 篇中文文章,并停用 SyntaxHighlighter Evolved

作者:

前段时间,我一直在处理 WordPress 站点中的历史文章,包括中文摘要回填、旧代码格式迁移、SyntaxHighlighter 短代码处理,以及对应英文文章的覆盖翻译。

此前相关处理过程可以参考:

这项工作持续了相当长一段时间。历史文章中同时存在 Gutenberg、Classic Editor、Code Block Pro、SyntaxHighlighter、<pre><code> 等不同格式,还有不少 mixed 内容,因此很难通过一次简单的批量替换全部解决。

到现在,这一轮历史文章迁移终于正式收尾。

而且在准备发布本文之前,我也已经正式停用了 SyntaxHighlighter Evolved

暂时只是停用,还没有立即删除插件文件。接下来准备等待大约 5 天,让此前生成的旧页面缓存自然过期,再彻底删除插件。

一、67 个固定批次、1281 篇历史文章全部处理完成

最终的 history migration 状态为:

  • 固定批次:67
  • 固定文章:1281
  • remaining=0
  • integrity=ok
  • 最新未完成批次:无
  • 所有批次均已完成

执行证据中保留了:

  • completed=1279
  • failed=2
  • pending=0
  • translation_started=0

这里的 2 条 failed 属于历史执行证据,并不代表当前还有两篇文章没有处理。

最终流程状态已经全部收敛,remaining=0,而且当前不存在未完成批次。

【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】
【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】

完成历史文章迁移以后,我开始考虑另外一个已经拖了很久的问题:

SyntaxHighlighter Evolved 是否终于可以退出这个 WordPress 站点了?

二、为什么不能直接删除 SyntaxHighlighter

之前的大量历史文章已经完成代码格式迁移,但我仍然担心正文中残留 [text][php][json][js],以及其他 SyntaxHighlighter shortcode。

如果某篇文章原本就是依靠下面这样的短代码生成代码高亮:

Plaintext
[bash]
真正的代码或终端输出
[/bash]

那么直接删除插件以后,这些短代码就可能重新作为普通文字出现在页面中,原来的代码块也会失去正常展示效果。

因此,在真正让 SyntaxHighlighter 退出之前,我决定在历史迁移全部完成之后,再做一次独立的:

SyntaxHighlighter retirement audit

也就是 SyntaxHighlighter 退役前审计。

这一次不再自动修改文章,只负责把所有值得人工检查的中文文章找出来。

三、不能只搜索 [text][php][json][js]

最开始我想到的,只是重新搜索几个以前比较常见的短代码。

但真正检查生产环境中 SyntaxHighlighter Evolved 3.7.2 的运行时注册情况以后,发现远比这复杂。

除了三个通用 shortcode:

  • sourcecode
  • source
  • code

不同 brush 还注册了大量语言别名,例如:

  • bash
  • shell
  • php
  • go
  • golang
  • js
  • javascript
  • sql
  • text
  • plain
  • python
  • java
  • html
  • xml
  • yaml

等等。

最终确认生产运行时实际需要考虑 65 个 shortcode

这也意味着,如果只是手工搜索几个我印象中的字符串,很容易漏掉一些真正仍然依赖插件的历史文章。

因此这次没有简单使用几个固定关键字进行 grep,而是单独增加了一套 retirement audit scanner,根据生产插件实际注册的 shortcode 和 alias 进行扫描。

四、重新同步生产数据,而不是继续使用旧快照

由于之前的历史迁移已经持续了一段时间,期间我又人工修改过不少文章,所以这次没有继续使用历史阶段保存的旧 raw 数据。

而是重新从生产 WordPress 中读取当前最新的:

  • post_type=post
  • post_status=publish
  • Polylang 中文文章

英文文章没有单独扫描。

原因是如果中文文章需要修改,我会直接在 WordPress 后台修改中文,然后再使用现有翻译流程覆盖同步英文文章。

最终一共重新读取:

1438 篇中文已发布文章。

整个数据同步被分成 15 页:

  • 前 14 页各 100 篇
  • 最后一页 38 篇

每一页都进行了远程与本地 SHA-256、记录数、字节数、JSONL scope 和 schema 等检查。

最终:

  • duplicate post_id:无
  • 分页 overlap:无
  • cursor 异常:无
  • 所有页面均通过完整性校验

完成这次全量扫描以后,结果反而比我预计的轻很多。

五、1438 篇文章,最终只有 14 篇需要人工检查

最终 retirement audit 的统计为:

  • 中文 published posts:1438
  • JSONL pages:15
  • 命中文章:14
  • shortcode 总命中:58
  • 最早命中文章:2018-09-01 17:34:44
  • 最新命中文章:2026-07-21 12:36:24

真正出现的 shortcode 只有 8 种:

Shortcode命中次数涉及文章
source196
php102
go82
sql81
text52
sourcecode41
bash21
code21
【图2:SyntaxHighlighter retirement audit 最终统计,1438 篇文章中只有 14 篇命中】
【图2:SyntaxHighlighter retirement audit 最终统计,1438 篇文章中只有 14 篇命中】

这个结果非常重要。

因为它意味着,在经历前面的大量历史迁移以后,真正还需要我人工打开确认的文章只剩:

14 篇。

此时继续开发复杂的自动迁移逻辑已经没有多少意义。

直接人工逐篇检查,反而更安全,也更加高效。

六、命中 shortcode,不代表一定要修改

这次 retirement audit 和之前自动 migration detector 最大的区别,就是:

只负责找候选,不负责判断这篇文章一定有问题。

实际检查过程中,很快就遇到了一个非常典型的例子。

某篇文章正文正在介绍短代码检测问题,其中专门写了:

Plaintext
[sourcecode]...[/sourcecode]

这本身就是文章准备展示给读者看的文本。

【图3:文章正文中 [sourcecode]...[/sourcecode] 本身就是需要展示的示例文本】
【图3:文章正文中 [sourcecode]...[/sourcecode] 本身就是需要展示的示例文本】

但是在当时 SyntaxHighlighter Evolved 仍然启用的情况下,前台会把它当成真正的 shortcode 执行。

结果原本应该显示:

Plaintext
[sourcecode]...[/sourcecode]

的地方,被 SyntaxHighlighter 渲染成了一个代码区域,只剩下中间的:

Plaintext
...

从文章语义来看,这篇文章其实完全不应该修改

真正应该退出的是 SyntaxHighlighter 对这段文字的解析,而不是修改文章原文。

因此,这篇文章虽然被 retirement audit 命中,但最终人工判断是:

保留原文,不修改。

现在 SyntaxHighlighter Evolved 已经停用,这种本来就是为了展示 shortcode 本身的文字,也就不会再继续被插件当成代码高亮短代码处理。

这也是为什么我从一开始就没有把“shortcode 残留必须归零”当成 SyntaxHighlighter 退役条件。

有些 shortcode 外观,本来就是文章内容的一部分。

七、另一类文章则必须真正迁移

另外一篇文章就完全不同。

后台正文中保存的是:

Plaintext
[bash]
真正的终端输出
[/bash]

这里的 [bash]...[/bash] 并不是文章为了向读者展示 shortcode 本身,而是在真正使用 SyntaxHighlighter 完成代码高亮。

【图4:停用 SyntaxHighlighter 前,仍然依赖 [bash]...[/bash] shortcode 展示终端输出的历史文章】
【图4:停用 SyntaxHighlighter 前,仍然依赖 [bash]...[/bash] shortcode 展示终端输出的历史文章】

此前前台之所以能正常显示代码块,正是因为 SyntaxHighlighter 负责解析这段 shortcode。

如果停用插件之前不处理,那么原来的:

Plaintext
[bash]
...
[/bash]

就会重新作为普通文本暴露出来。

因此,这一类文章必须真正迁移。

我的处理方式是:

  1. 新建 Code Pro 区块;
  2. 只复制
Plaintext
[bash] 与 [/bash]

中间真正的代码内容;

不再保留 SyntaxHighlighter shortcode;

删除原来的简码区块;

保存中文文章;

再通过后台覆盖同步对应的英文文章。

最终 Code Pro 中保存的是实际代码,例如:

Plaintext
[root@server example.com]# php example.php
PHP Fatal error: ...
Stack trace:
...

而不再把

Plaintext
[bash] 和 [/bash]

保存进去。

这样代码展示就不再依赖 SyntaxHighlighter。

八、14 篇人工检查,真正需要修改的不到 5 篇

最终,我把这 14 篇候选全部人工检查了一遍。

实际真正需要修改的文章甚至不到 5 篇。

也就是说,这次最终结果大致是:

Plaintext
1438 篇最新中文文章

14 篇 shortcode 候选

全部人工检查

真正修改不到 5 篇

这个结果也再次说明,自动扫描和人工判断应该承担不同的职责。

自动化非常适合解决:

“我有没有漏掉什么?”

但对于:

“这个 [text] 到底是需要迁移的历史 shortcode,还是文章本来就准备展示的文字?”

人工结合文章语义判断,反而更可靠。

最终不需要强行把所有 shortcode-looking text 清理到 0。

九、Retirement audit 独立于历史迁移流程

这一次没有继续往原来的 history migration 状态机中增加逻辑。

而是单独增加了:

Plaintext
bin/build-syntaxhighlighter-retirement-audit.py

以及对应配置:

Plaintext
config/syntaxhighlighter-retirement.json

这样做的原因也比较明确。

历史 migration detector 的目标是:

安全地判断一篇文章是否适合自动迁移。

因此它会主动保护或屏蔽:

  • Code Block Pro
  • Gutenberg code block
  • <pre>
  • <code>
  • 某些代码区域中的 shortcode-looking text

而 retirement audit 的目标完全不同。

它更关注:

只要可能值得人工看一眼,就把文章列出来。

因此即使一个 shortcode 出现在 Code Block Pro、<pre><code> 或其他复杂区域中,也没有必要过早自动排除。

最终由人工判断即可。

这也是这次 1438 篇全量扫描最终能够缩小到 14 篇人工候选的重要原因。

十、项目代码也一起完成最终收口

完成 1438 篇文章的 retirement audit、14 篇人工检查和必要的文章修改以后,我又把这次新增的审计工具,以及最后一批历史 migration state,一起完成了 Git 收口。

最终提交:

Plaintext
e2fd42f

提交信息:

Plaintext
feat: 增加 SyntaxHighlighter 退役审计

这次还运行了完整自动化测试:

Plaintext
Ran 503 tests
OK

最终历史迁移状态:

Plaintext
67 fixed batches
1281 fixed posts
remaining=0
integrity=ok

SyntaxHighlighter retirement audit:

Plaintext
1438 Chinese published posts
14 candidates
58 matches

最终 Git 状态:

Plaintext
## main...origin/main

工作树干净。

【图5:最终 Git 提交、503 项测试、历史迁移与 SyntaxHighlighter retirement audit 全部收口】
【图5:最终 Git 提交、503 项测试、历史迁移与 SyntaxHighlighter retirement audit 全部收口】

至此,这个持续了很长时间的 WordPress 历史文章处理阶段,终于可以真正停下来了。

十一、为什么在发布本文之前就停用了 SyntaxHighlighter Evolved

原本我的计划是:

先完成全部人工检查和修改,然后继续保持 SyntaxHighlighter Evolved 启用大约 5 天,等待缓存自然过期,最后再卸载插件。

但在真正准备本文时,我发现还有一个很现实的问题。

本文本身就需要展示大量历史 shortcode,例如:

Plaintext
[sourcecode]...[/sourcecode]

[bash]...[/bash]

[text]
[php]
[code]

如果 SyntaxHighlighter Evolved 仍然处于启用状态,那么这些原本只是为了向读者展示的文本,就可能再次被插件当成真正的 shortcode 解析。

前面 [sourcecode]...[/sourcecode] 的实际案例已经证明,这并不是理论上的风险。

因此,在正式发布本文之前,我已经将:

SyntaxHighlighter Evolved 停用。

这样,从现在开始新生成的 WordPress 页面不再执行 SyntaxHighlighter 注册的 shortcode。

本文中用于说明历史格式的 shortcode 示例,也可以按照文章原意正常展示,而不是再次被插件解释成代码高亮内容。

十二、为什么只是停用,而不是立即彻底删除

虽然插件已经停用,但我目前还没有立即删除 SyntaxHighlighter Evolved 的插件文件。

这里主要考虑的仍然是缓存。

今天真正修改的不到 5 篇文章,在修改以前可能已经存在旧页面缓存。

那些旧缓存是在 SyntaxHighlighter 仍然启用、文章仍然依赖旧 shortcode 的状态下生成的。

我希望给这些旧页面缓存留出一个自然退出的时间窗口。

因此现在采用的是:

Plaintext
人工迁移完成

停用 SyntaxHighlighter Evolved

不主动清缓存

保留插件文件约 5 天

让此前生成的旧页面缓存自然过期

再彻底删除 SyntaxHighlighter Evolved

这里需要特别区分“停用”和“删除”。

插件停用以后,新的 WordPress 页面已经不会再执行 SyntaxHighlighter 的 PHP 逻辑,也不会再注册相关 shortcode。

但插件文件暂时仍然保留在服务器上。

这样,即使某些此前生成的缓存页面仍然引用了 SyntaxHighlighter 的 CSS 或 JavaScript 静态资源,对应插件文件暂时仍然存在,不需要立即面对资源文件被删除的问题。

等大约 5 天以后,这轮修改以前的旧缓存基本完成自然退出,我再进行最终的插件删除。

十三、这次历史文章处理终于真正结束

从最初只是想给旧文章补充摘要,到后来逐渐发现:

  • Classic Editor 历史格式
  • Gutenberg
  • Code Block Pro
  • SyntaxHighlighter
  • mixed content
  • shortcode 误判
  • <pre> / <code>
  • 中文与英文覆盖翻译
  • 自动校验
  • execution evidence
  • failed recovery
  • production drift
  • 人工修复

整个问题最终演变成了一套相当完整的历史内容迁移流程。

好在到现在,最终状态已经非常明确:

  • 67 个固定批次全部结束;
  • 1281 篇固定历史文章全部处理完成;
  • 1438 篇最新中文文章重新完成 SyntaxHighlighter 全量审计;
  • 只有 14 篇进入人工检查;
  • 真正需要修改的不到 5 篇;
  • SyntaxHighlighter Evolved 已经停用;
  • retirement audit 工具已经加入仓库;
  • 503 项自动化测试通过;
  • Git 工作树已经完全干净。

至此,SyntaxHighlighter 已经不再参与新页面的内容生成。

接下来也不再继续折腾历史文章。

现在只剩最后一个非常简单的收尾动作:

继续保留已经停用的 SyntaxHighlighter Evolved 插件文件大约 5 天,让此前的旧页面缓存自然退出,然后彻底删除插件。

等这一步完成以后,这一段持续了很久的 WordPress 历史代码格式迁移,也就真正画上句号了。

需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理