为 WordPress 编辑器的“预览”菜单添加自定义入口

  • 中文整理标题: 为 WordPress 编辑器的“预览”菜单添加自定义入口
  • 来源: WordPress Developer Blog
  • 作者: Birgit Pauli-Haack
  • 原文日期: 2026 年 2 月 19 日
  • 适用前提: WordPress 6.7 起;示例使用区块编辑器插件开发工具链

WordPress 编辑器顶部栏的“预览”下拉菜单可以放入插件自己的预览入口。本文按原文的“社交卡片预览”示例,说明如何注册菜单项、打开弹窗、从编辑器状态读取文章信息,并在本地临时站点中查看效果。原文页面包含菜单和弹窗截图;此稿不附带图片。

1. 了解扩展点

WordPress 6.7 起,插件可以通过 @wordpress/editor 包中的 PluginPreviewMenuItem 向编辑器“预览”菜单注册项目。它沿用 Slot/Fill 扩展模式,与 PluginMoreMenuItem、PluginSidebar 等编辑器扩展点相似。

菜单项可以使用 onClick 处理按钮行为,也可以用 href 指向链接;icon 是可选图标属性。组件标签之间的文本就是菜单显示名称。示例点击后打开一个模态框,预览当前文章在 X 上分享时的卡片样式。预览读取编辑器中的标题、摘要和特色图片,因此会反映尚未保存的编辑内容。

2. 准备插件目录和 PHP 引导文件

插件目录包含主 PHP 文件、构建配置和源文件:

custom-preview/
├── custom-preview.php
├── package.json
└── src/
    ├── index.js
    ├── social-card-preview.js
    └── style.css

在 custom-preview.php 中,通过 enqueue_block_editor_assets 钩子只为区块编辑器注册脚本和样式。构建工具生成的 build/index.asset.php 提供依赖项及版本哈希;文件不存在时直接返回,避免引用尚未构建的资源。

function social_card_preview_enqueue_editor_assets() {
    $asset_file = plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
    if ( ! file_exists( $asset_file ) ) {
        return;
    }

    $asset = include $asset_file;

    wp_enqueue_script(
        'social-card-preview-editor',
        plugin_dir_url( __FILE__ ) . 'build/index.js',
        $asset['dependencies'],
        $asset['version'],
        true
    );

    wp_enqueue_style(
        'social-card-preview-editor',
        plugin_dir_url( __FILE__ ) . 'build/style-index.css',
        array(),
        $asset['version']
    );
}
add_action( 'enqueue_block_editor_assets', 'social_card_preview_enqueue_editor_assets' );

3. 配置 JavaScript 构建工具

原文示例使用 @wordpress/scripts。在 package.json 中声明构建和监听脚本,并将该工具列为开发依赖:

{
    "name": "social-card-preview",
    "version": "1.0.0",
    "scripts": {
        "build": "wp-scripts build",
        "start": "wp-scripts start"
    },
    "devDependencies": {
        "@wordpress/scripts": "^30.0.0"
    }
}

安装依赖并构建生产资源:

npm install
npm run build

开发时可运行 npm run start,让构建工具监听文件变动并自动重建。

4. 注册“社交卡片预览”菜单项

在 src/index.js 中注册插件组件。点击菜单项时将弹窗状态设为打开;条件渲染弹窗,并把关闭回调传给它。

import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginPreviewMenuItem } from '@wordpress/editor';
import { useState } from '@wordpress/element';

import SocialCardPreview from './social-card-preview';
import './style.css';

const SocialCardPreviewMenuItem = () => {
    const [ isOpen, setIsOpen ] = useState( false );

    return (
        <>
            <PluginPreviewMenuItem
                onClick={ () => setIsOpen( true ) }
            >
                { __( 'Social Card Preview', 'social-card-preview' ) }
            </PluginPreviewMenuItem>
            { isOpen && (
                <SocialCardPreview
                    onClose={ () => setIsOpen( false ) }
                />
            ) }
        </>
    );
};
registerPlugin( 'social-card-preview', {
    render: SocialCardPreviewMenuItem,
} );

这里由 registerPlugin 把组件接入编辑器;useState 只负责控制弹窗显隐。菜单文本通过 __() 包装,便于国际化。

5. 从编辑器状态生成预览数据

src/social-card-preview.js 使用 useSelect 读取两个数据源:从 editor store 取得当前编辑的标题、摘要和特色媒体 ID;再从 core-data store 解析媒体对象及站点 URL。媒体优先使用 large 尺寸,没有该尺寸时回退到原始 source_url。示例将摘要截为 200 个字符,并在末尾添加省略号。

import { __ } from '@wordpress/i18n';
import { Modal } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import { store as coreStore } from '@wordpress/core-data';

const SocialCardPreview = ( { onClose } ) => {
    const { title, excerpt, imageUrl, siteUrl } = useSelect( ( select ) => {
        const { getEditedPostAttribute } = select( editorStore );
        const featuredMediaId = getEditedPostAttribute( 'featured_media' );

        let featuredImageUrl = '';
        if ( featuredMediaId ) {
            const media = select( coreStore ).getMedia( featuredMediaId );
            featuredImageUrl =
                media?.media_details?.sizes?.large?.source_url ||
                media?.source_url ||
                '';
        }

        return {
            title: getEditedPostAttribute( 'title' ) || '',
            excerpt: getEditedPostAttribute( 'excerpt' ) || '',
            imageUrl: featuredImageUrl,
            siteUrl: select( coreStore ).getSite()?.url || '',
        };
    }, [] );

    const domain = siteUrl ? new URL( siteUrl ).hostname : '';
    const truncatedExcerpt =
        excerpt.length > 200
            ? excerpt.substring( 0, 200 ) + '…'
            : excerpt;

    return (
        <Modal
            title={ __( 'X Preview', 'social-card-preview' ) }
            onRequestClose={ onClose }
            size="medium"
        >
            { /* 卡片预览标记见下一节 */ }
        </Modal>
    );
};

useSelect 会订阅所选数据,编辑过程中标题或摘要改变时,预览可以随编辑状态更新。此组件中的示例代码把卡片标记留作下一步插入到 Modal 内部。

6. 加入卡片标记

卡片由特色图片和文字区域构成。没有特色图片时不渲染 img;站点域名、标题和截短后的摘要分别使用 span。原文将它说明为视觉模拟,因此没有把这些元素写成语义标题或段落。类名采用 BEM 风格,便于把样式限定在本组件内。

将下面的 JSX 放在上一节 Modal 的开始和结束标签之间:

<div className="social-card-preview">
    <div className="social-card-preview__card social-card-preview__card--twitter">
        { imageUrl && (
            <img
                className="social-card-preview__image"
                src={ imageUrl }
                alt=""
            />
        ) }
        <div className="social-card-preview__content">
            <span className="social-card-preview__domain">
                { domain }
            </span>
            <span className="social-card-preview__title">
                { title }
            </span>
            <span className="social-card-preview__description">
                { truncatedExcerpt }
            </span>
        </div>
    </div>
</div>

7. 添加基础样式

示例以边框、圆角和溢出裁切模拟卡片外观;标题使用两行截断:

.social-card-preview__card {
    border: 1px solid #dadce0;
    border-radius: 16px;
    overflow: hidden;
}

.social-card-preview__title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

原文指出,卡片使用 16px 圆角来接近 X 的圆角视觉;-webkit-line-clamp 处理标题和描述的多行截断。

8. 用 WordPress Playground 查看入口

原文使用 Playground CLI 启动一次性 WordPress 实例,不要求预先安装完整站点。前提是 Node.js 20.18 或更高版本;在插件目录中依次运行:

npm install
npm run build
npx @wp-playground/cli@latest server --auto-mount --login

CLI 会自动挂载插件并登录管理员。随后在浏览器打开 http://127.0.0.1:9400,新建或编辑文章,打开编辑器顶部的“预览”下拉菜单,即可查看“Social Card Preview”入口。以上是原文给出的操作步骤,本稿没有实际运行这些命令。

9. 可扩展的预览场景

同一个扩展点也可以承载其他编辑时检查或预览,例如:

  • 无障碍检查: 打开模态框,检查缺少替代文本、对比度不足等常见问题。
  • 可读性预览: 展示可读性分数和简化后的内容。
  • 外部预览服务: 使用 href 属性,将文章 URL 带到第三方 staging 或 QA 环境。
  • 邮件简报预览: 展示文章套用邮件模板后在邮件客户端中的样子。

来源信息

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容