registerBlockTypeで指定する内容について

# Block Registration
以下のページを読んでみて、実際にちょっと動かしてみたのをきっかけに、自分なりに内容をかみ砕いてみました。
翻訳未満という感じにまとめてみます。
https://developer.wordpress.org/block-editor/developers/block-api/block-registration/
(全ページ訳して書き溜めておいてから公開したかったのですが、時代に取り残される前に公開だけしておこうというわけで中途半端にも公開しておこうと思ったらすでに5月です)

手元で書きながらテストしつつ…という作業をしているので、簡略化するために、
元のコードから翻訳機能を抜いてます。
この記事を書いた時点でのWordPressのバージョンは5.3です。

#関数 registerBlockType
新しいブロックタイプ定義を登録する（wp-blocksパッケージ）
引数:ブロック名、ブロック構成オブジェクト

#registerBlockTypeの引数の内容
##ブロック名 String
ブロックを識別する一意の文字列

registerBlockType('my-plugin/book', {} );

namespace/block-nameとして構造化する必要があります
名前空間(namespace)はプラグインまたはテーマの名前。ブロック名は小文字の英数字とダッシュのみ使用できますが、文字で始まる必要があります。
ブロック名はコメント区切り文字で<!-- wp:my-plugin/book -->として使用されます。
コアブロック（Gutenbergが提供しているブロック）はシリアル化されるときに名前空間は含まれません。

##ブロック構成 Object[{key: value}]
ブロックを登録するにはいくつかのプロパティを指定する必要があります
必須はtitleとcategoryです。

##ブロックプロパティ一覧表
プロパティは量が多いので、表にしてみました。
表の後に説明が続きます。

| プロパティ名 | 型 | 必須？ | 一言で表す |
|:--|:--|:--|:--|
| title | String | 必須 | 表示タイトル |
| description | String |  | 説明 |
| category | String | 必須 | カテゴリ |
| icon | String &#124; Object |  | アイコン |
| keywords | Array |  | 検索でひっかけるためのワード |
| styles | Array |  | クラスを選択肢として追加 |
| attributes | Object |  | ブロック内のデータ |
| example | Object |  | プレビュー用データ |
| transforms | Array |  | ブロックの変換 |
| parent | Array |  | 親子ブロックの指定 |
| supports | Object |  | 拡張機能の指定 |

supports

| プロパティ名 | デフォルト値 | 一言で表す |
|:--|:--|:--|
| align | false | 位置揃え |
| alignWide | true | 全幅の許可 |
| anchor | false | アンカー設定 |
| customClassName | true | 追加CSSクラス |
| className | true | デフォルトクラス名の付与 |
| html | true | HTMLとして編集 |
| inserter | false | ブロックの追加に表示 |
| multiple | true | 記事中でブロックを何度も使える |
| reusable | true | 再利用ブロックに追加 |

##ブロック登録の最低限プロパティ
最低限これだけ指定していればブロックとして登録されます
（この場合、中身はありません）

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common'
} );
```
![gutenberg_block_example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/72c38d8b-0991-1344-8d0e-e60a2b1083e9.png)

##ブロックプロパティの内容
一覧表であげたプロパティの詳細です。

### description
ブロックの説明を設定します。
設定するとブロックの説明としてサイドバーに表示されます。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	description: 'show message',
} );
```
![description.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/46e095ca-2eb8-2c13-af1b-75b28520b107.png)

### icon
ブロックのアイコンを設定します。
[こちら](https://developer.wordpress.org/resource/dashicons/)から選ぶことが可能です。
`dashicons-` 以下を文字列で指定

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	icon: 'smiley',
} );
```
![icon_string.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/e1958caf-9bbb-26bd-d0e8-c857042788b4.png)

SVGを指定できます。（SVGについてはわからない箇所があるので、元のものをコピペして動作を見ています）

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	icon: <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="none" d="M0 0h24v24H0V0z" /><path d="M19 13H5v-2h14v2z" /></svg>,

} );
```

![icon_svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/51b5c61d-be2b-45ba-9c08-4df92763910b.png)

アイコンに背景色などを付けることも可能です。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	icon: {
		background: '#ee82ee',
		foreground: '#e0ffff',
		src: 'smiley',
	}
} );
```

![icon_color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/b6b76654-b143-8e5c-ab20-39ac1499aa0c.png)

### keywords
ブロック検索で使用できる言葉を設定できます。
この例では、messageブロックを探す際に「言葉」「text」でも反応するようにしています。
ブロックの検索から「言葉」と入力するとmessasgeブロックが候補として表示されます。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	keywords: ['言葉','text'],
} );
```

![keywords.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/138400a8-cd41-05c4-86d8-4a3917c083df.png)

### styles
ブロックにクラスを追加するオプションを作成します。
ブロック作成時にオプションとしてサイドバーに表示され、投稿時に選択できます。
記事を保存すると、ブロックにクラスが付与されます。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	styles: [
		{
			name: 'default',
			label: '角丸',
			isDefault: true
		},
		{
			name: 'shadow',
			label: '影付き'
		},
		{
			name: 'onepoint',
			label: 'ワンポイント'
		},
	],
    edit: () => <div>Hola, mundo!</div>,
    save: () => <div>Hola, mundo!</div>,

} );
```

表示する画面のCSS

```
.is-style-default
{
	height: 50px;
	background-color: #FFF;
	padding: 10px;
	border-radius: 10px;
}

.is-style-shadow
{
	padding: 0.5em;
	background: #ffebcd;
	box-shadow: 0 0 4px rgba(0, 0, 0, 0.23);	
}

.is-style-onepoint
{
  padding: 0.25em 0.5em;
  background: transparent;
  border-left: solid 5px #7db4e6;
}
```

![styles.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/1e879e20-4723-c55d-191f-87a97e7f7008.png)

このブロックはHola, mundo!という挨拶を表示するだけという簡単な作りにしています。
このブロックを記事に追加すると、サイドバーからスタイルを選択できるようになります。
スタイルを選択すると、表側で表示する際にクラス名が付与されます。
（ただ、エディタ内でもスタイルは反映できそうですね。すみません、まだやり方わかってません。わかったら追記します）


表側の表示はこのようになります。
![styles_front.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/16a146e0-4515-ba25-1dd1-b5da80bcfc70.png)

上から…
角丸（default）
影付き（shadow）
ワンポイント（onepoint）

出力されるHTMLは以下の通りです。is-style-が追加されていますね。

```
<div class="wp-block-my-gutenblock-message is-style-default">Hola, mundo!</div>
<div class="wp-block-my-gutenblock-message is-style-shadow">Hola, mundo!</div>
<div class="wp-block-my-gutenblock-message is-style-onepoint">Hola, mundo!</div>
```

補足:自力でCSSを書くのが難しかったので、お借りしました。
https://saruwakakun.com/html-css/reference/h-design

### attributes
長くなりそうなので、別の機会に…。
https://developer.wordpress.org/block-editor/designers-developers/developers/block-api/block-attributes/

### example
ブロックを追加するときのプレビュー画面の表示を設定できます。

簡単にリッチテキストでテキストを入力して、表示するだけのブロックを作成して動作を見てみました。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	attributes: {
		text: {
			type: 'string',
			source: 'html',
			selector: 'p',
		},
	},
	example: {
		attributes: {
			text: 'Bonjour, monde',
		},
	},
	edit: ( props ) => {
		const onChangeText = ( newText ) => {
			props.setAttributes( { text: newText } );
		};
		return (
			<div>
				<wp.editor.RichText
					tagName="p"
					value={ props.attributes.text }
					onChange={ onChangeText }
				/>
			</div>
		);
	},
	save: ( props ) => {
		return (
			<div>
				<p>{ props.attributes.text }</p>
			</div>
		);
	},
} );
```

exampleで指定するのは、表示時に使うattributesの値です。
このコードでは<p>タグの中身を取りだして、テキストの値として設定しているので、exampleではこの変数に文字列を指定しています。
こちらを指定するとブロック追加時のプレビューに、指定した文字が埋め込まれたブロックが表示されます。
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/7c7cef8d-679d-dfe5-682a-84bacbcfdab6.png)


example自体を指定していない場合はプレビューは表示されません。
![example_undefined.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/33c7edc9-0298-9042-48a9-13f577852280.png)

exampleの値を空にすると、表示だけおこなわれます。
表示だけのブロックとかはこちらでもよいですね。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	attributes: {
		text: {
			type: 'string',
			source: 'html',
			selector: 'p',
		},
	},
	example: {
	},
	edit: ( props ) => {
		const onChangeText = ( newText ) => {
			props.setAttributes( { text: newText } );
		};
		return (
			<div>
				<wp.editor.RichText
					tagName="p"
					value={ props.attributes.text }
					onChange={ onChangeText }
				/>
			</div>
		);
	},
	save: ( props ) => {
		return (
			<div>
				<p>{ props.attributes.text }</p>
			</div>
		);
	},
} );
```

![example_empty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/c03ea9b6-8b95-4b70-d4d9-e3602fd24f5d.png)

### transforms
ブロックを別のブロックに変換する動作の指定をします。

段落ブロックからの変換先候補に独自ブロックを追加（from）

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	attributes: {
		text: {
			type: 'string',
			source: 'html',
			selector: 'p',
		},
	},
	transforms: {
		from: [
			{
				type: 'block',
				blocks: [ 'core/paragraph' ],
				transform: ( { content } ) => {
					return wp.blocks.createBlock( 'my-gutenblock/message', {
						text: content,
					} );
				},
			},
		]
	},
	edit: ( props ) => {
		const onChangeText = ( newText ) => {
			props.setAttributes( { text: newText } );
		};
		return (
			<div>
				<wp.editor.RichText
					tagName="p"
					value={ props.attributes.text }
					onChange={ onChangeText }
				/>
			</div>
		);
	},
	save: ( props ) => {
		return (
			<div>
				<p>{ props.attributes.text }</p>
			</div>
		);
	},
} );
```
![transforms_from.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/cefee189-e907-8d26-5f45-4c3d87c1d5a6.png)

独自ブロックの変換先として段落を指定（to）
createBlockでcore/paragraphを指定し、contentにtextの内容を入れています。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	attributes: {
		text: {
			type: 'string',
			source: 'html',
			selector: 'p',
		},
	},
	transforms: {
		to: [
			{
				type: 'block',
				blocks: [ 'core/paragraph' ],
				transform: ( { text } ) => {
					return wp.blocks.createBlock( 'core/paragraph', {
						content: text,
					} );
				},
			},
		]
	},
	edit: ( props ) => {
		const onChangeText = ( newText ) => {
			props.setAttributes( { text: newText } );
		};
		return (
			<div>
				<wp.editor.RichText
					tagName="p"
					value={ props.attributes.text }
					onChange={ onChangeText }
				/>
			</div>
		);
	},
	save: ( props ) => {
		return (
			<div>
				<p>{ props.attributes.text }</p>
			</div>
		);
	},
} );
```
![transforms_to.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/c1a2ee88-bece-ff2a-da78-51cafe59f8b3.png)


#### 公式ドキュメントに載っているショートコードについて
既にクラシックエディタで投稿されたショートコードを独自ブロックへ変換…ということです。
ブロックエディタにてショートコードブロックを使って作成したショートコードはブロック経由での変換となります。（type:block）

さて、こちらも動作確認のため、クラス名とメッセージを表示するショートコードを作成します。

```
function show_message_shortcode($atts, $content) 
{
	return '<div class="'.$atts['style'].'"><p>'.$content.'</p></div>';
}
add_shortcode('message', 'show_message_shortcode');
```

そしてショートコードをクラシックエディタの状態で任意の記事に入れます。
`[message style="de"]Hallo, Welt[/message]`
![transforms_shortcode_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/61d550c5-24d2-9731-d825-e891202fc1e4.png)

エディタをGutenbergにして、さきほどの記事を確認します。
記事の内容は、クラシックエディタの内容としてGutenbergでも使用できます。
![transforms_shortcode_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/d66ec912-e238-53d3-8029-29d4ad46bc72.png)


こちらの内容を独自ブロックに移行できるようにコードを書きます。クラシックエディタ内にあるショートコードを探してきて、独自ブロックに変換という動きです。

```
wp.blocks.registerBlockType( 'my-gutenblock/message', {
	title: 'message',
	category: 'common',
	attributes: {
		text: {
			type: 'string',
			source: 'html',
			selector: 'p',
		},
		style: {
			type: 'string',
		}
	},
	transforms: {
		from: [
			{
				type: 'shortcode',
				tag: 'message',
				attributes: {
					text: {
						type: 'string',
						shortcode: ( attributes, content ) => {
							return content.shortcode.content;
						},
					},
					style: {
						type: 'string',
						shortcode: ( attributes ) => {
							return attributes.named.style;
						},
					}
				},
			},
		],
	},
	edit: ( props ) => {
		const onChangeText = ( newText ) => {
			props.setAttributes( { text: newText } );
		};
		return (
			<div className={ props.attributes.style }>
				<wp.editor.RichText
					tagName="p"
					value={ props.attributes.text }
					onChange={ onChangeText }
				/>
			</div>
		);
	},
	save: ( props ) => {
		return (
			<div className={ props.attributes.style }>
				<p>{ props.attributes.text }</p>
			</div>
		);
	},
} );
```
![transforms_shortcode_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/352cdb80-ea27-5f7f-8795-acf47a73aff7.png)
![transforms_shortcode_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/72c42c13-50c4-d3d5-6ef9-4af579802e10.png)

```
<div class="wp-block-my-gutenblock-message de"><p>Hallo, Welt</p></div>
```

#### ワイルドカード
`blocks: [ '*' ],`
のように、変換元のブロックにワイルドカードを指定することもできます。
これを指定すると、どのブロックからの変換も受け付けるということになります。
（ロジック考えるのは大変そうですね…）

### parent
ブロックに親子関係を作成。親ブロックを指定すると、独自ブロックは親ブロックの下でしか作成できなくなります。
ドキュメントにも書いてある通り「カートに追加」の下には「製品」ブロックしか追加できないようにするなど、表示に縛りを入れたいときに使えますね。

### supports
ブロック作成時にGutenbergで付与してくれるクラスなどを制御します。

#### align(デフォルトfalse)
trueもしくは使用できるサイズを指定するとブロックの配置を制御するコントロールが追加されます。
実際にコントロールで右揃えにした場合、表示にてクラスが付与されます。

```
<div class="wp-block-my-gutenblock-message alignright"><p>Ciao, mondo</p></div>
```

attributes内にalignを作成し、defaultに値を入れるとデフォルト値を設定できます。

#### alignWide(デフォルトtrue)
trueでブロックの幅にて全幅を指定、falseで全幅指定をさせないというものです。
alignでwideを指定しているときはどうなるのかと思って試してみました。

こちらの場合は、幅広と全幅が消えます。
```
supports: {
	align: true,
	alignWide: false,
},
```

こちらの場合はalignで指定したものは無効になりません。（なんだろう、この差は…）

```
supports: {
	align: ['left', 'center', 'right', 'wide', 'full'],
	alignWide: false,
},
```

#### anchor(デフォルトfalse)
アンカー設定を使用するか否かの設定です。
trueに設定すると、ブロック使用時に右にアンカー用のオプションが表示されます。
サイドバーの高度な設定の中に隠れています。
![anchor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/74a55b59-1b83-3729-9db7-33b3ba1e2940.png)


#### customClassName(デフォルトtrue)
追加CSSクラスを使用するか否かの設定です。
falseにすると高度な設定で追加CSSクラス項目が消えます。
![customClassName.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/163b3b5d-3d62-eab7-7867-b5acd7e7a3ee.png)


#### className(デフォルトtrue)
.wp-block-your-block-nameを付与するかの設定です。
trueだとブロックを表示した際にクラス（.wp-block-your-block-name）が付与されます。
falseにするとこのクラスが付与されなくなります。
したがって、他にクラスを指定しないと、クラス名のないタグが表示されることになります。

#### html(デフォルトtrue)
「HTMLとして編集」を使用するか否かの設定です。
falseにすると、ブロックの設定から「HTMLとして編集」が消えます。

#### inserter(デフォルトfalse)
ブロック追加を画面から行えるかの設定です。
falseにすると、ブロックを追加にて独自ブロックの追加が不可になります。

#### multiple(デフォルトtrue)
記事中でブロックを何度も使えるかという設定です。
falseにすると、作成したブロックは記事中で1度しか使用できません。
multipleがfalseの状態で、同じブロックを2回使おうとすると、ブロック自体が選択できないようになっています。
![multiple.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404526/207aa0df-8683-8c95-7ccc-c516b548d531.png)

#### reusable(デフォルトtrue)
「再利用ブロックに追加」を使用するか否かの設定です。
falseにすると、ブロックの設定から「再利用ブロックに追加」が消えます。

## registerBlockCollection
公式ドキュメントに載っているこちらですが、Wordpress5.3の時点では使えないようです。おそらく次のバージョンからです。
追加されたのが2020年1月7日で、Gutenberg7.3以降…となっているので…。
https://github.com/WordPress/gutenberg/pull/17609