Gutenberg(ブロックエディタ)メモ: 登録されているショートコードの一覧を表示したブロックを作る

WordPressのGutenberg
WordPressのGutenberg

WordPressのGutenbergハンドブックに記述がみつからず、GitHubに載っている記述を使いつつ、わずかばかりの実用性向上を意図したブロックを作った内容です。

なお、Gutenbergでのショートコードの使い方をお探しの方は以下のリンクから該当記事をご覧ください。

構築環境
WordPress4.9.8
JavaScriptJSX/ESNext
Gutenberg3.9.0

注意点

  • Gutenbergがコアに入る前の段階の記事です
  • 書き方だけではなく、語句や名称にも問題がある可能性があります
  • バッドノウハウな可能性があるため、読む方は参考程度に考えてください

実現したいこと

  • Gutenbergでショートコードブロックを追加する
  • サイドバーにショートコードの一覧を表示させる

ショートコードブロックに関してはハンドブックでは見当たりませんでしたが、GitHubの以下のページが該当するようでした。

基本的にはこのまま使うことでショートコードブロックが追加できることを確認したため、これを用いて登録したショートコードの一覧表示を追加することを目指しました。

参考記事は以下の通りです。

今回の問題点

根本的な問題として、GitHubに記載されているショートコードブロックのコードをそのまま使ってよいものかの判断がつきませんでした。

当初はRichTextのように簡単に使えるコンポーネントにされていると考えていて、それさえかけばGitHubに載っている記述そのままを記載する必要はないのではと思ったためです。

しかしながら調べてもショートコードブロックを出せるコンポーネントがわからず、当記事のような形となっています。

そのため、未発見、あるいは今後追加されるかもしれませんので参考程度にご覧下さい。

なお、最終的には「必要な情報が不足している」という状態になりますが、長くなるのでこの点は記事末尾の問題点のところに記載します。

サンプル

ショートコードの一覧を表示させる
ショートコードの一覧を表示させる

今回はJSの他に、Gutenbergのカスタムをプラグインの形で作成する前提のためプラグイン内のPHPファイルへの記述が必要になります。

まずはPHP。


//初期設定
add_action( 'enqueue_block_editor_assets', function() {

  $keys = my_shortcode_list();

  //Gutenbergのブロックを作るための基本的記述
  wp_enqueue_script(
    'myplugin-gutenberge',
    plugins_url( 'block.js', __FILE__ ),
    [ 'wp-autop', 'wp-blocks', 'wp-element', 'wp-i18n', 'wp-components', 'wp-editor', 'wp-compose' ]
  );

  //wp_localize_scriptでGutenberg用のblock.jsにPHP側で処理した配列を渡す
  //使っている名称はそれぞれに合わせたり任意で記述
  wp_localize_script( 'myplugin-gutenberge', 'myShortcodeList', $keys );

} );

//ショートコードの一覧を取得して、登録名を配列に入れる
function my_shortcode_list(){
    global $shortcode_tags;
    $list = $shortcode_tags;
    $keys = array_keys($list);
    return $keys;
}

次いでブロック用のJS。


const { registerBlockType } = wp.blocks;
const { removep, autop } = wp.autop
const { RawHTML, Fragment } = wp.element
const { __ } = wp.i18n
const { Dashicon, PanelBody } = wp.components
const { PlainText, ServerSideRender, InspectorControls } = wp.editor
const { withInstanceId } = wp.compose

//アルファベット昇順でソートする
//「【Javascript】アルファベットの昇順・降順ソート」の記事参照のこと
const sortFunc = (a, b) => {
  a = a.toString().toLowerCase();
  b = b.toString().toLowerCase();
  if(a < b) return -1;
  else if(a > b) return 1;
  return 0;
}

registerBlockType( 'my-plugin/test-shortcode', {
  title: 'test-shortcode',
  icon: 'universal-access-alt',
  category: 'layout',

  attributes: {
    text: {
      type: 'string',
      source: 'text',
    },
  },

  transforms: {
    from: [
      {
        type: 'shortcode',
        tag: '[a-z][a-z0-9_-]*',
        attributes: {
          text: {
            type: 'string',
            shortcode: ( attrs, { content } ) => {
              return removep( autop( content ) );
            },
          },
        },
        priority: 20,
      },
    ],
  },

  supports: {
    customClassName: false,
    className: false,
    html: false,
  },

  edit: withInstanceId(
    ( { attributes, setAttributes, instanceId } ) => {
      //inputIdを変えないとcoreのショートコードブロックと重複してしまうので、自分で追加する際は変更必須
      //複数のブロックを追加数することを考えて、instanceIdで連番にして管理している模様
      const inputId = `blocks-shortcode-input-${ instanceId }-myshortcode`;

      //ショートコードの一覧表示用
      let len  = myShortcodeList.length;
      let i    = 0;
      let list = [];
      //ソートしないなら不要
      myShortcodeList.sort(sortFunc);
      while(i < len){
        //PHPから持って来た値をliタグで括った形でまた配列に入れ直す
        list.push(<li>[{myShortcodeList[i++]}]</li>);
      }

      return (
        <Fragment>
          <InspectorControls>
            <PanelBody title="ショートコード一覧">
              <ul>
                {list}
              </ul>
            </PanelBody>
          </InspectorControls>
          <div className="wp-block-shortcode">
            <label htmlFor={ inputId }>
              <Dashicon icon="shortcode" />
              { __( 'Shortcode' ) }
            </label>
            <PlainText
              className="input-control"
              id={ inputId }
              value={ attributes.text }
              placeholder={ __( 'Write shortcode here…' ) }
              onChange={ ( text ) => setAttributes( { text } ) }
            />
          </div>
        </Fragment>
      );
    }
  ),

  save( { attributes } ) {

    return (
      <Fragment>
        <RawHTML>{ attributes.text }</RawHTML>
      </Fragment>
      );

  },
} );

PHPからJSに値を渡す方法としてGutenberg専用の何かがあるのではと探したのですが、見つからず従来のwp_localize_script()を使っています。

今回の問題点

前述の「必要な情報が不足している」という点に関しての詳細です。

ショートコードと言っても、自己完結型ショートコード(終了タグなしで動作するショートコード)ばかりではなく、囲み型や値を渡して操作するタイプもあります。

今回のコードでは残念ながらショートコードの登録名と紐づいている関数名だけしか取得できないため、「囲み型か」「値が必要なのか」などの情報はありません。

また、最初から登録されているショートコードと、後からプラグインなどで追加されたショートコードを区別する手段もありません。
登録順序という方法も使えなくはないですが、今後も使えるのかは不明なため使用し難いと考えています。

こういった点から実用的とはいい難く、あくまで「何も表示されないよりはちょっと便利になる」という程度のものとなりました。

一応、以下方法で実現可能ではあるとは考えています。

  • プラグインの設定画面を作って欄を設置し、ショートコードを表示したい形で手動入力し、その入力値を出力する

ただ、ここまでするならもうショートコード作成プラグインとして作成し連動させたほうがよく、この方向性なら高い確率で有名プラグインが対応するだろうと考えまして、作成は中止しました。

関連記事

Gutenberg(ブロックエディタ)に関連する記事一覧。

1人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄