カテゴリー: Gutenberg

  • Advanced Posts Blocks 0.2.2 をりりーすしました。

    一月にリリースしたプラグインですが、今更ブログを書きます。Advanced Posts Blocks というプラグインをリリースしました。

    機能

    WordPress のビルトインのブロックに、「最新の記事」ブロックがありますが、あれを大幅に強化したプラグインです。より細かい検索条件で記事を取得できたり、テーマ側でテンプレートを用意することで表示をカスタマイズ出来ます。

    • 複数の投稿の一覧を表示する Multiple Posts Block
    • 特定の記事の子ページ一覧を表示する Children Posts Block
    • 特定の個別投稿を表示する Single Post Block

    の3つのブロックを提供します。

    テンプレート

    テーマのなかに、template-parts/blocks/advanced-posts-blocks/posts.php といったファイルを用意することで、表示をカスタマイズすることができます。WordPress のテンプレート階層のように、template-parts/blocks/advanced-posts-blocks/posts/page.php と行ったファイルを用意すると、個別ページの一覧の場合は、こちらが読み込まれます。ブロックのスタイルなどを利用すると更に細かいテンプレートのカスタマイズができます。

    開発

    開発は Github で行っています。https://github.com/torounit/advanced-posts-blocks プルリクエストなどください!

  • unregisterBlockType で ブロックを削除する。

    HandBook のほうには、

    wp.blocks.unregisterBlockType( 'core/verse' );

    をするとブロックの登録を解除できるという話だったのですが、このまま書いても解除されないんですよね。

    何故かというと、core/verse が 登録される前に unregisterBlockType が実行されてしまうからです。なので、Gutenberg / ブロックエディタの初期化処理が終了してから、こいつを実行してあげる必要があります。

    const { _wpLoadBlockEditor } = window;
    const { unregisterBlockType } = wp.blocks;
    _wpLoadBlockEditor.then( () => {
        unregisterBlockType( 'core/verse' );
    } );

    こんな感じで、_wpLoadBlockEditor の完了を待ってから実行すれば良いみたいです。

    _wpLoadBlockEditor はこんな感じです。

    
    window._wpLoadBlockEditor = new Promise( function( resolve ) {
    	wp.domReady( function() {
    		resolve( wp.editPost.initializeEditor( 'editor', "%s", %d, %s, %s ) );
    	} );
    } );

    覚えておくと何かの役に立つかもしれません。

  • Gutenberg のカスタムブロックでも、ES Modules import を使う。

    要は、どうしたいかというと、

    const { registerBlockType } = wp.blocks;

    これを、Gutenberg のコアのソースコードのように、

    import { registerBlockType } form '@wordpress/blocks'

    としたいと言うことです。

    やりかた

    webpack.config.js を の externals を良い感じに設定すればできます。Gunteberg 本体も似たようなコトをやっています。

    const entryPointNames = [
    	'blocks',
    	'components',
    	'editor',
    	'utils',
    	'viewport',
    	'edit-post',
    	'core-blocks',
    	'nux',
    ];
    
    const gutenbergPackages = [
    	'api-request',
    	'blob',
    	'core-data',
    	'data',
    	'date',
    	'deprecated',
    	'dom',
    	'element',
    	'keycodes',
    	'plugins',
    	'shortcode',
    ];
    
    const wordPressPackages = [
    	'a11y',
    	'dom-ready',
    	'hooks',
    	'i18n',
    	'is-shallow-equal',
    ];
    
    const externals = {
    	react: 'React',
    	'react-dom': 'ReactDOM',
    	tinymce: 'tinymce',
    	moment: 'moment',
    	jquery: 'jQuery',
    	lodash: 'lodash',
    	'lodash-es': 'lodash'
    };
    
    [
    	...entryPointNames,
    	...gutenbergPackages,
    	...wordPressPackages,
    ].forEach( ( name ) => {
    	externals[`@wordpress/${ name }`] = {
    		window: ['wp', name],
    	};
    } );
    
    module.exports = {
    	output: {
    		library: ['wp', '[name]'],
    		libraryTarget: 'window',
    	},
    	mode: 'production',
    	module: {
    		rules: [
    			{
    				test: /\.js$/,
    				exclude: /node_modules/,
    				use: {
    					loader: 'babel-loader',
    					options: {
    						presets: ['@babel/preset-env']
    					}
    				}
    			}
    		]
    	},
    	devtool: 'source-map',
    	externals,
    	resolve: {
    		extensions: ['.js', '.jsx']
    	}
    };

    こんな感じの config を書いてます。externals の 設定を行えば、@wordpress/{packageName} みたいなので、import の解決が出来ます。output の設定も書かないとうまいこと動きません。ここでちょっとつまづきました。

    メリット

    • コアのソースをコピペするときに、import とかを書き換えなくて済む。
    • npm で、@wordpress/editor 等を devDependencies で入れておけば、PHPStorm 等でコードジャンプが容易に出来る。
    • ちょっとカッコいい。

    addFilter 等もあるため、コアのソースを読みたいという瞬間はかなり多いです。ですので、コードジャンプが行えるのは大きな利点なのかなとおもいます。

  • registerBlockType の styles プロパティ

    wp.blocks.registerBlockType に styles というプロパティがあります。これにちょっとした設定をするだけで、「追加 CSS クラス」がグラフィカルに適用できるようになります。「ブロックタイプを変更」というボタンが出現し、GUIで適用するスタイルを選択出来ます。

    「ブロックタイプを変更」を押したときの様子

    実装

    'use strict';
    const { registerBlockType } = 'wp.blocks';
    
    registerBlockType( 'block-example/basic', {
    	title: 'Example',
    	icon: 'universal-access-alt',
    	category: 'example',
    	styles: [
    		{ name: 'default', label: 'default', isDefault: true },
    		{ name: 'style1', label: 'スタイル1' },
    		{ name: 'style2', label: 'スタイル2' },
    	],
    	edit ( { className } ) {
    		return <div className={ className }>Basic example with JSX! (editor)</div>;
    	},
    	save ( { className } ) {
    		return <div className={ className }>Basic example with JSX! (front)</div>;
    	},
    } );
    

    実装はこんな感じでとにかくシンプルです。styles プロパティを指定するだけです。適用される class は is-style-style1 だとか、is-style-[name] という格好になります。

    GUI でゴリゴリ出来ていろいろ楽そうですねこれ。