WordPressのビジュアルエディター(TinyMCE)に複数の自作カスタムボタンを追加する方法

WordPressのビジュアルエディターにカスタムボタンを追加することで、コンテンツ作成の効率を大幅に向上させることができます。この記事では、複数のカスタムボタンを追加する方法と、リンク(a)タグの属性を保持する方法について、初心者にもわかりやすく解説します。

<div><b class="bold">WordPressのビジュアルエディター(TinyMCE)に複数の自作カスタムボタンを追加する</b></div>
<cite><a href="https://gist.github.com/sarap422/b2b2b13580b092c610a0d929d50ba288" target="_blank" rel="noopener">https://gist.github.com/sarap422/b2b2b13580b092c610a0d929d50ba288</a></cite>
</div>

## 1. 必要なファイル

カスタムボタンを追加するには、以下のファイルが必要です：

1. ボタンアイコン用のPNGファイル（サイズ：20x20ピクセル）
2. JavaScriptファイル（例：`swpbtn-shortcode.js`）
3. PHPファイル（例：`swpbtn-shortcode.php`）

## 2. JavaScriptファイルの作成

`swpbtn-shortcode.js`ファイルを作成し、以下のような構造で記述します：

```javascript
(function () {
  const enclosePlugins = [
    //ここに複数のボタン設定を追加
  ];

  const componentPlugins = [
    //ここに複数のコンポーネントボタン設定を追加
  ];

  function createEnclosePlugin(plugin, index) {
    //ボタン作成のロジック
    tinymce.PluginManager.add(`swpquote${index + 1}`, function (editor, url) {
      editor.addButton(`swpquote${index + 1}`, {
        title: plugin.title,
        cmd: `swpquote${index + 1}`,
        image: url + '/icons/' + plugin.icon,
      });

      editor.addCommand(`swpquote${index + 1}`, function () {
        var selected_text = editor.selection.getContent({ 'format': 'html' });
        if (selected_text.length === 0) {
          alert('テキストを選択してください');
          return;
        }

        var selectedNode = editor.selection.getNode();
        var isLink = selectedNode.nodeName.toLowerCase() === 'a';

        if (isLink && (plugin.tag === 'a' || plugin.class.includes('link'))) {
          //リンクの場合、既存の属性を保持しつつクラスを追加
          var existingClass = selectedNode.getAttribute('class') || '';
          var newClass = existingClass ? existingClass + ' ' + plugin.class : plugin.class;

          editor.dom.setAttribs(selectedNode, {
            class: newClass
          });

        } else {
          //その他の場合は通常の処理
          var open_column = `<${plugin.tag}${plugin.class ? ` class="${plugin.class}"` : ''}${plugin.style ? ` style="${plugin.style}"` : ''}>`;
          var close_column = `</${plugin.tag}>`;

          if (plugin.innerTag) {
            open_column += `<${plugin.innerTag}${plugin.innerClass ? ` class="${plugin.innerClass}"` : ''}>`;
            close_column = `</${plugin.innerTag}>` + close_column;
          }

          var return_text = open_column + selected_text + close_column;
          editor.execCommand('mceReplaceContent', false, return_text);
        }
      });
    });
  }

  function createComponentPlugin(plugin, index) {
    //コンポーネントボタン作成のロジック
    tinymce.PluginManager.add(`swpquote${index + 41}`,
      function (editor, url) {
        editor.addButton(`swpquote${index + 41}`,
          {
            title: plugin.title,
            cmd: `swpquote${index + 41}`,
            image: url + '/icons/' + plugin.icon,
          });

        editor.addCommand(`swpquote${index + 41}`,
          function () {
            editor.execCommand('mceReplaceContent',
              false,
              plugin.html);
          });
      });
  }

  enclosePlugins.forEach(createEnclosePlugin);
  componentPlugins.forEach(createComponentPlugin);
})();
```

### 重要ポイント：複数ボタンの追加

複数のボタンを追加するには、`enclosePlugins`と`componentPlugins`配列に各ボタンの設定を追加します。例えば：

```javascript
const enclosePlugins = [
  {
    name: 'bold',
    title: '太字',
    icon: 'format-bold.svg',
    tag: 'b',
    class: 'bold'
  },
  {
    name: 'italic',
    title: '斜体',
    icon: 'format-italic.svg',
    tag: 'i',
    class: 'italic'
  },
  //他のボタンも同様に追加
];
```

### 重要ポイント：リンク属性の保持

リンク(a)タグのhref、target、rel属性を保持するには、`createEnclosePlugin`関数内で特別な処理を行います：

```javascript
function createEnclosePlugin(plugin, index) {
  tinymce.PluginManager.add(`swpquote${index + 1}`, function (editor, url) {
    editor.addButton(`swpquote${index + 1}`, {
      title: plugin.title,
      cmd: `swpquote${index + 1}`,
      image: url + '/icons/' + plugin.icon,
    });

    editor.addCommand(`swpquote${index + 1}`, function () {
      var selected_text = editor.selection.getContent({ 'format': 'html' });
      if (selected_text.length === 0) {
        alert('テキストを選択してください');
        return;
      }

      var selectedNode = editor.selection.getNode();
      var isLink = selectedNode.nodeName.toLowerCase() === 'a';

      if (isLink && (plugin.tag === 'a' || plugin.class.includes('link'))) {
        //リンクの場合、既存の属性を保持しつつクラスを追加
        var existingClass = selectedNode.getAttribute('class') || '';
        var newClass = existingClass ? existingClass + ' ' + plugin.class : plugin.class;
        
        editor.dom.setAttribs(selectedNode, {
          class: newClass
        });
      } else {
        //通常の処理
        var open_column = `<${plugin.tag}${plugin.class ? ` class="${plugin.class}"` : ''}${plugin.style ? ` style="${plugin.style}"` : ''}>`;
        var close_column = `</${plugin.tag}>`;

        if (plugin.innerTag) {
          open_column += `<${plugin.innerTag}${plugin.innerClass ? ` class="${plugin.innerClass}"` : ''}>`;
          close_column = `</${plugin.innerTag}>` + close_column;
        }

        var return_text = open_column + selected_text + close_column;
        editor.execCommand('mceReplaceContent', false, return_text);
      }
    });
  });
}
```

この方法により、リンクの既存の属性を保持しながら新しいクラスを追加できます。

## 3. PHPファイルの作成

`swpbtn-shortcode.php`ファイルを作成し、以下のようなコードを記述します：

```php
<?php
add_action('after_setup_theme', 'swp1_theme_setup');
if (!function_exists('swp1_theme_setup')) {
  function swp1_theme_setup() {
    add_action('init', 'swp1_buttons');
  }
}

if (!function_exists('swp1_buttons')) {
  function swp1_buttons() {
    if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
      return;
    }
    if (get_user_option('rich_editing') !== 'true') {
      return;
    }
    add_filter('mce_external_plugins', 'swp1_add_buttons');
    add_filter('mce_buttons_2', 'swp1_register_buttons'); //2段目に表示
  }
}

if (!function_exists('swp1_add_buttons')) {
  function swp1_add_buttons($plugin_array) {
    $plugin_array['swp_custom_buttons'] = get_theme_file_uri() . '/path/to/swpbtn-shortcode.js';
    return $plugin_array;
  }
}

if (!function_exists('swp1_register_buttons')) {
  function swp1_register_buttons($buttons) {
    $custom_buttons = array('swp_custom_buttons');
    return array_merge($buttons, $custom_buttons);
  }
}
```

## 4. functions.phpの編集

テーマのfunctions.phpに以下のコードを追加します：

```php
include "path/to/swpbtn-shortcode.php";
```

## 5. ファイルのアップロード

1. `swpbtn-shortcode.php`と編集した`functions.php`をテーマディレクトリにアップロード
2. `swpbtn-shortcode.js`とアイコン用のPNGファイルを適切なディレクトリ（例：`/assets/js/`）にアップロード

## まとめ

この方法を使用することで、WordPressのビジュアルエディターに複数のカスタムボタンを追加し、リンクタグの属性を保持することができます。初心者の方でも、step by stepで進めていけば、簡単にカスタムボタンを実装できるはずです。

カスタムボタンを追加することで、コンテンツ作成の効率が大幅に向上し、一貫性のあるスタイルを簡単に適用できるようになります。ぜひ、自分のニーズに合わせてカスタマイズしてみてください。