WordPressでins要素を使うためのショートコード

ins要素は後から追加された内容を表すHTML要素です。ブログで後日追記した時などに使えます。

<p>吾輩は猫である。<ins>犬ではない。</ins></p>

HTML5ではins要素はトランスペアレントというコンテンツモデルで、内包できる要素が親要素のものと同じになります。そのため上記のようにp内で使用した場合はinsの中にpdivを含めることはできなくなりますが、divの直下などでは含めることができます。

これはHTML4.01などでも同様で、インライン要素とブロックレベル要素両方を含むことができる要素として定義されていました。

さて、そんな複雑な挙動をするからでしょうか、WordPressでinspを含んで記事を書くと、

<!-- こう書いたはずが -->
<ins><p>追記文</p></ins>

<!-- こうなる -->
<p><ins>
<p>追記文</p>
<p></ins></p>

なんか残念な感じになります。WordPressの自動整形のせいです。insをインライン要素と捉えているんでしょう。

wpautopのフィルタを停止させれば問題ないのですが、そうなると改行など全て自分で書く必要があるし、複数人でブログを書いている場合に問題になるかもしれません。

そこで、ショートコードを使って、insタグを埋め込めるようにしてみようと思いました。

function shortcode_insert($atts, $content = null) {
	return '<ins>'.$content.'</ins>';
}
add_shortcode('ins', 'shortcode_insert');

囲み型ショートコードの基本形です。

これで[ins]<p>〜</p>[/ins]の様に書けばちゃんとしたコードを吐き出してくれるはずです。

実際やってみると、

<ins>
<p>追記文</p>
<p></ins>

思ってたんと違う。

前後に改行が入るのはいい。ちゃんとinsの中にpも入ってる。

でも</ins>の前にある<p>はなんなんですか。

これもWordPressの自動整形の影響です。「あ、pの閉じタグの後に改行がある! 新しくpを追加しなきゃ!」ってことでしょうか。余計なお世話です。

さらにショートコード[ins]の直後に改行があった場合、最初に</p>が追加されてしまいます。

ショートコードはフィルタ適用後に展開されるので、ショートコードの関数が内容を受け取った時点で、これらの余分なタグは含まれています。

なので、ショートコードの側でこれらを削除してやればうまくいくはずです。

function shortcode_insert($atts, $content = null) {
	return '<ins>'.preg_replace(array('/^<\/p>/', '/<p>$/'), '', $content).'</ins>';
}
add_shortcode('ins', 'shortcode_insert');

preg_replaceで最初の</p>と最後の<p>を置換して削除しています。

<!-- 表示結果 -->
<ins>
<p>追記文</p>
</ins>

これでやっとちゃんとしたマークアップになりました。なお、このショートコードを使う時は、pを明記してあげる必要があります。

最後にショートコードの引数で、属性を設定できるようにしておきます。

function shortcode_insert($atts, $content = null) {
	$atts = shortcode_atts(array(
		'class' => '',
		'datetime' => '',
		'cite' => '',
	), $atts);
	
	$attr = '';
	
	foreach($atts as $key => $value) {
		if($value) $attr .= ' '.$key.'="'.esc_attr($value).'"';
	}
	
	return '<ins'.$attr.'>'.preg_replace(array('/^<\/p>/', '/<p>$/'), '', $content).'</ins>';
}
add_shortcode('ins', 'shortcode_insert');

classと、追加日時を示すdatetime、追記に関連したドキュメントのURLを示すciteを入力できるようにしました。

全く同じ要領で、削除した内容を表すdel要素のショートコードも作れます。del要素もinsと同じコンテンツモデルがトランスペアレントの要素です。他にもa要素なんかも該当しますが、記事中でapを含めたりすることはあまりないと思うので、無理に作る必要もなさそうです。必要であれば作ればいいし。

ショートコードは便利ですが、不意に使用できなくなった時にちゃんと表示されなくなったり、間違って上書きしてしまう危険性もあるので、あまり多用しすぎるのはよくないと思います。

とはいえこういうWordPressとの干渉を回避したり、イレギュラーな処理をする場合にはとても重宝するので、うまく使いこなしたいですね。

WordPressの自動整形ももうちょっと進化してくれると嬉しいのですが。

Comments