Gutenberg の Format type に複数クラスを指定
インラインで文字を修飾するために registerFormatTypeを使用してツールバーにボタンを追加できます。
ただ registerFormatType で指定できるクラス名はスペース等で複数指定できません。
実際のソースを見るとわかりますが、英数字とハイフン、アンダーバー以外が入っているとはじかれてしまうためです。
ただ実際はGutenbergの内部でクラス名をスペースで区切って処理したりはしていないため、スペースが入っていても問題なく動く場合があります。
ここでは WordPress v5.1 で問題なく複数のクラスの付け外しを行うことのできるボタンをRichTextのツールバーに追加する非公式な方法を紹介します。
フォーマットの追加
registerFormatType のほとんどは引数のチェックや既に登録されているフォーマットかどうかのチェックであり、実際の登録自体は addFormatTypes の一行だけです。
したがって直接これを呼び出せば現状のクラス名チェックを飛ばして登録することが可能です。
同じクラスの判定による制限
同じクラス名かどうかの判定は getFormatTypeForClassName で行われます。
登録しようとしているクラス名の一部または全部から構成されるクラス名を持つフォーマットが登録されている場合に、この検索で引っかかります。
したがって以下のような二つのフォーマットを登録する場合は 2. のほうを先に登録する必要があります。
- className: class1
- className: class1 class2
Gutenbergの内部の処理でも getFormatTypeForClassName が使用されているため、この制限を無視して登録した場合はボタンのアクティブ判定などに影響が出てしまいます。
その他のチェック
その他の部分は元のチェックをそのまま利用します。
最終的なコード例
const {dispatch, select} = wp.data;
function _registerFormatType( name, settings ) {
settings.name = name;
if ( typeof settings.name !== 'string' ) {
window.console.error(
'Format names must be strings.'
);
return;
}
if ( ! /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test( settings.name ) ) {
window.console.error(
'Format names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-format'
);
return;
}
if ( select( 'core/rich-text' ).getFormatType( settings.name ) ) {
window.console.error(
'Format "' + settings.name + '" is already registered.'
);
return;
}
if (
typeof settings.tagName !== 'string' ||
settings.tagName === ''
) {
window.console.error(
'Format tag names must be a string.'
);
return;
}
if (
( typeof settings.className !== 'string' || settings.className === '' ) &&
settings.className !== null
) {
window.console.error(
'Format class names must be a string, or null to handle bare elements.'
);
return;
}
if ( ! /^([_a-zA-Z]+[a-zA-Z0-9-]*)(\s+[_a-zA-Z]+[a-zA-Z0-9-]*)*$/.test( settings.className ) ) {
window.console.error(
'A class name must begin with a letter, followed by any number of hyphens, letters, or numbers.'
);
return;
}
if ( settings.className === null ) {
const formatTypeForBareElement = select( 'core/rich-text' )
.getFormatTypeForBareElement( settings.tagName );
if ( formatTypeForBareElement ) {
window.console.error(
`Format "${ formatTypeForBareElement.name }" is already registered to handle bare tag name "${ settings.tagName }".`
);
return;
}
} else {
const formatTypeForClassName = select( 'core/rich-text' )
.getFormatTypeForClassName( settings.className );
if ( formatTypeForClassName ) {
window.console.error(
`Format "${ formatTypeForClassName.name }" is already registered to handle class name "${ settings.className }".`
);
return;
}
}
if ( ! ( 'title' in settings ) || settings.title === '' ) {
window.console.error(
'The format "' + settings.name + '" must have a title.'
);
return;
}
if ( 'keywords' in settings && settings.keywords.length > 3 ) {
window.console.error(
'The format "' + settings.name + '" can have a maximum of 3 keywords.'
);
return;
}
if ( typeof settings.title !== 'string' ) {
window.console.error(
'Format titles must be strings.'
);
return;
}
dispatch( 'core/rich-text' ).addFormatTypes( settings );
return settings;
}
主な違いはクラス名の判定箇所です。
if ( ! /^[_a-zA-Z]+[a-zA-Z0-9-]*$/.test( settings.className ) ) {
↓
if ( ! /^([_a-zA-Z]+[a-zA-Z0-9-]*)(\s+[_a-zA-Z]+[a-zA-Z0-9-]*)*$/.test( settings.className ) ) {
スペース区切りで複数の指定を許可しています。
動作確認
まとめ
複数クラスを付けられると使用しているテーマに組み込まれたデザインの利用がさらにしやすくなって便利になりそうです。
ただし RichText 周りは仕様変更が頻繁に入るため今後問題が起こる可能性があります。
修正を追えない場合はやらないほうがです。