オリジナルブロックを作る


ブロックエディターに、独自のブロック(オリジナルブロック)を追加します。

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: 登録 API の名前と引数、ブロック定義に指定できる項目は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: PHP 側のフック処理(HTML のサニタイズの拡張など)は、この実験的機能の対象外です。従来どおりの仕様として提供しています。
  • 公開 API の線引き: このページに掲載している登録 API とブロック定義の項目を公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

全体像

オリジナルブロックは2つの部分でできています。

部分何をするか必要な場合
ブロックの定義メニューに出すラベル・アイコンと、挿入したときの動作を決めるほぼ必ず必要
要素の定義(スキーマ)エディターが扱える新しい要素そのものを追加する既存の要素の組み合わせでは表現できない場合

ブロックメニューに表示するかどうかは、管理者が編集設定で選びます。 プラグイン側は「使える種類を提供する」までを行い、メニューへの表示は設定に任せる形です。

ブロックの定義と要素の定義を登録する

次の例は、注意書きを目立たせる「コールアウト」ブロックを追加します。ブロックの定義と要素の定義は、どちらも setup(ctx) の中で登録します。

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-blocks', {
    setup(ctx) {
      // 要素の定義: エディターが扱える「callout」要素を追加する
      ctx.blockEditor.registerExtension('callout', ({ core }) =>
        core.Node.create({
          name: 'callout',
          group: 'block',
          content: 'paragraph+',
          parseHTML: () => [{ tag: 'div[data-callout]' }],
          renderHTML: () => ['div', { 'data-callout': '' }, 0],
        })
      );

      // ブロックの定義: メニューに出すラベルと、挿入したときの動作
      ctx.blockEditor.registerBlockDefinition('callout', () => ({
        label: 'コールアウト',
        description: '注意書きを目立たせるブロック',
        icon: 'info',
        isTextMenu: false,
        aliases: ['callout', 'note'],
        createActions: (cmd, actionCtx) => ({
          action: (editor) => {
            actionCtx.recordUsage(cmd);
            editor
              .chain()
              .focus()
              .insertContent({ type: 'callout', content: [{ type: 'paragraph' }] })
              .run();
          },
          convert: () => {},
          isDisabled: (editor) => editor.isActive('callout'),
          isActive: (editor) => editor.isActive('callout'),
        }),
      }));
    },
  });
});

ブロックの定義に指定できる項目は次のとおりです。

項目説明
labelメニューに表示する名前
descriptionメニューの説明文
iconアイコン名(Material Symbols の名前)
isTextMenu選択したテキストに対する変換メニューに出すかどうか
aliasesメニュー検索で引っかかるキーワード
menuCategory編集設定の選択肢での分類(省略すると「プラグイン」の分類にまとめられます)
createActions挿入・変換・状態判定の処理を返す関数

createActions が返すもの:

関数呼ばれるとき
action(editor)メニューから選ばれたとき(ブロックを挿入する)
convert(editor, pos)既存のブロックをこの種類に変換するとき
isDisabled(editor, pos)変換先として選べないかどうかの判定。true を返すと選べません
isActive(editor)現在のカーソル位置がこのブロックかどうかの判定

上の例のように、他のブロックからの変換に対応しない場合は、convert を何もしない関数にします。

既存のブロック(段落・見出し・画像など)の組み合わせで表現できる場合は、要素の定義(registerExtension)は不要で、ブロックの定義(registerBlockDefinition)だけで足ります。

ブロックエディターは Tiptap をベースにしています。要素の定義方法は Tiptap のドキュメントを参照してください。

Tiptap を自分で読み込まないでください

registerBlockDefinition / registerExtension に渡す関数は、引数として Tiptap を受け取ります。上の例の ({ core }) がそれです。この引数を使ってください。

プラグイン側で @tiptap/core などを import して使うと、ブロックエディター本体とは別の Tiptap が読み込まれ、エディターが正しく動作しません。TypeScript の型として参照する場合(import type)は問題ありません。詳細は 開発環境と型定義 を参照してください。

ブロックメニューに表示する

登録しただけではメニューに出ません。管理画面で表示する設定を行います。

  1. 管理画面の「編集設定」→「ブロックエディター設定」→「ブロックメニュー」を開きます。編集画面セットを使っているサイトでは、使っているセットの「ブロックエディター設定」を開きます(使っていないセットに保存しても、メニューには出ません)。
  2. 「追加」で行を増やし、「ブロック」の選択肢から、登録したブロックを選びます。選択肢には**「プラグイン」の分類**が追加されており、ブロックの定義の label(例: 「コールアウト」)で表示されます。
  3. 保存します。

PHP 側の追加実装は必要ありません。 選択肢は、登録されているブロックの種類から自動的に作られます。

保存した HTML からタグが消える場合

ブロックが出力する HTML は、保存時や表示時に、不正な HTML を防ぐための仕組み(HTML のサニタイズ)を通ります。多くの標準の HTML 要素と、Ver. 3.2.36 以降では data- で始まる属性が、そのまま通ります。上の例の <div data-callout> も、Ver. 3.2.36 以降では設定なしで保存されます。Ver. 3.2.35 以前では、data- 属性も次の Hook で許可が必要です($def->addAttribute('div', 'data-callout', 'CDATA');)。

独自の要素名(例: <acme-note>)や、標準にない属性を出力する場合は、取り除かれないように PHP 側で許可します。extension/acms/Hook.php に、次のメソッドを追加してください。

public function extendsHtmlPurifierDefinition(\HTMLPurifier_HTMLDefinition $def, \HTMLPurifier_Config $config): void
{
    $def->addElement('acme-note', 'Block', 'Flow', 'Common');
}

許可する要素・属性の定義はキャッシュされます。変更したあとは、ダッシュボードからキャッシュをクリアしてください。詳細は フック処理 を参照してください。

関連ページ

変更履歴

バージョン変更内容
Ver. 3.2新規追加(実験的機能)