WordPress|Gutenbergカスタムブロック|Create Guten Block

前項まではスクラッチでプラグインとしてカスタムブロックを追加する方法をまとめたが、GutenbergはReactで実装されており、JSXというReactの記述法を用いて開発できるCreate Guten Blockというブロック追加のプラグイン作成公式開発ツールを使用したプラグイン作成についてメモ。

準備

Node.jsが存在する前提

$ cd wp-content/plugins

プラグインフォルダに移動

$ npx create-guten-block my-block

末尾は作成するプラグインフォルダのフォルダ名として任意の文字列にする。

my-blockが作成され、必要なnpmパッケージがインストールされる。

$ cd my-block
$ npm start

作成したプラグインフォルダに移動して、npm startすると、watchして自動的にビルドしてくれる状態となる。

この時点でmy-blockというプラグインができているので、管理画面から有効化するととりあえずプラグインが使える状態になる。

開発

おおまかなファイル構成

my-block

package.json

plugin.php

readme.md

src

block

block.js

editor.scss

style.scss

block.js

common.scss

init.php

dist

src/blockのフォルダ一つがブロック一つにあたる。本プラグイン内でブロックを増やす場合はsrc/block2などでフォルダを増やして対応。

ブロックの編集

src/block/block.jsがブロックの本体にあたり、主にこれを編集することでブロックの中身をカスタマイズする。同フォルダ内に当該ブロック用のscssも配置されており、CSSをそちらに記述する。

ブロックを増やす場合はregisterBlockTypeで他とかぶらない固有のブロック名をつけ、src/block.js(ブロックフォルダ下のblock.jsとは別)に増やしたブロックのimportの記述を追加する。

registerBlockType( 'cgb/block-my-block2', { //名前空間+固有の名称
import './block/block.js';
import './block2/block.js'; //増やしたブロック

scssは各ブロックフォルダ下にあるがブロック単位でなんらかパッケージされるわけではない。コピーしてブロックを増やした場合などにはそれぞれのscss内でセレクタをちゃんと書きなおさないと意図せず他のブロックのスタイルで上書きされてしまうので注意。

ブロックの詳細な記述については前項までと同様。ブロックのHTML部分をJSXで書けるのでこちらのほうが直感的でわかりやすいかも。

	edit: ( 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>
		);
	},
	save: ( props ) => {
		return (
			<div className={ props.className }>
				<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>
		);
	},

編集可能にしてみる

サンプルとしてでデフォルトで配置されているsrc/block/block.jsは編集領域の無いブロックなので、これを編集可能にしてみる。

なお、ソースにおいて追加位置がわかりづらいものはもとのサンプルコードの追加位置の上の記述を含めて記載。

RichTextライブラリ追加

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

attributes追加

編集領域の保存先としてattributesを設定。

	keywords: [
		//省略
	],
	attributes: { //ここから追加
		myText: {
			default: 'ここになにか書いて'
		}
	},

editの設定

入力できるようにRichTextに書き直し。

	edit: ( props ) => {
		return (
			<RichText
				tagName='div'
				className={ props.className }
				onChange={ (event) => props.setAttributes({ myText: event }) }
				value={ props.attributes.myText }
			/>
		);
	},

saveの設定

表示のみ。

	save: ( props ) => {
		return (
			<div className={ props.className }>
				{ props.attributes.myText }
			</div>
		);
	},

変更した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 './editor.scss';
import './style.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: {
		myText: {
			default: 'ここになにか書いて'
		}
	},
	/**
	 * 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/
	 *
	 * @param {Object} props Props.
	 * @returns {Mixed} JSX Component.
	 */
	edit: ( props ) => {
		return (
			<RichText
				tagName='div'
				className={ props.className }
				onChange={ (event) => props.setAttributes({ myText: event }) }
				value={ props.attributes.myText }
			/>
		);
	},

	/**
	 * 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/
	 *
	 * @param {Object} props Props.
	 * @returns {Mixed} JSX Frontend HTML.
	 */
	save: ( props ) => {
		return (
			<div className={ props.className }>
				{ props.attributes.myText }
			</div>
		);
	},
} );

雑感

当初こちらを先に触ったときにはいまいち理解が進まず、ベタで書いて理解を先に進めてから開発ツール利用に戻ってやってみたが、こちらのほうがかなり楽だし、たぶん正しいコードになりやすいかも。

参考にさせていただいた記事