WP-CLIで始めるはじめてのGutenbergカスタムブロックプラグイン制作

カスタムブロックですが、WP-CLIを使うのが正直一番楽です。 WP-CLIのある開発環境を用意する VCCWやWockerがカスタマイズできて便利ですが、黒い画面に抵抗のある人はLocal by Flywheel使いま […]

広告ここから
広告ここまで

目次

    カスタムブロックですが、WP-CLIを使うのが正直一番楽です。

    WP-CLIのある開発環境を用意する

    VCCWやWockerがカスタマイズできて便利ですが、黒い画面に抵抗のある人はLocal by Flywheel使いましょう。これもデフォルトで入ってます。

    https://blog.mismithportfolio.com/web/20161218flywheelwpcli

    WP-CLIのバージョンが古いことがあるので、要注意です。

    # wp cli version
    WP-CLI 1.4.1
    
    
    # wp cli check-update
    +---------+-------------+-----------------------------------------------------------------------------+
    | version | update_type | package_url                                                                 |
    +---------+-------------+-----------------------------------------------------------------------------+
    | 1.5.1   | minor       | https://github.com/wp-cli/wp-cli/releases/download/v1.5.1/wp-cli-1.5.1.phar |
    +---------+-------------+-----------------------------------------------------------------------------+
    
    
    # wp cli update
    You have version 1.4.1. Would you like to update to 1.5.1? [y/n] y
    Downloading from https://github.com/wp-cli/wp-cli/releases/download/v1.5.1/wp-cli-1.5.1.phar...
    md5 hash verified: c2953cd2563e8ad0be8fb0544215906b
    New version works. Proceeding to replace.
    Success: Updated WP-CLI to 1.5.1.
    
    # wp cli version
    WP-CLI 1.5.1

    プラグインフォルダを用意する

    今回はユニットテスト等は省略するので、--skip-testしときます。気持ち的には、入れておいた方がいいと思いますが。

    # cd /app/public
    # wp scaffold plugin guten-blocks --skip-tests --activate
    Success: Created plugin files.
    Plugin 'guten-blocks' activated.
    Success: Activated 1 of 1 plugins.

    カスタムブロックをセットアップする

    # wp scaffold block first-block --category=formatting --title="hello custom"  --plugin=guten-blocks
    Success: Created block 'Hello custom'.

    プラグインディレクトリ内にblocksというフォルダが作られ、その中に4つのファイルが展開されます。

    $ git status
    On branch master
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
    	new file:   blocks/first-block.php
    	new file:   blocks/first-block/editor.css
    	new file:   blocks/first-block/index.js
    	new file:   blocks/first-block/style.css

    scaffoldしたファイルをプラグインで呼び出す

    scaffoldしただけでは、まだ読み込みされていません。scaffold pluginで生成されたphpファイルでrequireする必要があります。

    <?php
    /**
     * Plugin Name:     Guten Blocks
     * Plugin URI:      PLUGIN SITE HERE
     * Description:     PLUGIN DESCRIPTION HERE
     * Author:          YOUR NAME HERE
     * Author URI:      YOUR SITE HERE
     * Text Domain:     guten-blocks
     * Domain Path:     /languages
     * Version:         0.1.0
     *
     * @package         Guten_Blocks
     */
    
    require_once( plugin_dir_path( __FILE__ ) . 'blocks/first-block.php' );
    

    これでプラグインを有効化していれば読み込みされるようになります。

    scaffoldされたファイルは何をするファイルか見る

    再度確認ですが、scaffold blockコマンドで4つのファイルが追加されています。それぞれの役割をざっとまとめてみました。

    $ tree blocks/
    blocks/
    ├── first-block
    │   ├── editor.css  - エディターでの表示を調整するCSS
    │   ├── index.js    - Gutenbergのブロックを定義するJS
    │   └── style.css   - フロントでの表示を調整するCSS
    └── first-block.php - JS / CSSの読み込み設定をするPHP 
    

    あとで紹介しますが、このうちfirst-block/index.jsはそのまま使わない方がファイル容量の節約になって良いかなと思います。

    カスタムブロックをjsxでかけるようにする

    scaffoldコマンドで生成されるjsファイルは、(React遣い的には)あまり楽しくない感じになっています。

    	registerBlockType( 'guten-blocks/first-block', {
    		/**
    		 * This is the display title for your block, which can be translated with `i18n` functions.
    		 * The block inserter will show this name.
    		 */
    		title: __( 'Hello custom' ),
    
    		/**
    		 * Blocks are grouped into categories to help users browse and discover them.
    		 * The categories provided by core are `common`, `embed`, `formatting`, `layout` and `widgets`.
    		 */
    		category: 'formatting',
    
    		/**
    		 * Optional block extended support features.
    		 */
    		supports: {
    			// Removes support for an HTML mode.
    			html: false,
    		},
    
    		/**
    		 * 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.
    		 * @see https://wordpress.org/gutenberg/handbook/block-edit-save/#edit
    		 *
    		 * @param {Object} [props] Properties passed from the editor.
    		 * @return {Element}       Element to render.
    		 */
    		edit: function( props ) {
    			return el(
    				'p',
    				{ className: props.className },
    				__( 'Hello from the editor!' )
    			);
    		},

    コメントもありますし、ドキュメントもあるのでまったくわからないというわけではありません。ただ、Reactで作られているものならReactっぽく書きたいという気持ちが湧いてきます。

    ということでここからはscaffoldしたものをReact(ES Next)っぽくかけるようにしていきます。

    jsファイルの読み込み場所の変更

    この後の設定でいろいろなファイルを1つにまとめることになります。なので読み込み場所を変えておきましょう。

    $ cd blocks
    $ mkdir dist
    $ mv first-block/index.js dist/index.js

    phpファイルの$index_jsで定義しているパスも変更しておきましょう。

    $ git diff first-block.php 
    diff --git a/blocks/first-block.php b/blocks/first-block.php
    index 35260ef..1ad900d 100644
    --- a/blocks/first-block.php
    +++ b/blocks/first-block.php
    @@ -15,7 +15,7 @@
     function first_block_block_init() {
            $dir = dirname( __FILE__ );
     
    -       $index_js = 'first-block/index.js';
    +       $index_js = 'dist/index.js';
            wp_register_script(
                    'first-block-block-editor',
                    plugins_url( $index_js, __FILE__ ),

    babel & webpackの設定

    いれます。Rollupとかもありますが、webpackでいきます。

    $ pwd
    /PATH/TO/WP/wp-content/plugins/guten-blocks/blocks
    $ npm init -y
    $ npm i -D webpack babel-core babel-loader babel-plugin-transform-react-jsx cross-env babel-preset-env
    $ vim .babelrc
    {
    	"presets": [
    		[ "env", {
    			"modules": false,
    			"targets": {
    				"browsers": [
    					"last 2 Chrome versions",
    					"last 2 Firefox versions",
    					"last 2 Safari versions",
    					"last 2 iOS versions",
    					"last 1 Android version",
    					"last 1 ChromeAndroid version",
    					"ie 11"
    				]
    			}
    		} ]
    	],
    	"plugins": [
    		[ "transform-react-jsx", {
    			"pragma": "wp.element.createElement"
    		} ]
    	]
    }
    
    $ vim webpack.config.js
    module.exports = {
      entry: './index.js',
      output: {
        path: __dirname,
        filename: 'dist/index.js',
      },
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            use: 'babel-loader',
          },
        ]
      },
    };

    JSXでのコンポーネント作成

    $ pwd
    /PATH/TO/WP/wp-content/plugins/guten-blocks/blocks
    $ vim first-block/index.jsx
    const { __ } = wp.i18n;
    const { registerBlockType } = wp.blocks;
    
    registerBlockType( 'guten-blocks/first-block', {
    	title: __( 'Hello custom' ),
    	category: 'formatting',
    
    	supports: {
    		// Removes support for an HTML mode.
    		html: false,
    	},
    	edit() {
    		return <p>{__( 'Hello from the editor!' )}</p>;
    	},
    	save() {
    		return <p>{__( 'Hello from the saved content!' )}</p>;
    	},
    } );
    

    エントリーファイルの用意

    $ pwd
    /PATH/TO/WP/wp-content/plugins/guten-blocks/blocks
    $ vim index.js 
    require('./first-block/index.jsx');

    ビルドの実行

    $ npm run build

    この後エディタでブロックの表示がきえてなければOKです。

    テキスト入力を許可する

    このままでは入力も保存される値も固定ですので、変更できるようにします。

    const { __ } = wp.i18n;
    const { registerBlockType, RichText } = wp.blocks;
    
    registerBlockType( 'guten-blocks/first-block', {
    	title: __( 'Hello custom' ),
    	category: 'formatting',
    	attributes: {
    		content: {
    			type: 'array',
    			source: 'children',
    			selector: 'p'
    		}
    	},
    	supports: {
    		// Removes support for an HTML mode.
    		html: false,
    	},
    	edit({attributes, setAttributes}) {
    		const { content } = attributes
    		const onChangeContent = (newContent) => setAttributes({content: newContent})
    		return (
    			<RichText
    				tagName="p"
    				onChange={ onChangeContent }
    				value={ content }
    			/>
    		);
    	},
    	save() {
    		return <p>{__( 'Hello from the saved content!' )}</p>;
    	},
    } );
    

    RichTextの読み込み場所に注意

    The RichText component has been moved from wp.blocks.RichText to wp.editor.RichText and the documentation is updated to reflect this.
    The result is the official documentation is ahead of the current release.
    The currently published example code in the official Gutenberg handbook references wp.editor.RichText and therefore does not work with the current release of the Gutenberg plugin (2.8.0).

    https://github.com/WordPress/gutenberg/issues/6514#issuecomment-387754124

    保存した内容を出力する

    これだけだと出力されません。保存する時に走る処理でも反映させましょう。save()をカスタマイズします。

    	save({attributes}) {
    		const { content } = attributes
    		return <p>{content}</p>;
    	},

    入力と出力をコントロールする

    エディタ画面と保存処理を個別にかけるので、「ここはユーザーに変更されたくない」という場所を切り分けることができます。

    const { __ } = wp.i18n;
    const { registerBlockType, RichText } = wp.blocks;
    
    registerBlockType( 'guten-blocks/first-block', {
    	title: __( 'Hello custom' ),
    	category: 'formatting',
    	attributes: {
    		content: {
    			type: 'array',
    			source: 'children',
    			selector: 'p'
    		}
    	},
    	supports: {
    		// Removes support for an HTML mode.
    		html: false,
    	},
    	edit({attributes, setAttributes}) {
    		const { content } = attributes
    		const onChangeContent = (newContent) => setAttributes({content: newContent})
    		return [
    			<h2>ここに色々なテキスト書いてね</h2>,
    			<RichText
    				tagName="p"
    				onChange={ onChangeContent }
    				value={ content }
    			/>
    		];
    	},
    	save({attributes}) {
    		const { content } = attributes
    		return (<div>
    			<h2>本文ここから</h2>
    			<p>{content}</p>
    		</div>);
    	},
    } );
    

    エディター

    出力

    おわりに

    WP-CLIをベースに作り始めるとどうなるかを一通りまとめました。RichTextだけしか紹介していませんが、これだけでも入力ガイドや表示の制御がかなりやりやすくなるので、エディタのカスタマイズ要望にも応えやすくなるかなと思います。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark