create-guten-blockでGutenbergの「カスタムブロック」を追加してみる

WordPressの5系がリリースされて早数ヶ月。
Gutenbergという新しいエディタも正式に使えるようになりました。

Gutenbergにはブロックという考え方があり、いろいろな種類のブロックをエディタ上に追加していくことで直感的にレイアウトが組めるようになっています(少々慣れが必要ですが)。

デフォルトで存在しているブロックだけでもそれなりのレイアウトを組めるようになっていますが、自分がカスタマイズした「カスタムブロック」を追加することで、より自由なレイアウトが実現できるようになっています。

しかし、今までのWordPressのカスタマイズと違い、npmやReactなどのフロントエンドの知識が必要になってきます。慣れていない人からすれば若干理解し辛いかもしれないので、カスタマイズの基礎的なところを本日は書こうかと思います。

Windowsの方へ

windowsをお使いの方はnode.jsがデフォルトでインストールされていません。
以下URLよりnode.jsをインストールしてから進んでください。
https://nodejs.org/ja/

create-guten-blockで開発環境の構築

1. pluginディレクトリに移動

cd wp-content/plugins

2. npxで下記コマンドを実行します。

my-blockはプラグイン名なので、任意の名前を設定してください。

npx create-guten-block my-block

3. my-blockディレクトリに移動して、npm startします。

cd my-block
npm start

管理画面のプラグイン一覧にmy-blockが追加されているので、有効化してください。

4. ディレクトリ構成

いろいろなファイルが置いてありますが、src/blockの中身が1つのブロックとなります。src/block2などを追加し、block.jsにインポートすればプラグインの中で複数ブロックを追加することも可能です。

シンプルに作ってみる

src/block/block.jsの中身を見ると、初期設定は以下のようになっています。

/**
 * BLOCK: my-block
 *
 * Registering a basic block with Gutenberg.
 * Simple block, renders and saves the same content without any interactivity.
 */

//  Import CSS.
import './style.scss';
import './editor.scss';

const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks

/**
 * Register: aa Gutenberg Block.
 *
 * Registers a new block provided a unique name and an object defining its
 * behavior. Once registered, the block is made editor as an option to any
 * editor interface where blocks are implemented.
 *
 * @link https://wordpress.org/gutenberg/handbook/block-api/
 * @param  {string}   name     Block name.
 * @param  {Object}   settings Block settings.
 * @return {?WPBlock}          The block, if it has been successfully
 *                             registered; otherwise `undefined`.
 */
registerBlockType( 'cgb/block-my-block', {
	// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
	title: __( 'my-block - CGB Block' ), // Block title.
	icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
	category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
	keywords: [
		__( 'my-block — CGB Block' ),
		__( 'CGB Example' ),
		__( 'create-guten-block' ),
	],

	/**
	 * The edit function describes the structure of your block in the context of the editor.
	 * This represents what the editor will render when the block is used.
	 *
	 * The "edit" property must be a valid function.
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	edit: function( props ) {
		// Creates a <p class='wp-block-cgb-block-my-block'></p>.
		return (
			<div className={ props.className }>
				<p>— Hello from the backend.</p>
				<p>
					CGB BLOCK: <code>my-block</code> is a new Gutenberg block
				</p>
				<p>
					It was created via{ ' ' }
					<code>
						<a href="https://github.com/ahmadawais/create-guten-block">
							create-guten-block
						</a>
					</code>.
				</p>
			</div>
		);
	},

	/**
	 * The save function defines the way in which the different attributes should be combined
	 * into the final markup, which is then serialized by Gutenberg into post_content.
	 *
	 * The "save" property must be specified and must be a valid function.
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	save: function( props ) {
		return (
			<div>
				<p>— Hello from the frontend.</p>
				<p>
					CGB BLOCK: <code>my-block</code> is a new Gutenberg block.
				</p>
				<p>
					It was created via{ ' ' }
					<code>
						<a href="https://github.com/ahmadawais/create-guten-block">
							create-guten-block
						</a>
					</code>.
				</p>
			</div>
		);
	},
} );

registerBlockType()の中にブロックの設定や処理を記述していきます。第一引数はブロックのidのようなものなので、ユニークな名前になるよう設定しましょう。

ちなみにカスタムブロックを追加すると以下画像のような見た目になります。
※デフォルトでは編集できるようになっていません。

細かい箇所を見ていきます。

	// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
	title: __( 'my-block - CGB Block' ), // Block title.
	icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
	category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
	keywords: [
		__( 'my-block — CGB Block' ),
		__( 'CGB Example' ),
		__( 'create-guten-block' ),
	],

title

ブロックの名前を設定します。
ブロックの選択時に表示されるものです。

icon

ブロックの上にあるアイコンを選択できます。
コメントでも書いてありますが、下記URLより文字列を記述することでアイコンを表示できます。

Dashicons

「dashicons-〇〇」の〇〇の部分を記述してください。

category

ブロックは以下5つのカテゴリーに分かれています。
どのカテゴリーに追加するか設定してください。

– 共通ブロック(Common Blocks) – common
– 書式設定(Formatting) – formatting
– レイアウト要素(Layout Element) – layout
– ウィジェット(Widget) – widget
– 埋め込み(Embeds) – embeds

keywords

検索時にヒットするキーワードを追加します。
1つのブロックには最大3つのキーワードが設定出来ます。

カスタムブロックを編集できるように設定

次は文字列を入力できるようにしてみましょう。
ハイライトしている行が編集する行です。

/**
 * BLOCK: my-block
 *
 * Registering a basic block with Gutenberg.
 * Simple block, renders and saves the same content without any interactivity.
 */

//  Import CSS.
import './style.scss';
import './editor.scss';

const { __ } = wp.i18n; // Import __() from wp.i18n
const { registerBlockType } = wp.blocks; // Import registerBlockType() from wp.blocks
const RichText = wp.editor.RichText;

/**
 * Register: aa Gutenberg Block.
 *
 * Registers a new block provided a unique name and an object defining its
 * behavior. Once registered, the block is made editor as an option to any
 * editor interface where blocks are implemented.
 *
 * @link https://wordpress.org/gutenberg/handbook/block-api/
 * @param  {string}   name     Block name.
 * @param  {Object}   settings Block settings.
 * @return {?WPBlock}          The block, if it has been successfully
 *                             registered; otherwise `undefined`.
 */
registerBlockType( 'cgb/block-my-block', {
	// Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
	title: __( 'my-block - CGB Block' ), // Block title.
	icon: 'shield', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
	category: 'common', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
	keywords: [
		__( 'my-block — CGB Block' ),
		__( 'CGB Example' ),
		__( 'create-guten-block' ),
	],
	attributes: {
		children : {
			source: 'html',
			selector: 'div'
		}
	},

	/**
	 * The edit function describes the structure of your block in the context of the editor.
	 * This represents what the editor will render when the block is used.
	 *
	 * The "edit" property must be a valid function.
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	edit: function({ className, setAttributes, attributes }) {
		// Creates a <p class='wp-block-cgb-block-my-block'></p>.
		const { children } = attributes;
		return (
			<RichText
				tagName='div'
				className={ className }
				onChange={ children => setAttributes({ children }) }
				value={children}
			/>
		);
	},

	/**
	 * The save function defines the way in which the different attributes should be combined
	 * into the final markup, which is then serialized by Gutenberg into post_content.
	 *
	 * The "save" property must be specified and must be a valid function.
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	save: function( { attributes } ) {
		const { children } = attributes;
		return (
			<div>{children}</div>
		);
	},
} );

上記コードに書き換えることで編集できるようになります。

最後に

今回はシンプルにテキストの編集ができるGutenbergのカスタムブロックを作ってみました。

実は公式の「Gutenberg Handbook」というところでかなり詳しく書かれています。
カスタマイズする際はぜひ一度読んでみてください。
https://wordpress.org/gutenberg/handbook/