WordPress Gutenberg 编辑器优化:自动将代码块转换为 Code Block Pro

图 1:粘贴代码后默认生成 SyntaxHighlighter Code

作者:

最近在整理博客写作流程时,又遇到了一个影响效率的小问题。

虽然每次只需要多点击几下,但由于我几乎每天都会写技术博客,长期下来,这种重复操作就变成了一个值得优化的地方。

最终,我通过分析 Gutenberg Block 的注册机制,并结合 WPCode,实现了保留 SyntaxHighlighter Evolved 历史文章兼容性的同时,让新文章自动转换为 Code Block Pro

本文记录整个排查和解决过程,希望能给遇到类似问题的朋友提供一些参考。


问题背景

我的博客目前同时安装了两个代码高亮插件:

  • SyntaxHighlighter Evolved:用于历史文章,已经使用多年。
  • Code Block Pro:用于新文章,界面更加现代,支持更多功能,因此决定以后全部使用它。

但是在实际写作过程中,我发现了一个比较影响效率的问题。

当我从 ChatGPT 或 Markdown 文档中直接复制包含代码块的内容到 WordPress Gutenberg 编辑器时,系统默认创建的并不是 Code Block Pro,而是 SyntaxHighlighter Code

图 1:粘贴代码后默认生成 SyntaxHighlighter Code
图 1:粘贴代码后默认生成 SyntaxHighlighter Code

随后,我不得不手动执行:

Plaintext
SyntaxHighlighter Code

转换(Transform)

Code Block Pro

如果一篇文章包含十几个代码块,就需要重复操作很多次。

虽然每次只需要几秒钟,但长期来看,非常影响写作效率。


为什么不能直接卸载 SyntaxHighlighter Evolved?

最开始,我想到的方案就是直接停用 SyntaxHighlighter Evolved。

但是查看历史文章后,很快发现这个方案不可行。

历史文章中的代码块实际上保存为:

Plaintext
<!-- wp:syntaxhighlighter/code {"language":"yaml"} -->
<pre class="wp-block-syntaxhighlighter-code">
...
</pre>
<!-- /wp:syntaxhighlighter/code -->

也就是说,我的历史文章已经全部依赖于 syntaxhighlighter/code 这个 Gutenberg Block。

如果直接停用插件,虽然文章内容不会丢失,但代码高亮效果将全部失效。

因此,最终确定原则:

历史文章保持不动,新文章继续使用 Code Block Pro。


分析 Gutenberg Block

为了找到真正的问题,我打开浏览器开发者工具,在 Console 中执行:

JavaScript
wp.blocks.getBlockTypes().map(x => x.name)

结果发现,编辑器中同时注册了三个代码块:

Plaintext
core/code
syntaxhighlighter/code
kevinbatdorf/code-block-pro

继续查看 SyntaxHighlighter Block:

JavaScript
wp.blocks.getBlockType("syntaxhighlighter/code")

发现它注册了如下转换规则:

Plaintext
transforms: {
    from: [
        {
            type: "enter"
        },
        {
            type: "raw"
        },
        {
            type: "block"
        }
    ]
}

其中最关键的是:

Plaintext
type: "raw"

这意味着,当我粘贴 Markdown 或 HTML 中的代码块时,会优先被 SyntaxHighlighter 接管,因此自动生成 SyntaxHighlighter Code Block。

而 Code Block Pro 本身并没有注册对应的 raw 转换规则,所以无法自动接管粘贴行为。


最终解决方案

既然不能修改历史文章,也不希望卸载 SyntaxHighlighter,那么思路就变成了:

仅修改 Gutenberg 编辑器行为,不影响前台显示。

最终,我使用 WPCode 添加了一个后台专用 PHP Snippet。

该 Snippet 会监听页面中新创建的:

  • core/code
  • syntaxhighlighter/code

随后自动转换为:

Plaintext
kevinbatdorf/code-block-pro

整个过程完全自动完成。

WPCode 配置如下:

图 2:WPCode 配置截图
图 2:WPCode 配置截图

名称:

Plaintext
[WP] Editor - 自动转换为 Code Block Pro

配置:

  • Code Type:PHP Snippet
  • Insert Method:Auto Insert
  • Location:Admin Only

由于仅在后台编辑器运行,因此不会影响前台页面,也不会影响历史文章。

完整代码如下:

PHP
/**
 * 后台编辑器:新粘贴/新插入的 core/code 或 syntaxhighlighter/code
 * 自动转换为 Code Block Pro。
 * 不处理打开文章时已经存在的历史代码块。
 */
add_action('enqueue_block_editor_assets', function () {
    wp_add_inline_script(
        'wp-blocks',
        <<<JS
wp.domReady(function () {
    if (!wp.data || !wp.blocks) return;

    const TARGET = 'kevinbatdorf/code-block-pro';
    const SOURCES = ['core/code', 'syntaxhighlighter/code'];
    let knownClientIds = new Set();
    let initialized = false;
    let converting = false;

    function flattenBlocks(blocks, result = []) {
        blocks.forEach(function (block) {
            result.push(block);
            if (block.innerBlocks && block.innerBlocks.length) {
                flattenBlocks(block.innerBlocks, result);
            }
        });
        return result;
    }

    function getAllBlocks() {
        return flattenBlocks(
            wp.data.select('core/block-editor').getBlocks()
        );
    }

    function rememberExistingBlocks() {
        getAllBlocks().forEach(function (block) {
            knownClientIds.add(block.clientId);
        });
        initialized = true;
    }

    setTimeout(rememberExistingBlocks, 1200);

    wp.data.subscribe(function () {
        if (!initialized || converting) return;

        const blocks = getAllBlocks();
        const candidates = blocks.filter(function (block) {
            return SOURCES.includes(block.name) && !knownClientIds.has(block.clientId);
        });

        if (!candidates.length) {
            blocks.forEach(function (block) {
                knownClientIds.add(block.clientId);
            });
            return;
        }

        converting = true;

        candidates.forEach(function (block) {
            let converted = null;

            if (wp.blocks.switchToBlockType) {
                converted = wp.blocks.switchToBlockType(block, TARGET);
            }

            if (Array.isArray(converted)) {
                converted = converted[0];
            }

            if (!converted && wp.blocks.createBlock) {
                const attrs = block.attributes || {};
                const code = attrs.code || attrs.content || attrs.text || '';
                const language = attrs.language || attrs.lang || 'text';

                converted = wp.blocks.createBlock(TARGET, {
                    code: code,
                    language: language
                });
            }

            if (converted) {
                wp.data.dispatch('core/block-editor').replaceBlock(block.clientId, converted);
                knownClientIds.add(converted.clientId);
            }
        });

        setTimeout(function () {
            getAllBlocks().forEach(function (block) {
                knownClientIds.add(block.clientId);
            });
            converting = false;
        }, 300);
    });
});
JS
    );
});

最终效果

添加 Snippet 后,再次测试。

直接将 ChatGPT 生成的 Markdown 内容粘贴到编辑器中:

以前:

Plaintext
Ctrl + V

SyntaxHighlighter Code

Transform

Code Block Pro

现在:

Plaintext
Ctrl + V

Code Block Pro

整个过程已经实现自动完成。

图 3:自动转换后的效果
图 3:自动转换后的效果

目前唯一的小问题是:

Code Block Pro 默认会继承上一次使用的语言,例如上一篇文章选择的是 Go,那么下一次新建代码块时默认仍然是 Go。

不过,对于我的写作习惯来说,这已经完全可以接受。

通常一篇文章主要围绕一种语言展开,例如:

  • Go
  • PHP
  • Bash
  • YAML

因此,只需要偶尔修改个别代码块的语言即可,相比之前已经节省了大量重复操作。


总结

这次优化解决的并不是一个复杂的问题。

它只是省掉了每篇文章中一次又一次重复点击的操作。

但是,对于长期坚持写技术博客的人来说,这类高频重复动作,往往才是最值得优化的地方。

整个优化过程中,我没有修改插件源码,也没有迁移历史文章,而是利用 Gutenberg Block API、浏览器开发者工具以及 WPCode,对编辑器行为进行了定制。

最终实现了:

  • 保留 SyntaxHighlighter Evolved 的历史文章兼容性;
  • 新文章默认使用 Code Block Pro;
  • 不影响前台显示;
  • 明显提升日常写作效率。

以后如果再遇到类似问题,我也会优先考虑:

先分析 Gutenberg Block 的工作机制,再决定是否通过 WPCode 对编辑器行为进行定制,而不是急着更换插件或者修改历史数据。

很多时候,只需要几十行代码,就能够让日常写作流程变得更加顺畅。

我是拥有 15+ 年经验的 PHP / Go 后端工程师。如需以下服务,欢迎联系我(更多介绍请查看 关于我 & 合作):

  • ✅ PHP / Go 项目开发与维护
  • ✅ 系统架构设计与技术咨询
  • ✅ 网站性能优化与故障排查
  • ✅ Linux 服务器部署与运维
  • ✅ 网络环境优化与远程支持
  • ✅ 长期技术顾问合作

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

评论

发表回复

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

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