多くの開発者が、Gutenbergのブロックやアプリ開発を始めるハードルの高さに不満を抱いています。習得の難易度が高い理由は、開発環境のインストールと設定の複雑さにあります。しかも、ブロック開発には、JavaScript、Node.js、React、Reduxの深い知識が必要です。
WordPress公式のブロックエディターハンドブックは有用なリソースですが、開発者向けの膨大な情報の中で、初心者が迷子になることはほぼ間違いないでしょう。
Gutenbergプロジェクトのリード開発者Matías Ventura氏は、WP Tavernのインタビューで以下のように語っています。
すぐにブロック開発を習得できる人もいますが、やはり多くの人にとって大きな壁となっています。段階的な習得が必要になりますが、ドキュメントは、構成も表現も桁違いに改善できるはずです。もっといろいろなことができればと思っています。(英語原文の日本語訳)
そこで、今回の記事では、Gutenbergブロック開発について、徹底的に解説していきます。
それでは、早速始めましょう!
Gutenbergブロック開発の前提条件
WordPressプラグイン開発の知識と、基本的なHTML、CSS、JavaScript、Reactの知識のみを使って実行できる範囲でご説明していきます。
今回の記事は、やや長編になりそうです。
必要な情報をすべて盛り込みつつ、わかりやすい簡潔な解説を行うため、適切な妥協点を探り、取り上げるトピックを厳選しました。
中級者・上級者の方々は、Reactのステート、Reduxのストア、高階コンポーネントなどに触れないことに不満を感じられるかもしれませんが、今回はご了承ください。これらのトピックを網羅すると、さらに長尺になり、(React開発者でない限り)ブロック開発の初心者にとって高度過ぎる内容になってしまうという判断です。
同じ理由で、ダイナミックブロックやメタボックスなど、Gutenbergのブロック開発に関連する高度なトピックも今回は取り上げません。
しかし、この記事を通してブロック開発の基礎を理解すれば、すぐに生産的な開発を始められるはず。
そして、一度ブロック開発を始めれば、スキルを磨きながら、より高度なGutenbergブロックを作成できるようになるはずです。
Gutenbergのブロック
2018年12月のリリース以来、ブロックエディターは、あらゆる面で大きく改善されました。強力なAPI、高度なユーザーインターフェース、ユーザビリティの向上、数々のブロック、フルサイト編集の最初の実装など。
未だ開発中のGutenbergも、それなりに長い道のりを歩んできました。今日、ブロックエディターは、ページビルダーやサイトビルダーとして、信頼性も向上し、機能的で、十分な成長を見せています。
開発者の視点で見ると、Gutenbergは、WordPress利用者がコンテンツを作成、編集、削除できる、Reactベースのシングルページアプリケーション(SPA)です。ただし、従来のコンテンツエディターの拡張ではありません。
この点について、少し掘り下げてみましょう。
Gutenbergでは、コンテンツをブロックに分割します。ブロックは、投稿や固定ページ、あるいはウェブサイト全体の作成に使用できるレンガのようなものです。
では、技術的に見たブロックの定義とは何でしょうか。
WordPressがこれをうまく表現しています。
「ブロック」とは、ウェブページのコンテンツやレイアウトを構成するマークアップのまとまりを表す抽象的な用語である。アイデアとしては、今日のWordPressで、ショートコード、カスタムHTML、埋め込みの発見で実現している概念を、単一の一貫したAPIやユーザー体験と統合したものと言える。(英語原文の日本語訳)
タイトル、段落、カラム、画像、ギャラリー、そしてサイドバーパネルからブロックツールバーコントロールまで、エディターのインターフェースを構成するすべての要素は、Reactコンポーネントです。
では、Reactコンポーネントとは何でしょうか。W3Schoolsは、以下のように定義しています。
コンポーネントは、独立した、再利用可能な小さなコードである。JavaScriptの関数と同じ目的を果たすが、分離して動作し、
render()
関数でHTMLを返す。(英語原文の日本語訳)
Gutenbergは、従来のWordPressクラシックエディターとは異なりますが、データベース内でのコンテンツの保存方法は同じです。これは、GutenbergがWordPress内で動作するアプリケーションであり、コアでのCMSの動作に変化はないためです。
Gutenbergで作成した投稿(および固定ページ、カスタム投稿タイプ)は、クラシックエディター同様、wp_posts
テーブルに格納されます。
しかし、テーブル内のGutenbergで作成された投稿には、クラシックエディターで作成された投稿と根本的に異なる情報が追加されています。
HTMLコメントのようにも見えるこの情報には、区切りブロックという機能があります。
このブロックを区切る、区切りブロックは、画面にレンダリングするブロックとJSONオブジェクトのブロックプロパティの値を定義します。プロパティは、ブロックが画面上でどのように表示されるかを決定します。
WordPress開発環境のセットアップ
最新のJavaScript開発環境をセットアップするには、Webpack、React、JSX、Babel、ESLintなどの高度な技術に関する確実な知識が求められます。
一見尻込みしてしまいそうですが、ご安心を。WordPressコミュニティが、すでに救いの手を差し伸べており、面倒な個別の設定を回避できる、優れたツールが存在しています。
この記事では簡潔な解説を心がけるため、トランスパイルについては触れません(ブロック開発の基本を習得後に学習することをお勧めします)。代わりに、最新のJavaScript開発環境を、素早く簡単に、数分でセットアップできる、2つの代替ツールを紹介します。開発するプロジェクトに応じて、便利な方を選択してください。
Gutenbergブロック構築用のJavaScript開発環境のセットアップは、以下の3つのステップで行います。
では、それぞれの手順を見ていきましょう。
1. Node.jsとnpmのインストール
開発環境をインストールし、最初のブロックを登録する前に、Node.jsとNodeパッケージマネージャ(npm)をインストールする必要があります。
Node.jsとnpmは、複数の方法でインストールできますが、まずは、コンピュータにインストール済みかどうかを確認してください。
ターミナルを起動し、次のコマンドを実行します。
node -v
結果が「command not found
(コマンドが見つかりません)」であれば、Node.jsはインストールされていません。このままインストールを進めてください。
この記事では、最も簡単なインストール方法であるNodeインストーラを使った方法をご紹介します。使用しているオペレーティングシステムに対応するバージョンをダウンロードし、ウィザードを起動するだけでインストールできます。
Node.jsのインストールが完了したら、再度ターミナルでnode -v
コマンドを実行します。また、npm -v
コマンドを実行して、npmパッケージを利用できることも確認します。
これで、以下のツールを使えるようになりました。
npx
:Node.jsパッケージランナー(ドキュメント参照)。インストールせずに、npm
コマンドを実行する。npm
:Node.jsパッケージマネージャ(ドキュメント参照)。依存関係のインストールとスクリプトを実行する。
次に開発環境をインストールします。
2. 開発環境のセットアップ
ローカル環境に最新版のNode.jsとnpmをインストールしたら、次に、WordPressの開発環境が必要です。
これには、DevKinstaのようなローカル開発環境を使うか、WordPressの公式ツールを使うかのどちらかになります。それぞれの方法を見てみましょう。
方法1. DevKinstaを使用する
KinstaのローカルWordPress開発ツール「DevKinsta」を使用すれば、数クリックでローカルにWordPressをインストールできます。また、DevKinstaの他に、MAMPやXAMPPなど、他のローカル開発ツールも選択できます。
方法2. wp-envを使用する
公式ツール「wp-env
」もあります。wp-envは、コマンドラインから直接起動して、ローカルのWordPress開発環境を作成できます。Noah Alen氏は、wp-envを以下のように定義しています。
WordPressのローカル環境はコマンド1つで、簡単に構築できるようになりました。
wp-env
を使用すると、個別の設定をしなくても簡単にローカル環境を構築し、オプションの指定により、時間をかけずに素早くWordPressを起動できます。wp-env開発によって、開発者、デザイナー、管理者など、誰もがローカル環境を簡単に利用できることが目標です。(英語原文の日本語訳)
wp-env
は、以下の2ステップでインストールできます。
ステップ1. DockerとNode.jsのインストールを確認する
インストール要件を満たすには、まずDockerとNode.jsの両方をコンピュータにインストールする必要があります。wp-env
は、WordPressウェブサイトを実行するDockerインスタンスを作成します。コードに加えられた変更は、即座にWordPressのインスタンスに反映されます。
ステップ2. コマンドラインから@wordpress/env
をインストールする
DockerとNode.jsがコンピュータ上で動作している状態で、次に、WordPress開発環境をインストールします。
wp-env
は、グローバルにもローカルにもインストールできます。グローバルにインストールするには、pluginsディレクトリからコマンドを実行してください(以下の「重要」セクションで詳しくご説明します)。
npm install -g @wordpress/env
コマンドのオプションは以下のとおりです。
npm install
:パッケージをインストールする-g
:コマンドに付加して、特定のパッケージをグローバルにインストールする@wordpress/env
:インストールするパッケージ
wp-env
が正常にインストールされたことを確認するには、次のコマンドを実行します。
wp-env --version
wp-env
の現在のバージョンが表示されるはずです。これで、プラグインのフォルダから次のコマンドを使用して、環境を起動できます。
wp-env start
WordPressの管理画面には、以下のアドレスでアクセスできます。
- http://localhost:8888/wp-admin/
デフォルトの認証情報は以下のとおりです。
- ユーザー名:
admin
- パスワード:
password
ブロックプラグインのセットアップ
次に、開発のベースとなるスターターブロックプラグインが必要ですが、すべてのファイルやフォルダを含むプラグインの準備は不要です。開発ツールを実行するだけで、ブロック開発に必要なすべてのファイルや設定を準備することができます。
これを行うには、2つの方法があります。それぞれ詳しく見ていきましょう。
方法1. @wordpress/create-blockを使用する
@wordpress/create-blockは、Gutenbergブロックを作成する、構成の不要な公式ツールです。
Create Blockは、ブロックのWordPressプラグインのひな形を作成する、公式サポートツールです。構成は不要で、モダンなビルド環境を構築します。PHP、JS、CSSコード、その他、プロジェクトの開始に必要なすべてのファイルを生成します。
Create Blockはcreate-react-appから多大な影響を受けました。@gaearon、Facebookの開発者、そしてReactコミュニティに大きな賛辞を送ります。
ローカル環境を起動したら、npx @wordpress/create-bloc
kコマンドを実行するだけで、スターターブロックをセットアップできます。このコマンドは、プラグインのひな形を作成し、新しいブロックの登録に必要な、すべてのファイルとフォルダを準備します。
テストを実行し、どのように動作するかを確認してみます。
コマンドラインツールから、/wp-content/plugins/ディレクトリに移動して、次のコマンドを実行してください。
npx @wordpress/create-block my-first-block
確認を求められたら、y
を入力して次に進みます。
この処理には少し時間がかかります。完了すると、以下のようなメッセージが表示されます。
以上です!
次にWordPressの開発環境を起動し、WordPress管理画面の「プラグイン」画面を表示します。一覧にプラグイン「My First Block」が追加されているはずです。
必要に応じてプラグインを有効化し、新しいブログ投稿を作成します。次に、ブロックインサーターを「ウィジェット」セクションまでスクロールして、新しいブロックを選択します。
ここでターミナルに戻り、カレントディレクトリをmy-first-blockに変更します。
cd my-first-block
以下のコマンドを実行します。
npm start
これでプラグインを開発モードで実行できます。本番用のコードを作成するには、以下のコマンドを実行します。
npm run build
方法2. create-guten-blockを使用する
create-guten-block
は、Gutenbergブロックを構築する、サードパーティ製の開発ツールです。
create-guten-block
は、構成の不要な開発ツールキット(#0CJS)です。React、webpack、ES6/7/8/Next、ESLint、Babelなどを個別に設定しなくても、WordPress Gutenbergブロックを数分で開発できます。
公式のcreate-block
ツールと同様に、create-guten-block
も、create-react-appをベースにしており、最初のブロックプラグインを簡単に生成できます。
このツールキットには、最新のWordPressプラグインの作成に必要な、以下を含むすべての機能が揃っています。
- React、JSX、ES6構文に対応
- バックグラウンドで実行される、webpack開発用、本番用のビルドプロセス
- オブジェクトスプレッド演算子など、ES6を超える言語拡張
- -webkitなどの接頭辞が不要な、CSSの自動接頭辞
- 本番用に、JS、CSS、画像をソースマップ付きでバンドルするビルドスクリプト
- cgb-scriptsのみへの依存による機能の更新
なお、以下の点に注意してください。
トレードオフとして、これらのツールは特定の方法で動作するように構成されています。もし、プロジェクトで高度なカスタマイズが必要であれば、境界を越えて自由にカスタマイズできますが、そのときも、構成を維持する必要があります。
WordPressのローカルサイトを手元に用意したら、コマンドラインツールを起動し、インストール先の/wp-content/pluginsフォルダに移動して、以下のコマンドを実行します。
npx create-guten-block my-first-block
プロジェクト構造の作成、依存関係のダウンロードには、1~2分ほどかかります。
処理が完了すると、以下の画面が表示されます。
以下のスクリーンショットは、Visual Studio Code内で稼働しているターミナルとプロジェクト構造の様子です。
次に、WordPressの管理画面に戻ります。「プラグイン」画面に「my-first-block」プラグインが表示されているはずです。
プラグインを有効化し、ターミナルに戻ります。カレントディレクトリを「my-first-block」に変更し、npm start
を実行します。
cd my-first-block
npm start
以下のような応答があるはずです。
この場合も、プラグインは開発モードで実行されます。本番用のコードを作成するには、以下のコマンドを使用します。
npm run build
プラグインを有効化して、新規投稿または固定ページを作成します。ブロックインスペクタを検索して、Gutenbergブロックを選択します。
詳細な概要や、発生したエラーへの対応については、Ahmad Awais氏のドキュメントをご覧ください。
スターターブロックのひな形の探索
create-block
とcreate-guten-block
のどちらの開発ツールを選択しても、ブロックプラグイン構築の出発点として利用可能なブロックのひな形を取得できます。
ブロックのひな形とは何でしょうか。
ブロックのひな形とは、WordPressからブロックとして認識されるために必要なディレクトリ構造を表す言葉です。通常、このディレクトリにはindex.php、index.js、style.cssなどのファイルがあり、ファイルの内部には
register_block_type
などの呼び出しが含まれます。
ブロックエディターハンドブックでも使用されている公式のCreate Block開発ツールを使用します。ただし、create-guten-block
のようなサードパーティツールでも大きな違いはないはずです。
それでは、create-block
ツールを見ていきましょう。
開発ツール「Create Block」とは
前述のように、Create Blockは、Gutenbergブロックを作成する公式のコマンドラインツールです。ターミナルで@wordpress/create-block
を実行すると、新しいブロックタイプの登録に必要な、PHP、JS、SCSSファイルとコードが生成されます。
npx @wordpress/create-block [options] [slug]
[slug]
(任意):ブロックのスラッグの割り当てとプラグインのインストールに使用される[options]
(任意):利用可能なオプション
デフォルトでは、ESNextテンプレートが割り当てられます。すなわち、JSX構文が追加された次バージョンのJavaScriptが作成されます。
ブロック名を省略すると、コマンドは対話モードで実行され、ファイル生成前に複数の設定を編集することができます。
npx @wordpress/create-block
下のスクリーンショットは、公式のCreate Blockツールで作成された、ブロックプラグインのファイル構成です。
ブロックプラグインの主なファイルとフォルダを確認します。
プラグインファイル
メインのプラグインファイルでは、サーバーにブロックを登録します。
<?php
/**
* Plugin Name: Kinsta Academy Block
* Plugin URI: https://kinsta.com/
* Description: An example block for Kinsta Academy students
* Requires at least: 5.9
* Requires PHP: 7.0
* Version: 0.1.0
* Author: Kinsta Students
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: ka-example-block
*
* @package ka-example-block
*/
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/reference/functions/register_block_type/
*/
function ka_example_block_ka_example_block_block_init() {
register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'ka_example_block_ka_example_block_block_init' );
register_block_type
関数は、block.jsonファイルに格納されたメタデータを使用して、サーバーにブロックタイプを登録します。
この関数は2つのパラメータを取ります。
- 名前空間を含むブロックタイプ名、またはjsonファイルがあるフォルダのパス、または完全な
WP_Block_Type
オブジェクト - ブロックタイプの引数の配列
上のコードでは、ブロックタイプの引数に、マジック定数「__DIR__
」が指定されています。これは、プラグインのファイルと同じフォルダにblock.jsonファイルが存在することを意味します。
package.jsonファイル
package.jsonファイルは、プロジェクトのJavaScriptプロパティとスクリプトを定義します。ここには、プロジェクトの依存関係もインストールできます。
コードエディターでファイルを開き、内容を確認してください。
{
"name": "ka-example-block",
"version": "0.1.0",
"description": "An example block for Kinsta Academy students",
"author": "Kinsta Students",
"license": "GPL-2.0-or-later",
"homepage": "https://kinsta.com/",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip",
"start": "wp-scripts start"
},
"devDependencies": {
"@wordpress/scripts": "^24.1.0"
},
"dependencies": {
"classnames": "^2.3.2"
}
}
scripts
プロパティは、コマンドを含む連想配列です。コマンドはnpm run [cmd]
を使用して、パッケージのライフサイクルの様々なタイミングで実行されます。
この記事では、以下のコマンドを使用します。
npm run build
:(圧縮された)本番用ビルドを作成npm run start
:(圧縮されていない)開発用ビルドを作成
dependencies
とdevDependencies
は、パッケージ名とバージョンを対応付ける2つのオブジェクトです。dependencies
は本番用ビルドで、devDependences
はローカル開発でのみ必要です(詳細はこちら)。
デフォルトのdevDependenciesは、@wordpress/scripts
パッケージのみで、これは「WordPress開発専用の、再利用可能なスクリプト集」として定義されています。
block.jsonファイル
WordPress 5.8以降、正式なブロックタイプの登録には、block.jsonメタデータファイルを使用します。
block.jsonファイルには、パフォーマンスの向上や、WordPressプラグインディレクトリでの視認性の向上など、様々な利点があります。
パフォーマンスの観点から、テーマがアセットの遅延ロードをサポートするとき、block.jsonで登録されたブロックは、デフォルトでアセットのキュー処理が最適化されます。
style
またはscript
プロパティにリストされたフロントエンドCSSやJavaScriptアセットは、ブロックがページ上に存在するときのみキューに入れられ、結果、ページサイズが縮小します。
@wordpress/create-block
コマンドを実行すると、以下のblock.jsonファイルが生成されます。
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "ka-example-block/ka-example-block",
"version": "0.1.0",
"title": "Kinsta Academy Block",
"category": "widgets",
"icon": "superhero-alt",
"description": "An example block for Kinsta Academy students",
"supports": {
"html": false
},
"textdomain": "ka-example-block",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
以下は、デフォルトのプロパティの一覧です。
apiVersion
:ブロックが利用するAPIのバージョン(現在のバージョンは2)name
:名前空間を含むブロックの一意な識別子version
:ブロックの現在のバージョンtitle
:ブロックの表示タイトルcategory
:ブロックのカテゴリicon
:Dashiconのスラッグまたは自作SVGアイコンdescription
:ブロックインスペクタに表示される短い説明supports
:エディターで使用される機能を制御するオプション群textdomain
:プラグインのテキストドメインeditorScript
:エディタースクリプト定義editorStyle
:エディタースタイル定義style
:ブロックの代替スタイルを指定
上のプロパティに加えて属性オブジェクトを定義でき、ブロックが保存するデータに関する情報を指定できます。block.jsonでは、キーと値のペアでいくつでも属性を設定できます。この時、キーは属性名、値は属性定義です。
以下は属性定義の例です。
"attributes": {
"content": {
"type": "array",
"source": "children",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"link": {
"type": "string",
"default": "https://kinsta.com"
}
},
block.jsonファイルについてはこの記事の後半で詳しくご説明しますが、ブロックエディターハンドブックでも、block.jsonファイルのメタデータや属性について詳しく解説されていますので、参照してみてください。
srcフォルダ
src
フォルダは、開発が行われる場所です。フォルダには、以下のファイルがあります。
- index.js
- edit.js
- save.js
- editor.scss
- style.scss
index.js
index.jsファイルは出発点です。依存関係をインポートし、ブロックタイプをクライアントに登録します。
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
import metadata from './block.json';
registerBlockType( metadata.name, {
/**
* @see ./edit.js
*/
edit: Edit,
/**
* @see ./save.js
*/
save,
} );
最初の文では、@wordpress/blocks
パッケージからregisterBlockType
関数をインポートしています。続くimport文は、スタイルシート、Edit
関数、save
関数をインポートしています。
registerBlockType
関数は、クライアントでコンポーネントを登録します。この関数は2つのパラメータを取ります。ブロック名の「名前空間/ブロック名」(サーバー上で登録されたものと同じ)とブロック構成オブジェクトです。
Edit
関数はブロックエディターで描画されるブロックインターフェースを定義し、save
関数はシリアライズされてデータベースに保存される構造を定義します(詳しくはこちら)。
edit.js
edit.jsでは、ブロック管理インターフェースを構築します。
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p {...useBlockProps()}>
{__('My First Block – hello from the editor!', 'my-first-block')}
</p>
);
}
まず、@wordpress/i18n
パッケージ(このパッケージには、JavaScript版の翻訳関数が含まれています)の__
関数、useBlockProps
Reactフック、editor.scss
ファイルをインポートしています。
続いて、Reactコンポーネントをエクスポートします(詳細はimport文とexport文をご覧ください)。
save.js
save.jsファイルでは、データベースに保存するブロック構造を構築します。
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
export default function save() {
return (
<p {...useBlockProps.save()}>
{__(
'My First Block – hello from the saved content!',
'my-first-block'
)}
</p>
);
}
editor.scssとstyle.scss
スクリプトとは別に、2つのSASSファイルがsrcフォルダに存在します。editor.scssファイルにはエディターのコンテキストでブロックに適用されるスタイルが含まれ、style.scssファイルにはフロントエンドとエディターでの表示用のブロックのスタイルが含まれます。これらのファイルについては、この記事の後半で掘り下げていきます。
node_modulesとbuildフォルダ
node_modules
フォルダには、nodeモジュールとその依存関係が格納されています。nodeパッケージは、この記事で扱う範囲を超えるため深入りしませんが、npmがパッケージをインストールする場所については、この記事をご覧ください。
build
フォルダには、ビルド処理で生成されたJSファイルとCSSファイルが格納されます。詳しいビルドプロセスについては、「ESNext構文」と「JavaScriptビルド環境のセットアップ」をご覧ください。
実践─Gutenbergブロックを作成しよう
それでは、実際にブロックを作っていきましょう。このセクションでは、CTA(コール・トゥ・アクション)ブロック、Kinsta Academyブロックを実装するプラグインの作成方法をご説明します。
ブロックは2つのカラムで構成され、左側に画像、右側にテキストの段落があります。テキストの下には、編集可能なリンクが付いたボタンが配置されます。
これは簡単な例ですが、Gutenbergブロック開発の基本を網羅することができます。一通り理解できたら、ブロックエディターハンドブックなどのリソースを参照して、より複雑なGutenbergブロックを作ってみてください。
今回は、ローカル開発環境で最新版のWordPressが稼働していることを前提とし、以下の順番でブロック開発をご紹介していきます。
- スターターブロックプラグインのセットアップ
- jsonの編集
- 組み込みコンポーネントの使用─RichTextコンポーネント
- ブロックツールバーへのコントロールの追加
- ブロック設定サイドバーの編集
- 外部リンクの追加と編集
- 複数のブロックスタイルの追加
- InnerBlocksコンポーネントを使用したブロックのネスト
- 細かな編集
では、始めましょう。
スターターブロックプラグインのセットアップ方法
コマンドラインツールを起動して、/wp-content/pluginsフォルダに移動します。
以下のコマンドを実行します。
npx @wordpress/create-block
このコマンドは対話モードで、ブロック登録用のPHP、SCSS、JSファイルを生成します。対話モードでは、ブロックに必要なデータを簡単に設定できます。この記事では、以下の値を使用します。
- Template variant(テンプレート):static(静的)
- Block slug(ブロックのスラッグ):ka-example-block
- Internal namespace(内部名前空間):ka-example-block
- Block display title(ブロック表示タイトル):Kinsta Academy Block
- Short block description(ブロックの説明):An example block for Kinsta Academy students(Kinstaアカデミー受講者向けブロックの例)
- Dashicon(アイコンフォント):superhero-alt
- Category name(カテゴリ名):widgets
- Do you want to customize the WordPress plugin?(WordPressプラグインを編集しますか?):Yes
- The home page of the plugin(プラグインのトップページ):https://kinsta.com/
- Current plugin version(現在のプラグインのバージョン):1.0
- Plugin author(プラグイン開発者名) :自分の名前
- License(ライセンス):─
- Link to the license text(ライセンステキストへのリンク):─
- Custom domain path for translation(翻訳用独自ドメインパス):─
プラグインとすべての依存関係をインストールするには、数分かかります。処理が完了すると、以下のようなメッセージが表示されます。
次に、/wp-content/pluginsフォルダから以下のコマンドを実行します。
cd ka-example-block
最後に、プラグインのフォルダ(この例ではka-example-block)から次のコマンドを入力して、開発を始めます。
npm start
「プラグイン」画面を開き、「Kinsta Academy Block」プラグインを有効化してください。
新しい投稿を作成し、ブロックインサーターを開き、「デザイン」カテゴリまでスクロールします。「Kinsta Academy Block」をクリックして、投稿に追加してください。
block.jsonの編集
前述したように、サーバーサイドのブロック登録はメインの.phpファイルで行われます。しかし、ここでは.phpファイル内で設定を定義しません。代わりに、block.jsonファイルを使用します。
もう一度block.jsonを開いて、デフォルトの設定を詳しく見てみましょう。
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "ka-example-block/ka-example-block",
"version": "0.1.0",
"title": "Kinsta Academy Block",
"category": "widgets",
"icon": "superhero-alt",
"description": "An example block for Kinsta Academy students",
"supports": {
"html": false
},
"textdomain": "ka-example-block",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
スクリプトとスタイル
editorScript
、editorStyle
、style
プロパティには、フロントエンドとバックエンドのスクリプトとスタイルへの相対パスを指定します。
ここで定義したスクリプトとスタイルは、WordPressによって自動的に登録され、キューに入れられるため、手動で登録する必要はありません。確認のため、ブラウザの「検証」を起動し、「ネットワーク」タブを開いてください。
上のスクリーンショットからもわかるように、buildフォルダ内のindex.jsスクリプトは、正しくキューに入れられています。PHPコードを記述する必要はありません。
UIラベル
title
とdescription
プロパティには、エディター上でのブロックの識別に必要なラベルを指定します。
キーワード
前述したように、プロパティと属性を使用してブロックを設定できます。例えば、1つ以上のkeywords
を追加して、ブロックを検索しやすくできます。
"keywords": [
"kinsta",
"academy",
"superhero"
],
クイックインサーターに「kinsta」「academy」または「superhero」を入力すると、エディターに「Kinsta Academy」ブロックが表示されます。
ローカライズ
JSONファイル内の文字列をローカライズする方法については、こちらをご覧ください。
JavaScript内では、
@wordpress/blocks
パッケージのregisterBlockTypeFromMetadata
メソッドと、block.jsonファイルから読み込んだメタデータを使用して、ブロックタイプを登録できるようになりました。すべてのローカライズされたプロパティは、PHPのregister_block_type_from_metadata
と同様に、自動的に_x
(@wordpress/i18n
パッケージ)関数呼び出しにラップされます。唯一の要件として、block.jsonファイルにtextdomain
プロパティを設定してください。
ここでは、registerBlockTypeFromMetadata
の代わりにregisterBlockType
関数を使用します。Gutenberg 10.7以降、registerBlockTypeFromMetadataが非推奨になったためですが、仕組みは同じです。
組み込みコンポーネントの使用─RichTextコンポーネント
Gutenbergブロックを構成する要素は、Reactコンポーネントであり、wp
グローバル変数でアクセスできます。例えば、ブラウザのコンソールにwp.editorと
入力すると、wp.editor
モジュールに含まれるコンポーネントの一覧が表示されます。
リストをスクロールして、コンポーネントの名前から中身を推測してみてください。
同様に、wp.components
モジュールに含まれるコンポーネントの一覧を確認できます。
edit.jsファイルに戻り、スクリプトを詳しく見てみましょう。
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit() {
return (
<p { ...useBlockProps() }>
{ __(
'Kinsta Academy Block – hello from the editor!',
'ka-example-block'
) }
</p>
);
}
このコードは、シンプルで編集できないテキストを含む静的ブロックを生成しますが、簡単に変更できます。
テキストを編集可能にするには、現在の<p>タグを、入力内容を編集できるコンポーネントで置き換えます。Gutenbergには、この目的で使用できる組み込みのRichTextコンポーネントがあります。
組み込みコンポーネントは、5つのステップでブロックに追加できます。
ステップ1. WordPressパッケージから必要なコンポーネントをインポートする
edit.jsファイルを開き、import
文を変更します。
import { useBlockProps } from '@wordpress/block-editor';
上のimport文を以下のように変更してください。
import { useBlockProps, RichText } from '@wordpress/block-editor';
@wordpress/block-editor
パッケージから、useBlockProps
関数とRichText
コンポーネントをインポートしています。
useBlockProps
useBlockProps
Reactフックは、ブロックのラッパー要素をマークします。
APIバージョン2を使用するには、ブロックの
edit
関数内で新しいuseBlockProps
フックを使用して、ブロックのラッパー要素をマークする必要があります。useBlockProps
フックは、ブロックの動作の有効化に必要な属性とイベントハンドラを挿入します。ブロック要素にはuseBlockProps
を介して属性を渡し、戻り値は要素に展開する必要があります。
つまり、useBlockProps
は、ラッパー要素(この例ではp要素)に自動的に属性とクラスを割り当てます。
ラッパー要素からuseBlockProps
を削除すると、単純なテキスト文字列になってしまい、ブロックの機能やスタイルにアクセスできません。
後で触れますが、useBlockProps
には、プロパティのオブジェクトを渡しても、出力をカスタマイズできます。
RichText
RichTextコンポーネントには編集可能な入力領域があり、ユーザーはコンテンツを編集し、書式を設定できます。
GitHubのRichTextコンポーネントのドキュメントをご覧ください。
ステップ2. JSXコードに対応する要素を追加する
...
const blockProps = useBlockProps();
return (
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);
各行は以下の通りです。
tagName
:編集可能なHTML要素のタグ名onChange
:要素の内容が変更されたときに呼び出される関数allowedFormats
:許可されるフォーマットの配列(デフォルトでは、すべてのフォーマットが許可されます)value
:編集可能になるHTML文字列placeholder
:要素が空のときに表示されるプレースホルダテキスト
ステップ3. block.jsonファイルに必要な属性を定義する
属性は、リッチコンテンツ、背景色、URLなど、ブロックが保存するデータに関する情報を保持します。
attributes
オブジェクト内には、キーと値のペアで任意の数の属性を設定できます。キーは属性名、値は属性定義です。
block.jsonファイルを開き、以下のattributes
プロパティを追加します。
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
}
},
content
属性は、編集可能フィールドに入力されたテキストを格納できます。
type
は、属性によって保存されるデータの種類を示します。このプロパティは、enum
プロパティを定義しない限り必須です。source
は、投稿のコンテンツから、どのように属性値を抽出するかを定義します。この例では、HTMLコンテンツです。注意)このプロパティを指定しなければ、データはブロックデリミタに格納されます(詳細はこちら)。selector
は、HTMLタグ、またはクラス名やid属性などのその他のセレクタです。
Edit
関数には、プロパティのオブジェクトを渡します。edit.jsファイルに戻り、以下のように変更してください。
export default function Edit( { attributes, setAttributes } ) { ... }
ステップ4. イベントハンドラを定義する
RichText
要素にはonChange
属性があり、要素の内容が変更されたときに呼び出される関数を指定します。
以下は、この関数を定義したedit.jsスクリプトの全文です。
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
return (
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
/>
);
}
ファイルを保存して、ターミナルウィンドウでnpm run startを実行します。WordPressの管理画面に戻り、新規投稿または固定ページを作成し、Kinsta Academyブロックを追加します。
テキストを入力して、コードビューに切り替えます。コードは以下のようになります。
<!-- wp:ka-example-block/ka-example-block -->
<p class="wp-block-ka-example-block-ka-example-block">Kinsta Academy Block – hello from the saved content!</p>
<!-- /wp:ka-example-block/ka-example-block -->
ここでページを保存してフロントエンドの表示をチェックしても、残念なことに変更はサイトに反映されていません。save.jsファイルを修正して、投稿を保存する際、データベースに入力を保存する必要があります。
ステップ5. データを保存する
save.jsファイルを開き、スクリプトを次のように変更します。
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ attributes.content }
/>
);
}
ここでは以下を実行しています。
block-editor
パッケージからRichText
コンポーネントをインポートするsave
関数にオブジェクト引数を介して複数のプロパティを渡す(この例ではattributes
プロパティのみを渡しています)RichText
コンポーネントのコンテンツを返す
RichText
コンポーネントの詳細については、ブロックエディターハンドブック、プロパティの一覧については、Githubを参照してください。
次は、ブロックツールバーにコントロールを追加します。
ブロックツールバーへのコントロールの追加
ブロックツールバーには、ブロックコンテンツの一部を操作できるコントロールが並びます。各ツールバーコントロールには、コンポーネントがあります。
例えば、ブロックにはテキスト配置コントロールを追加できます。必要な作業は、@wordpress/block-editor
パッケージから2つのコンポーネントをインポートするだけです。
前の例と同じ手順で進めていきます。
- WordPressパッケージから必要なコンポーネントをインポートする
- JSXコードに対応する要素を追加する
- block.jsonファイルに必要な属性を定義する
- イベントハンドラを定義する
- データを保存する
ステップ1. @wordpress/block-editorからBlockControlsとAlignmentControlコンポーネントをインポートする
ブロックツールバーに配置コントロールを追加するには、2つのコンポーネントが必要です。
BlockControls
は、コントロールの動的ツールバーをレンダリングします(ドキュメントなし)。AlignmentControl
は、選択されたブロックの整列方法を表示するドロップダウンメニューをレンダリングします(詳細についてはこちら)。
edit.jsを開き、以下のようにimport
文を編集します。
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls
} from '@wordpress/block-editor';
ステップ2. BlockControlsとAlignmentControl要素を追加する
Edit
関数に移動し、<BlockControls />
要素を<RichText />
と同じレベルで挿入します。次に、<BlockControls />
の中に<AlignmentControl />
を追加します。
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}
上のコードで<>
と</>
は、Reactで複数の要素を返す「フラグメント」を宣言する短い記法です。
この例では、AlignmentControl
に2つの属性があります。
value
は、この要素の現在の値を表しますonChange
は、値が変更されたときに実行するイベントハンドラを指定します
また、RichText要素に追加の属性も定義しています(例付きの属性の一覧についてはこちら)。
ステップ3. block.jsonにalgin属性を定義する
block.jsonファイルに移動して、align
属性を追加します。
"align": {
"type": "string",
"default": "none"
}
ブロックエディターに戻り、ページを更新してブロックを選択します。ブロックツールバーに、配置コントロールが表示されるはずです。
これは、まだイベントハンドラを定義していないのが原因です。
ステップ4. イベントハンドラを定義する
次に、onChangeAlign
を以下のように定義します。
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
newAlign
がundefined
であれば、none
に設定し、そうでなければ、newAlign
を使用します。
これで、edit.jsスクリプトは(一旦)完了です。
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
<BlockControls>
<AlignmentControl
value={ attributes.align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ attributes.content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: attributes.align } }
/>
</>
);
}
これでエディターに戻って、ブロックのコンテンツを配置することができます。ブロックに配置ツールバーが表示されているはずです。
なお、投稿を保存すると、ブロックのコンテンツがブロックエディターで表示されるようにフロントエンドで配置されないことがあります。この場合、save
関数を修正して、ブロックのコンテンツと属性をデータベースに保存する必要があります。
ステップ5. データを保存する
save.jsを開き、save
関数を以下のように変更してください。
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ attributes.content }
style={ { textAlign: attributes.align } }
/>
);
}
最後に、分割代入構文を使用して、attribute
オブジェクトから個々のプロパティを抽出し、コードを整理しましょう。
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align } = attributes;
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ content }
style={ { textAlign: align } }
/>
);
}
edit.jsファイルでも同じことができます。
ファイルを保存して、コードエディターモードでエディターに戻ります。コードは以下のようになるはずです。
<!-- wp:ka-example-block/ka-example-block {"align":"right"} -->
<p class="wp-block-ka-example-block-ka-example-block" style="text-align:right">This is my first editable <strong>Gutenberg</strong> <em>block</em> 😎</p>
<!-- /wp:ka-example-block/ka-example-block -->
これで完了です。ブロックツールバーに配置コントロールを追加できました🤓
ブロックツールバーコントロールの詳細については、ブロックエディターハンドブックの「ブロックツールバーと設定サイドバー」を参照してください。
ブロック設定サイドバーの編集
コントロールは、ブロック設定サイドバーにも追加できます(アプリケーション用に新規サイドバーを作成することも)。
APIとしては、InspectorControls
コンポーネントがあります。
ブロックエディターハンドブックで、設定サイドバーの使い方を以下のように説明しています。
設定サイドバーは、あまり使わない設定や、大きな画面スペースが必要な設定で使用されます。設定サイドバーはブロックレベル設定でのみ使用してください。
ブロック内の選択したコンテンツでのみ有効な設定は(例:段落内の選択したテキストに対する「太字」設定)、設定サイドバーの中に置かないでください。設定サイドバーはHTMLモードでブロックを編集するときにも表示されるため、ブロックレベルの設定のみを配置する必要があります。
再び、同じ手順で進めます。
- WordPressパッケージから必要なコンポーネントをインポートする
- JSXコードに対応する要素を追加する
- block.jsonファイルに必要な属性を定義する
- イベントハンドラを定義する
- データを保存する
ステップ1. @wordpress/block-editorからInspectorControlsとPanelColorSettingsコンポーネントをインポートする
ブロックの特定部分をカスタマイズできるようにするには、必要なコントロールを追加します。例えば、カラーコントロールパネルを実装するには、block-editor
モジュールからInspectorControls
とPanelColorSettings
コンポーネントをインポートします。
import {
useBlockProps,
RichText,
AlignmentControl,
BlockControls,
InspectorControls,
PanelColorSettings
} from '@wordpress/block-editor';
ステップ2. JSXコードに対応する要素を追加する
次に、Edit
関数が返すJSXに、対応する要素を追加します。
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const { content, align, backgroundColor, textColor } = attributes;
const onChangeContent = ( newContent ) => {
setAttributes( { content: newContent } )
}
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
return (
<>
<InspectorControls>
<PanelColorSettings
title={ __( 'Color settings', 'ka-example-block' ) }
initialOpen={ false }
colorSettings={ [
{
value: textColor,
onChange: onChangeTextColor,
label: __( 'Text color', 'ka-example-block' )
},
{
value: backgroundColor,
onChange: onChangeBackgroundColor,
label: __( 'Background color', 'ka-example-block' )
}
] }
/>
</InspectorControls>
<BlockControls>
<AlignmentControl
value={ align }
onChange={ onChangeAlign }
/>
</BlockControls>
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
</>
);
}
なお、RichText
要素のstyle
属性も更新します。
<RichText
{ ...blockProps }
tagName="p"
onChange={ onChangeContent }
allowedFormats={ [ 'core/bold', 'core/italic' ] }
value={ content }
placeholder={ __( 'Write your text...' ) }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
ステップ3. block.jsonに必要な属性を定義する
ここで、block.jsonファイルにbackgroundColor
とtextColor
属性を定義します。
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
},
"align": {
"type": "string",
"default": "none"
},
"backgroundColor": {
"type": "string"
},
"textColor": {
"type": "string"
}
},
ステップ4. イベントハンドラを定義する
次に、入力に応じてbackgroundColor
とtextColor
を更新する2つの関数を定義します。
const onChangeBackgroundColor = ( newBackgroundColor ) => {
setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
setAttributes( { textColor: newTextColor } )
}
ステップ5. データを保存する
最後にsave.jsファイルを開き、スクリプトを以下のように変更します。
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
const { content, align, backgroundColor, textColor } = attributes;
return (
<RichText.Content
{ ...blockProps }
tagName="p"
value={ content }
style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>
);
}
ファイルを保存して、エディターでブロックを確認します。ブロックに予期せぬ、または無効なコンテンツが含まれていることを知らせるエラーメッセージが表示される場合があります。
このエラーは、save.jsファイルが変更され、データベースに保存されたコードがエディターで使用されているコードと一致しない時に発生します。
これを修正するには、ページを更新し、ブロックのインスタンスを一度削除して、再度投稿に追加してください。
変更を加え、投稿を保存して、フロントエンドで表示します。ブロックエディターで行った変更が、サイトにも反映されているはずです。
外部リンクの追加と編集
次に、ブロックタイプに新しいコンポーネントを追加します。
- カスタムブロックにカスタマイズ可能なリンクを追加できるようにする
ExternalLink
コンポーネント - リンクの設定をカスタマイズできる複数のサイドバーコントロール
ステップ1. @wordpress/componentsからコンポーネントをインストールする
@wordpress/components
から複数のコンポーネントをインポートする必要があります。edit.jsを開き、以下のimport
文を追加してください。
import {
TextControl,
PanelBody,
PanelRow,
ToggleControl,
ExternalLink
} from '@wordpress/components';
PanelBody
:設定サイドバーに折りたたみ可能なコンテナを追加PaneRow
:サイドバーコントロール用の汎用コンテナを生成TextControl
:テキスト入力用のコントロールToggleControl
:特定のオプションの有効・無効を切り替えられるトグル用コントロールExternalLink
:外部リンクを追加するシンプルなコンポーネント
ステップ2. JSXコードに対応する要素を追加する
まず、div
コンテナ内に、RichText
と同じレベルでExternalLink
要素を追加します。
<div { ...blockProps }>
<RichText
...
/>
<ExternalLink
href={ kaLink }
className="ka-button"
rel={ hasLinkNofollow ? "nofollow" : "" }
>
{ linkLabel }
</ExternalLink>
</div>
なお、ExternalLink
コンポーネントはドキュメント化されていないため、コンポーネントのソースコードを参照して利用可能な属性の一覧を取得しました。ここでは、href
、className
、rel
属性を使用しています。
デフォルトでは、rel
属性の値はnoopener noreferrer
に設定されます。このコードでは、トグルコントロールがオンのとき、結果のa
タグのrel
属性にnofollow
キーワードが追加されます。
ブロックサイドバーにリンク設定を追加します。まず、InspectorControls
内に、PanelColorSettings
と同じレベルでPanelBody
要素を追加します。
<InspectorControls>
<PanelColorSettings
...
/>
<PanelBody
title={ __( 'Link Settings' )}
initialOpen={true}
>
...
</PanelBody>
</InspectorControls>
今回は、以下を実行しています。
title
属性でパネルのタイトルを指定initialOpen
で初期状態でパネルが開いているかどうかを設定
次に、PanelBody
の中に2つのPanelRow
要素を追加し、それぞれのPanelRow
の中にTextControl
要素を追加します。
<PanelBody
title={ __( 'Link Settings', 'ka-example-block' )}
initialOpen={true}
>
<PanelRow>
<fieldset>
<TextControl
label={__( 'KA link', 'ka-example-block' )}
value={ kaLink }
onChange={ onChangeKaLink }
help={ __( 'Add your Academy link', 'ka-example-block' )}
/>
</fieldset>
</PanelRow>
<PanelRow>
<fieldset>
<TextControl
label={__( 'Link label', 'ka-example-block' )}
value={ linkLabel }
onChange={ onChangeLinkLabel }
help={ __( 'Add link label', 'ka-example-block' )}
/>
</fieldset>
</PanelRow>
</PanelBody>
上のコードは、もうかなり簡単に思えるはず。それから、2つのテキストコントロールにリンクラベルとURLを設定します。
さらに、ToggleControl
を含むPanelRow
を追加して、属性を含めるかどうかなど、特定のオプションの有効、無効を切り替えられるようにします。
<PanelRow>
<fieldset>
<ToggleControl
label="Add rel = nofollow"
help={
hasLinkNofollow
? 'Has rel nofollow.'
: 'No rel nofollow.'
}
checked={ hasLinkNofollow }
onChange={ toggleNofollow }
/>
</fieldset>
</PanelRow>
ステップ3. block.jsonに必要な属性を定義する
block.jsonファイルにkaLink
、linkLabel
、hasLinkNofollow
属性を定義します。
"kaLink": {
"type": "string",
"default": ""
},
"linkLabel": {
"type": "string",
"default": "Check it out!"
},
"hasLinkNofollow": {
"type": "boolean",
"default": false
}
これ以上、何かを追加する必要はありません。イベントハンドラ関数の定義に移りましょう。
ステップ4. イベントハンドラを定義する
edit.jsファイルに戻り、以下の関数を追加します。
const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;
const onChangeKaLink = ( newKaLink ) => {
setAttributes( { kaLink: newKaLink === undefined ? '' : newKaLink } )
}
const onChangeLinkLabel = ( newLinkLabel ) => {
setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}
const toggleNofollow = () => {
setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}
この関数は、入力に対応する属性値を更新します。
ステップ5. データを保存する
最後に、save.jsのsave
関数を更新します。
export default function save( { attributes } ) {
const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;
const blockProps = useBlockProps.save( {
className: `has-text-align-${ align }`
} );
return (
<div
{ ...blockProps }
style={ { backgroundColor: backgroundColor } }
>
<RichText.Content
tagName="p"
value={ content }
style={ { color: textColor } }
/>
<p>
<a
href={ kaLink }
className="ka-button"
rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
>
{ linkLabel }
</a>
</p>
</div>
);
}
なお、今回の例では、ExternalLink
の代わりに、通常のa
要素を使用しています。
結果は以下のようになります。
複数のブロックスタイルの追加
前のセクションでは、テキストの配置を設定できる、ブロックツールバーコントロールの追加方法について学びました。同じ手順でブロックツールバーにさらにスタイルコントロールを追加できますが、ワンクリックで選択できる、定義済みのブロックスタイルを追加する方法もあります。
これにはブロックAPIの便利な機能ブロックスタイルを使用します。
block.jsonのstyles
プロパティを定義して、対応するスタイルをスタイルシートで宣言します。
例えば、次のようなスタイルの配列を追加できます。
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "border",
"label": "Border"
}
],
これで、デフォルトのスタイルと、border
(枠)と呼ばれるスタイルが追加されました。ブロックエディターに戻ります。
スタイルは、ブロックスイッチャーをクリックし、ブロック設定サイドバーの「スタイル」パネルから利用できます。
スタイルを選択し、p
要素に適用されるクラスを確認します。ブロック上で右クリックして、「検証」を選択してください。次の形式の名前の新しいクラスが追加されています。
is-style-{style-name}
「Border
」スタイルを選択すると、p要素にis-style-border
クラスが追加されます。「Default
」スタイルを選択すると、代わりにis-style-default
クラスが追加されます。
あとは、CSSのプロパティを宣言するだけです。editor.scssを開き、現在のスタイルを以下のように置き換えます。
.wp-block-ka-example-block-ka-example-block {
padding: 4px;
}
次に、style.scssにも同様に追加します。前述したように、style.scssで定義されたスタイルは、フロントエンドとエディターの両方に適用されます。
.wp-block-ka-example-block-ka-example-block {
&.is-style-default{
border: 0;
background-color: #FFE2C7;
}
&.is-style-border{
border: 2px solid #000;
border-radius: 16px;
background-color: #F6F6F6;
}
}
これで完了です。ページを更新して、新たなブロックスタイルをお楽しみください。
InnerBlocksコンポーネントを使用したGutebnergブロックのネスト
このカスタムブロックは、機能的には十分ですが、このままでは魅力的な外観とは言えません。訪問者の目を引く写真やグラフィックを追加することができます。
画像を追加すると、ブロックに複雑なレイヤーを重ねてしまう可能性がありますが、幸い一から作りなおす必要はありません。Gutenbergには、ネストしたブロック構造を作成する特別なコンポーネントがあります。
InnerBlocks
コンポーネントは、以下のように定義されています。
InnerBlocks
は、コンポーネントのペアをエクスポートし、ネストしたブロックコンテンツを実現するブロックを実装するもの。(英語原文の日本語訳)
まず、srcフォルダに.jsファイルを作成します。今回の例では、container.jsを作成します。
次に、新しいリソースをindex.jsファイルにインポートします。
import './container';
container.jsに戻り、必要なコンポーネントをインポートします。
import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
useBlockProps,
InnerBlocks
} from "@wordpress/block-editor";
次に、内部におけるブロックの配置を規定するテンプレートを定義します。この例では、2つのカラムからなるテンプレートを定義します。それぞれのカラムに、コアとなる画像ブロックとカスタムブロックを配置します。
const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
[ 'core/column', { templateLock: 'all' }, [
[ 'core/image' ],
] ],
[ 'core/column', { templateLock: 'all' }, [
[ 'ka-example-block/ka-example-block', { placeholder: 'Enter side content...' } ],
] ],
] ] ];
テンプレートの構造は、blockTypes(ブロック名と任意の属性)の配列です。
上のコードでは、複数の属性を使用して、ColumnsブロックとColumnブロックを構成しています。特に、templateLock: 'all'
属性は、Columnブロックをロックし、不用意に既存のブロックを追加、並べ替え、削除できないようにしています。templateLock
は、以下のいずれかの値を取ります。
all
:InnerBlocks
がロックされブロックの追加、並べ替え、削除ができなくなるinsert
:ブロックの並べ替えと削除のみ可能false
:テンプレートがロックされない
テンプレートは、InnerBlocks
要素に割り当てられます。
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>
互換性の問題の回避のため、InnerBlocks
コンポーネントにtemplateLock
属性も追加します(issue #17262とpull #26128参照)。
最終的なcontainer.jsファイルは、以下の通りです。
registerBlockType('ka-example-block/ka-example-container-block', {
title: __( 'KA Container block', 'ka-example-block' ),
category: 'design',
edit( { className } ) {
return(
<div className={ className }>
<InnerBlocks
template={ TEMPLATE }
templateLock="all"
/>
</div>
)
},
save() {
const blockProps = useBlockProps.save();
return(
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
)
},
});
細かな編集
これでブロックが機能するようになりましたが、さらにちょっとした編集を加えることで、ブロックを改良することもできます。
RichText
コンポーネントで生成される段落には、backgroundColor
属性を割り当てましたが、コンテナのdiv
に背景色を割り当てた方が良いかもしれません。
その場合は、edit.jsファイルとsave.jsファイルのdiv
を以下のように変更します。
<div
{ ...blockProps }
style={ { backgroundColor: backgroundColor } }
>
...
</div>
これでブロック全体の背景を変更できます。
一方、関連性の高い変更が、useBlockProps
メソッドです。今回の例では、元のコードでは、定数blockProps
を以下のように定義しました。
const blockProps = useBlockProps();
しかし、プロパティのセットを渡すことで、useBlockProps
を効果的に使用できます。例えば、classnames
モジュールからclassnames
をインポートして、それに応じたラッパークラス名を設定できます。
以下の例では、align
属性の値に基づいてクラス名を割り当てています(edit.js)。
import classnames from 'classnames';
...
export default function Edit( { attributes, setAttributes } ) {
...
const onChangeAlign = ( newAlign ) => {
setAttributes( {
align: newAlign === undefined ? 'none' : newAlign,
} )
}
const blockProps = useBlockProps( {
className: `has-text-align-${ align }`
} );
...
}
save.jsも同様に変更します。
import classnames from 'classnames';
...
export default function save( { attributes } ) {
...
const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;
const blockProps = useBlockProps.save( {
className: `has-text-align-${ align }`
} );
...
}
これで終了です!本番用のビルドを実行しましょう。
npm run build
まとめ
ここまで、お読みいただきありがとうございました。今回の記事では、開発環境の設定から完全なブロックタイプの作成まで詳しくご紹介しました。
冒頭で述べたように、高度なGutenbergブロックを作成し、プロのGutenberg開発者になるには、Node.js、Webpack、Babel、Reactに精通していなければなりません。
しかし、Reactの経験が十分でなくても、ブロック開発を楽しむことはできます。実際に手を動かしていく中で、Gutenbergブロックに必要な幅広い技術スキルを磨くモチベーションは自ずと生まれるはずです。
この解説記事は、あくまで、はじめてのGutenbergブロック作成に役立つ情報のご紹介が目的であり、すべての関連トピックには触れていません。オンラインドキュメントや解説記事を利用して、知識を深めていってください。以下は、特におすすめのリソースです。
- 公式のブロック作成チュートリアル(初心者向け)
- 公式のブロックチュートリアル(中級者向け)
- ダイナミックブロック
- メタボックス
- プラグインのサイドバーの作成
WordPressの開発を始めたばかりであれば、フロントエンド開発の基本的なコンセプトの理解も欠かせません。以下のリソースを学習にお役立てください。
- WordPressをローカル環境にインストールする方法(無料電子書籍)
- WordPress専用マネージドホスティングの本当の価値(無料電子書籍)
- JavaScriptとは
- HTML対HTML5
- WordPressでCSSを編集する方法
- PHPとは
- WordPressフックとは
また、この記事で取り上げたサンプルコードはGistで公開されていますので、ぜひご活用ください。
Gutenbergブロックを開発したことはありますか?これまでにどのような問題に遭遇されましたか?
コメントを残す