affingerで、ビジュアルエディタにタグを追加する

affingerでは基本機能としてビジュアルエディタにタグが設置されている。ボタンを押せば(あるいはセレクトボックスから選択すれば)、指定のタグが編集画面に入力されるという優れもの。
現在、ボタンとして表示されているのは「ADs」「SC」「ボタンA」「ボタンB」「会話A」「会話B」「会話C」「ブログカード」「Youtube」「タグID」「タグSlug」。
ここに新しく独自のタグを追加したい。
まず子テーマのjsディレクトリにtinymce-st-plugin.jsをコピーする。内容は整形すると以下になる。

(function(x,w,E,q){
	var u;
	function D(a){
		var b=a.selection.getRng();
		return Math.abs(b.endOffset-b.startOffset)>0
	}
	function C(a,i,f){
		var d=D(a);
		var j;
		var g;
		var b;
		var h;
		var c;
		var e;
		j=d?a.selection.getContent({format:"text"}):"";
		g=i+j+f;
		a.execCommand("mceInsertContent",false,g);
		if(d){
			return
		}
		b=a.selection.getRng();
		h=f.length-(f.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g)||[]).length;
		c=b.endOffset-h;
		e=b.startContainer;
		b.setStart(e,c);
		b.setEnd(e,c);
		a.selection.setRng(b)
	}
	function y(c,f,e){
		var a="";
		var d;
		if(D(c)){
			var b=c.selection.getNode();
			a=c.selection.getContent();
			a=(a===b.innerHTML)?b.outerHTML:a
		}
		d=f+a+e;
		c.execCommand("mceInsertContent",false,d)
	}
	function r(b,a){
		b.execCommand("mceInsertContent",false,a)
	}
	function z(b,a){
		b.selection.setContent(a)
	}
	function s(a){
		return{
			st_button_smanone:{
				text:"スマホに表示しないボックス",
				icon:false,
				tooltip:"スマホに表示しないボックス",
				callback:y.bind(null,a,"[pc]","[/pc]")
			},
			st_button_pcnone:{
				text:"PCに表示しないボックス",
				icon:false,
				tooltip:"PCに表示しないボックス",
				callback:y.bind(null,a,"[nopc]","[/nopc]")
			},
			st_button_clipmemo:{
				text:"クリップメモ",
				icon:false,tooltip:"クリップメモ",
				callback:C.bind(null,a,
					'[st-cmemo fontawesome="fa-file-text-o" iconcolor="#919191" bgcolor="#fafafa" color="#000000" iconsize="100"]',
					"[/st-cmemo]")
			},
			st_button_kintou:{
				text:"均等横並び",
				icon:false,
				tooltip:"均等横並び",
				callback:r.bind(null,a,
					'<div class="kintou"><ul><li>横並びコンテンツ</li><li>横並びコンテンツ</li><li>横並びコンテンツ</li></ul></div><br/>')
			},
			st_button_responbox33:{
				text:"PCとTab3分割",
				icon:false,
				tooltip:"PCとTab3分割",
				callback:r.bind(null,a,
					'<div class="clearfix responbox33"><div class="lbox"><p>左側のコンテンツ33%</p></div><div class="lbox"><p>真ん中のコンテンツ33%</p></div><div class="lbox"><p>右側のコンテンツ33%</p></div></div><br/>')
			},
			st_button_responbox:{
				text:"PCとTab左右40:60%",
				icon:false,
				tooltip:"PCとTab左右40:60%",
				callback:r.bind(null,a,
					'<div class="clearfix responbox"><div class="lbox"><p>左側のコンテンツ40%</p></div><div class="rbox"><p>右側のコンテンツ60%</p></div></div><br/>')
			},
			st_button_responbox50:{
				text:"PCとTab左右50%",
				icon:false,
				tooltip:"PCとTab左右50%",
				callback:r.bind(null,a,
					'<div class="clearfix responbox50"><div class="lbox"><p>左側のコンテンツ50%</p></div><div class="rbox"><p>右側のコンテンツ50%</p></div></div><br/>')
			},
			st_button_responbox30s:{
				text:"全サイズ左右30:70%",
				icon:false,
				tooltip:"全サイズ左右30:70%",
				callback:r.bind(null,a,
					'<div class="clearfix responbox30 smart30"><div class="lbox"><p>左側のコンテンツ50%</p></div><div class="rbox"><p>右側のコンテンツ50%</p></div></div><br/>')
			},
			st_button_responbox50s:{
				text:"全サイズ左右50%",
				icon:false,
				tooltip:"全サイズ左右50%",
				callback:r.bind(null,a,
					'<div class="clearfix responbox50 smart50"><div class="lbox"><p>左側のコンテンツ50%</p></div><div class="rbox"><p>右側のコンテンツ50%</p></div></div><br/>')
			},
			st_button_responboxfree:{
				text:"全サイズ左右free%",
				icon:false,
				tooltip:"全サイズ左右free%",
				callback:r.bind(null,a,
					'<div class="clearfix responboxfree smartfree"><div class="lbox" style="width:50%"><p>左側のコンテンツ%</p></div><div class="rbox" style="width:50%"><p>右側のコンテンツ%</p></div></div><br/>')
			},
			st_button_blackboard:{
				text:"こんな方におすすめ",
				icon:false,
				tooltip:"こんな方におすすめ",
				callback:r.bind(null,a,
					'<div class="st-blackboard"><p class="st-blackboard-title-box"><span class="st-blackboard-title">こんな方におすすめ</span></p><ul class="st-blackboard-list"><li>これはダミーのテキストです</li><li>これはダミーのテキストです</li></ul></div><br/>')
			},
			st_button_freebox:{
				text:"見出し付きフリーボックス",
				icon:false,
				tooltip:"見出し付きフリーボックス",
				callback:C.bind(null,a,
					'[st-midasibox title="見出し(全角15文字)" fontawesome="" bordercolor="" color="" bgcolor="" borderwidth="" borderradius="" titleweight="bold"]<p>',
					"</p>[/st-midasibox]")
			},
			st_button_mybox:{
				text:"マイボックス",
				icon:false,
				tooltip:"マイボックス",
				callback:C.bind(null,a,
					'[st-mybox title="ポイント" fontawesome="fa-check-circle" color="#424242" bordercolor="#424242" bgcolor="#ffffff" borderwidth="2" borderradius="5" titleweight="bold"]<p>',
					"</p>[/st-mybox]")
			},
			st_button_memobox:{
				text:"メモボックス",
				icon:false,
				tooltip:"メモボックス",
				callback:r.bind(null,a,
					'<div class="st-memobox"><p class="st-memobox-title">メモ</p><p>ここに本文を記述</p></div><br/>')
			},
			st_button_memobox2:{
				text:"メモボックス2",
				icon:false,
				tooltip:"メモボックス2",
				callback:r.bind(null,a,
					'<div class="st-memobox2"><p class="st-memobox-title">メモ</p><p>ここに本文を記述</p></div><br/>')
			},
			st_button_slidebox:{
				text:"スライドボックス",
				icon:false,
				tooltip:"スライドボックス",
				callback:r.bind(null,a,
					'<div class="st-slidebox-c"><p class="st-btn-open">+ クリックして下さい</p><div class="st-slidebox"><p>クリックで開かれる内容です</p></div></div><br/>')
			},
			st_button_toc:{
				text:"目次(TOC+)",
				icon:false,
				tooltip:"目次(TOC+)",
				callback:r.bind(null,a,"[toc]")
			},
			st_button_st_toc:{
				text:"目次(カスタム)",
				icon:false,
				tooltip:"目次(カスタム)",
				callback:r.bind(null,a,
					'<div id="st_toc_container"><p class="st_toc_title">目次</p><ol class="st_toc_list st-original-toc"><li><a href="#">これはダミーです</a></li><li><a href="#">これはダミーです</a></li><li><a href="#">これはダミーです</a></li></ol></div><br/>')
			},
			st_button_star:{
				text:"スター",
				icon:false,
				tooltip:"スター",
				callback:r.bind(null,a,"[star5]")
			}
		}
	}
	function A(a){
		return{
			st_button_adsense:{
				text:"ADs",
				icon:false,
				tooltip:"ADs",
				callback:r.bind(null,a,"[adsense]")
			},
			st_button_originalsc:{
				text:"SC",
				icon:false,
				tooltip:"SC",
				callback:r.bind(null,a,"[originalsc]")
			},
			st_btnlink_main:{
				text:"ボタンA",
				icon:false,
				tooltip:"ボタンA",
				callback:r.bind(null,a,
					'<div class="rankstlink-r2"><p><a href="#">ボタンA</a></p></div><br/>')
			},
			st_btnlink_sub:{
				text:"ボタンB",
				icon:false,
				tooltip:"ボタンB",
				callback:r.bind(null,a,
					'<div class="rankstlink-l2"><p><a href="#">ボタンB</a></p></div><br/>')
			},
			st_button_blogcard:{
				text:"ブログカード",
				icon:false,
				tooltip:"ブログカード",
				callback:C.bind(null,a,"[st-card id="," label='' name='']")
			},
			st_button_kaiwa1:{
				text:"会話A",
				icon:false,
				tooltip:"会話A",
				callback:C.bind(null,a,"[st-kaiwa1]","[/st-kaiwa1]")
			},
			st_button_kaiwa2:{
				text:"会話B",
				icon:false,
				tooltip:"会話B",
				callback:C.bind(null,a,"[st-kaiwa2]","[/st-kaiwa2]")
			},
			st_button_kaiwa3:{
				text:"会話C",
				icon:false,
				tooltip:"会話C",
				callback:C.bind(null,a,"[st-kaiwa3]","[/st-kaiwa3]")
			},
			st_button_youtubeid:{
				text:"YouTube",
				icon:false,
				tooltip:"YouTube",
				callback:C.bind(null,a,"[youtube id=","]")
			},
			st_button_st_af_cpt:{
				text:"タグID",
				icon:false,
				tooltip:"タグID",
				callback:C.bind(null,a,'[st_af id="','"]')
			},
			st_button_st_af_slug:{
				text:"タグSlug",
				icon:false,
				tooltip:"タグSlug",
				callback:C.bind(null,a,'[st_af name="','"]')
			}
		}
	}
	function F(b,c){
		for(var a in c){
			if(!Object.prototype.hasOwnProperty.call(c,a)){
				continue
			}
			b.addButton(a,{
				type:"button",
				text:c[a].text,
				icon:c[a].icon,
				onclick:c[a].callback
			})
		}
	}
	function B(b){
		var a=[];
		for(var c in b){
			if(!Object.prototype.hasOwnProperty.call(b,c)){
				continue
			}
			a.push({
				text:b[c].text,
				icon:b[c].icon,
				tooltip:b[c].tooltip,value:c
			})
		}
		return a
	}
	function v(a,b){
		a.addButton("st_listbox_1",{
			type:"listbox",
			text:"タグ",
			icon:false,
			values:B(b),
			onPostRender:function(){
				this.value(this.settings.values[0].value)
			},
			onselect:function(c){
				tinyMCE.execCommand(this.value(),false);
				this.value(null)
			}
		})
	}
	function t(b,c){
		for(var a in c){
			if(!Object.prototype.hasOwnProperty.call(c,a)){
				continue
			}
			b.addCommand(a,c[a].callback)
		}
	}
	u={
		init:function(a,b){
			var c=s(a);
			var d=A(a);
			t(a,c);
			t(a,d);
			v(a,c);
			F(a,d)
		}
	};
	E.create("tinymce.plugins.st",u);
	E.PluginManager.add("st_plugin",E.plugins.st)
}(window,window.document,tinymce));

セレクトボックスを編集するならfunction sを、ボタンを編集するならsunfcion Aに追記することになる。
今回はボタンタグを追加したので、function Aのreturnの最後に

			st_button_add_mybox1:{
				text:"ボックス1",
				icon:false,
				tooltip:"ボックス1",
				callback:r.bind(null,a,
					'<div class="box_1"><p>&nbsp;</p></div><br/>')
			}

追加。
このままだと特に呼び出しもされないので、functions.php

if ( !function_exists( 'st_register_tiny_mce_plugins' ) ) {
	function st_register_tiny_mce_plugins( $plugins ) {
		$plugins['st_plugin'] = get_stylesheet_directory_uri() . '/js/tinymce-st-plugin.js';
		return $plugins;
	}
}
add_filter( 'mce_external_plugins', 'st_register_tiny_mce_plugins' );

追記して、JSファイルの呼び出しをオーバーライドさせる。
ただ、このままだとスクリプトの内容を表示させることができないので、さらに

if ( !function_exists( 'st_tiny_mce_visual_buttons' ) ) {
	function st_tiny_mce_visual_buttons( $buttons ) {
		$custom_buttons = array(
			'st_listbox_1'         => PHP_INT_MAX,
			'st_button_adsense'    => PHP_INT_MAX,
			'st_button_originalsc' => PHP_INT_MAX,
			'st_btnlink_main' => PHP_INT_MAX,
			'st_btnlink_sub' => PHP_INT_MAX,
			'st_button_kaiwa1' => PHP_INT_MAX,
			'st_button_kaiwa2' => PHP_INT_MAX,
			'st_button_kaiwa3' => PHP_INT_MAX,
			'st_button_blogcard'    => PHP_INT_MAX,
			'st_button_youtubeid'  => PHP_INT_MAX,
			'st_button_st_af_cpt'  => PHP_INT_MAX,
			'st_button_st_af_slug'  => PHP_INT_MAX,
			'st_button_add_mybox1'  => PHP_INT_MAX,
		);

		foreach ( $custom_buttons as $custom_button => $position ) {
			$buttons = _st_insert_tiny_mce_button( $custom_button, $buttons, $position );
		}

		return $buttons;
	}
}

を追記して、ボタンを実際に表示させる。
多分これでOKだと思う。