因为之前用的两个代码高亮插件不是很顺手,所以打算自己制作一个
先创建一个空的块插件
npx @wordpress/create-block gutenpride
cd gutenpride
如果电脑本来就有wordpress,则可以直接生成在 /wp-content/plugins 目录
如果没有,则可以使用 wp-env 工具,配合 docker ,生成一个专门调试插件的环境
npm -g install @wordpress/env ## 安装 wp-env
wp-env start ## 在当前目录启动WordPress调试环境
然后打开 http://localhost:8888/ 就可以看到一个WP站点了,并且默认启用了刚才创建的插件(登陆账号密码为 admin/password )
然后使用 npm start
(wp-scripts start)命令,开启实时更改重构
npm start

使用npx创建的插件中,包含一个 block.json 文件
这个文件定义了插件的所有信息,其中 attributes 字段表示这个古腾堡块中会创建哪些属性
"attributes": {
"code": {
"type": "string",
"source": "text",
"selector": "code"
},
"lang": {
"type": "string"
}
},
比如我创建了一个 code 值表示插入的代码,lang 则为代码语言
我不需要 lang 值直接呈现出来,所以不需要添加 source 和 selector 值。它将会储存在古腾堡块的注释中

selector 为这个块的内容输出到的HTML标记的选择器,可以是HTML标签、class或id
我在 supports 段中加了 align 和 alignWide 的支持
这样这个块就能调整宽度了

在生成的插件中的src目录下, 有 edit.js 和 save.js 两个文件,它们负责这个块的功能实现和渲染。
在 Edit 函数中 return 的内容就是在编辑器中呈现的东西
save 函数 return 的内容 就是渲染成HTML的内容
我这里需要在编辑器中可以写代码语言和内容,分别用 TextControl 和 TextareaControl 两个组件制作,先要引入这两个组件
import {TextControl, TextareaControl} from '@wordpress/components';
然后把它们包裹在一个div块中返回
return (
<div {...blockProps} >
<TextControl
label="代码语言"
value={attributes.lang}
onChange={(val) => setAttributes({lang: val})}
/>
<TextareaControl
label="代码"
value={attributes.code}
onChange={(val) => setAttributes({code: val})}
/>
</div>
)
然后在 save.js 文件中将它们渲染成HTML内容
return (
<div {...blockProps}>
<pre>
<code className={lang}>{attributes.code}</code>
</pre>
</div>
)
添加 {…blockProps} 可以让div带有古腾堡块的class
const blockProps = useBlockProps(); //edit
const blockProps = useBlockProps.save(); //save
editor.scss 中的样式只会在编辑器里加载
style.scss 则在网页和编辑器都加载
Textarea高度自适应
我用于输入代码的组件是 TextareaControl ,它会返回一个 textarea 元素,textarea 是无法根据内容长度自动改变高度的,创建一个函数获取内容换行数自动设置高度
export function setHeightCodeBlocks(elem) {
const num = elem.value.match(/\r\n|\n/g);
let line;
if (null !== num) {
line = num.length + 1;
} else {
line = 1;
}
elem.style.height = line * 1.8 + 3.8 + 'em';
}
useEffect 钩子检测到代码组件重新渲染时触发设置高度
import {useEffect} from '@wordpress/element';
useEffect(() => {
// console.log('useEffect');
setTimeout(() => {
// alert(clientId)
const codeBlock = document.getElementById('block-' + clientId);
const textarea = codeBlock.querySelector('textarea');
setHeightCodeBlocks(textarea);
}, 10);
}, [clientId, attributes.code]);
然后在插件的php文件中引入prismjs就可以实现代码高亮了
function load_plugin_scripts() {
wp_enqueue_script(
'prismjs',
'https://cdn.jsdelivr.net/npm/prismjs@1.25.0/prism.min.js'
);
wp_enqueue_script(
'prismjs-autoloader',
'https://cdn.jsdelivr.net/npm/prismjs@1.25.0/plugins/autoloader/prism-autoloader.min.js'
);
// wp_enqueue_style( 'my-theme', 'https://cdn.jsdelivr.net/npm/prismjs@1.25.0/themes/prism.css' );
}
add_action( 'wp_enqueue_scripts', 'load_plugin_scripts' );
区块转换
古腾堡区块支持互相转换,实例如下
form 表示可以从哪些区块转换来, to 表示可以转换成什么
我添加了让WP默认code块转换为我自己块的支持(不过如果是插件中的块,插件卸载后,就不能转换了)
transforms: {
from: [
{
type: 'block',
blocks: ['core/code'],
transform: (attributes) => {
return createBlock('xiyuyyy/code-block', {
code: attributes.content,
});
},
},
{
type: 'block',
blocks: ['loos-hcb/code-block'],
transform: (attributes) => {
// console.log(attributes)
return createBlock('xiyuyyy/code-block', {
lang: attributes.langType,
code: attributes.code,
});
},
},
],
to: [
// {
// type: 'block',
// blocks: ['core/code'],
// transform: (attributes) => {
// return createBlock('core/code', {
// content: attributes.code,
// });
// },
// },
],
},