Wonderful! WordPress

[caption]ショートコードとpタグの問題

この記事は公開または最後に更新されてから2365日が経過しています。情報が古くなっている可能性があるのでご注意下さい。

Operaを使っている時にソースコードを見ようとしたら、ふとした手違いでW3CValidationを通してしまいました。
出てきた結果はエラーのオンパレード。
w3cvalidation

以前は、作ったHPは必ずW3C Validationを通して完璧にしていたものです。
が、phpで動的に生成されるwordpressのブログは通しても検査できないものと勝手に思い込んでいました。

エラーのオンパレードを見てしまったので、これは直すしかありません。
しかし、こんなにたくさんエラーがあるとは思いもしなかった。
とりあえず、ひとつひとつ問題をつぶしていくしかないです。
だいたいこういうのは、ほんのケアレスミスのようなものばかりで、すぐに対応できるものがほとんどです。
が、その時のエラーがあって気づいたちょっと難儀な問題が。

画像を投稿に挿入するときにcaptionに入力するとwordpressでは[caption]ショートコードを使用して投稿に入力されます。
実際にhtmlがマークアップされるときには、[caption]ショートコードはdivタグの中にimgタグと、そしてcaptionで与えられた文字列はpタグに入れて生成されます。
これだけなら何も問題はないのですが、the_content関数で記事全てがマークアップされると、ご存知の通りpタグとbrタグで整形されて生成されます。
この時、[caption]ショートコードで生成されたdivタグとpタグもthe_content関数で生成されたpタグの中に入ってしまいます。
これが、実際のデータです。

<p>
	<div id="attachment_25035" class="wp-caption aligncenter" style="width: 510px">
		<a href="JavaScript:showpop('Whimbrel*2012/10/1209297752.jpg')">
			<img src="https://strix.main.jp/wp-content/uploads/2012/10/1209297752-500x375.jpg" alt="チュウシャクシギ" title="1209297752" width="500" height="375" class="size-medium wp-image-25035" />
		</a>
		<p class="wp-caption-text">左足を怪我しています。</p>
	</div><br />
	<a href="JavaScript:showpop('Whimbrel*2012/10/1209297758.jpg')">
		<img src="https://strix.main.jp/wp-content/uploads/2012/10/1209297758-500x375.jpg" alt="チュウシャクシギ" title="1209297758" width="500" height="375" class="aligncenter size-medium wp-image-25031" />
	</a><br />
	<div id="attachment_25032" class="wp-caption aligncenter" style="width: 510px">
		<a href="JavaScript:showpop('Whimbrel*2012/10/1209297897.jpg')">
			<img src="https://strix.main.jp/wp-content/uploads/2012/10/1209297897-500x375.jpg" alt="チュウシャクシギ" title="1209297897" width="500" height="375" class="size-medium wp-image-25032" />
		</a>
		<p class="wp-caption-text">ピンボケですが。</p>
	</div>
</p>
HTML
CopyExpand

このサイトの場合は、画像をクリックした時に拡大表示させるのにjavascriptを動かしているので画像に対するアンカータグにはそのためのコマンドが指定してあります。詳しくはこちらを»画像クリック時のjavascript

pタグはブロックレベルのタグですが、含むことができるのはインライン要素やテキストのみで、divタグやネストとなるpタグは含めることができません。
ということで上記のhtmlデータは下のようなエラーとなります。
w3cvalidation
ここにあるのは許されませんということです。
しかし、ネットを見てもこんなことは全く問題にはなっていないようで。となると自分だけのこと?ローカルのwordpressにおいても、プラグインなど全く使用していない環境でも同じことになっているのだがなぜか。使い方に問題があったりするのでしょうか。わからない。
・・・

2015年3月16日追記:

« Filter hook : img caption shortcode »

随分と時間が経ってから知った事なのですが、divタグとpタグを変更するだけであれば フィルターフック img_caption_shortcode を使えば簡単にできます。
codexはここ⇒Plugin API/Filter Reference/img caption shortcode
codex にある Example の20行目から25行目のdiv と p を書き換えたのが以下のとおり。

<?php
add_filter( 'img_caption_shortcode', 'my_img_caption_shortcode', 10, 3 );

function my_img_caption_shortcode( $empty, $attr, $content ){
	$attr = shortcode_atts( array(
		'id'      => '',
		'align'   => 'alignnone',
		'width'   => '',
		'caption' => ''
	), $attr );

	if ( 1 > (int) $attr['width'] || empty( $attr['caption'] ) ) {
		return '';
	}

	if ( $attr['id'] ) {
		$attr['id'] = 'id="' . esc_attr( $attr['id'] ) . '" ';
	}

	return '<span ' . $attr['id']
	. 'class="wp-caption ' . esc_attr( $attr['align'] ) . '" '
	. 'style="max-width: ' . ( 10 + (int) $attr['width'] ) . 'px;">'
	. do_shortcode( $content )
	. '<span class="wp-caption-text">' . $attr['caption'] . '</span>'
	. '</span>';

}
?>
PHP
CopyExpand

実際に投稿がwordpressのシステムによってcaption ショートコードの処理をされてhtmlとして吐き出される時に、その処理によって吐き出されるhtml を指定してしまうということです。ちゃんとこういう機能が用意されている。であれば、これを使わない手は無いということで。二度手間ではなくなるので合理的でスマートです。またしても無知損、すごいなwordpressは。

で、キャプションの文字数が少ない時はalign-center、字数が多くなった時はalign-leftで表示させるためのclassの付加なんてこともここで一緒にやってしまえば良いと。

<?php
add_filter( 'img_caption_shortcode', 'my_img_caption_shortcode', 10, 3 );

function my_img_caption_shortcode( $empty, $attr, $content ){
	$attr = shortcode_atts( array(
		'id'      => '',
		'align'   => 'alignnone',
		'width'   => '',
		'caption' => ''
	), $attr );

	if ( 1 > (int) $attr['width'] || empty( $attr['caption'] ) ) {
		return '';
	}

	if ( $attr['id'] ) {
		$attr['id'] = 'id="' . esc_attr( $attr['id'] ) . '" ';
	}

	$capalign='capcenter';
	if(mb_strlen($attr['caption'],"UTF-8")>30){
		$capalign='capleft';
	}

	return '<span ' . $attr['id']
	. 'class="wp-caption ' . esc_attr( $attr['align'] ) . '" '
	. 'style="max-width: ' . ( 10 + (int) $attr['width'] ) . 'px;">'
	. do_shortcode( $content )
	. '<span class="wp-caption-text ' . $capalign . '">' . $attr['caption'] . '</span>'
	. '</span>';

}
?>
PHP
CopyExpand

変更したのは20~23行目と29行目。
あとはcssを追加するのみ。たとえばwp-caption-textをdisplay:block;でwidth:100%;にしておいて、capcenter、capleft それぞれのclass にtext-align:center;とtext-align:left;をしておけば良いかなと。なんてこった!こんな簡単なことだったとは、あちゃ~。
ということで、以下はこれを知らなかった時に色々と試行錯誤した記録となります。
・・・

the_content関数により生成されるpタグに煩わされていることも多いようです。
調べてみるとthe_content関数からpタグを取り除く方法もちゃんとあったりします。

<?php
	remove_filter('the_content','wpautop');
	the_content();
?>
PHP
CopyExpand

実際に適用してみると、たしかにpタグは無くなりますが、逆にpタグがなくなることでの不具合が出ます。brタグも無くなるので、これまで改行されていたのが同じ行に連なったりしてしまいます。

pタグを取り除くのをやめて、逆にdivタグとその中にあるpタグをたとえばspanタグに置き換えるということを試してみました。
実は「画像をクリックした時のログ」で画像をクリックした時に拡大表示させるとともにログを残すようにしたのですが、この後、画像のurlだけだと一目で何の鳥なのかは判別できないので、鳥名を一緒に残せるように改良しました。
既に、多くの投稿をしていましたので、記事自体を訂正するのも骨の折れることなので、the_content関数のフィルターフックを使って鳥名を入れるようにしてありました。
その関数をそのまま使用して、とりあえずやっかいそうなclass="wp-caption-text"のついたpタグを正規表現を使って差し替えるように試みたのが下記です。7,8行目がその部分です。
が、これでは全く差し替わることなくうまくいきませんでした。

<?php
function add_title_java($content){
	global $post;
	$bardname=get_the_title($post->ID);
	$bardname="showpop('".$bardname."*";
	$content=str_replace("showpop('https://strix.main.jp/***/uploads/",$bardname,$content);
	$pattern="/(<p class=\"wp-caption-text\">)(.*?)(<\/p>)/";
	$content=preg_replace($pattern,"<span class=\"wp-caption-text\">$2</span>",$content);
	return $content;
}

add_filter('the_content', 'add_title_java');
?>
PHP
CopyExpand

フィルターフックが[caption]ショートコードで生成される前なのか、文字列がエスケープされているからなのかよくわかりませんがこれではダメだということです。ちなみに鳥名を差し替える部分については上手く作動しています。

これでちょっと行き詰ってしまいました。
どうしてよいものか案がうかばず、caption自体を使用せず、そのかわりに画像の説明用の文字列を表示するためのcssの設定をして、入力しやすいようにショートコードを作って、というようなことをしてみました。
それはそれで新しい発見があって、また一つ便利な事を学ぶことが出来たのですが、既に投稿済みの記事においての対策は全く出来ません。

ふと、気づいたのは投稿の記事を取得するにはthe_content関数の他にもう一つget_the_content関数があります。
記事にphpにて何らかの処理を施してから出力したい場合にこちらを使用するわけです。
いいのか悪いのかわかりませんが、最終的に出力される状態のデータを差し替えればうまくいくのかもしれません。
ということで、以下のコードで試してみると、果たしてこれがうまくいきました。

<?php
	$tmpcont = get_the_content();
	$tmpcont = apply_filters('the_content', $tmpcont);
	$tmpcont=str_replace("div","span",$tmpcont);
	$pattern="/(<p class=\"wp-caption-text\">)(.*?)(<\/p>)/";
	$tmpcont=preg_replace($pattern,"<span class=\"wp-caption-text\">$2</span>",$tmpcont);
	echo $tmpcont;
?>
PHP
CopyExpand

spanタグはインライン要素で、インライン要素とテキストを含むことが出来ます。spanタグ自体のネストも可能なのです。

これで、一応、pタグに内包されていたdivタグとpタグは全てspanタグに変換されました。
divタグやpタグのブロック要素からインライン要素のspanタグに代わることでデザインが崩れますが、それはcssにおいてdisplay:block;を指定することで対処できます。
結果、めでたくW3C Validationもパスできたというわけです。
w3cvalidation ただし、このページを含めwordpress DIYの各ページは使用しているSyntaxHighlighterにおいてerrorが出てしまいます。このページを何度もW3C Validationにかけて試した方がいました。スイマセン、ここはエラーが出る事を付け加えるのを忘れていました。
・・・

2013年10月6日追記:
あと、上記とは別のことで少し気になっていることを。
それはcaptionに記入した時に表示される文字列のtext-alignに関する事。
captionの文字数が少ない時は中央揃えで表示させて、文字数が多く複数行になる場合は左揃えで表示させたいということ。

画像の配置は画像を挿入するときに選択することができて、画像のみのときはimgタグのclassにaligncenterが、captionを記入したときは大外のdivのclassにwp-caption aligncenterとしてclassが設定されます。
このclassにそれぞれtext-alignを設定してもいいんだけど、これは画像の配置を設定するためのクラスとして使いたいわけで、たとえば画像はfloat:right;でもcaptionはtext-align:left;にしたい時もあるということです。
逆に、画像の配置をcenterにて固定してしまい、このclassをcaption専用に使う様にしたとしても、caption入力時に文字数を数えて配置を選択して画像を挿入しなければいけないわけで、それもなかなか面倒なので字数から自動的に判断させて表示できれば楽ちんでいいんだけどなぁという考えです。

ということで、どこかでcaptionに入力した文字数を計算してそのcaption文字列を入れるタグの要素のclassを設定するという目論見です。
captionが入力されているときに、挿入される画像にcaptionショートコードを付加する関数は、wp-admin/includes/media.phpに記述してあって、image_add_caption関数がそれにあたります。
コードを見ると、画像を挿入するときのフィルターフック image_send_to_editorを利用しているのがわかります。
このimage_add_caption関数にもimage_add_caption_shortcodeというフックが用意されているので、それを利用してcaptionショートコードが付加されるときに操作すればできそうです。
image_add_caption_shortcodeというフックの引数は2つあって、$shcodeと$html。

  • $shcodeはcaptionショートコードを付加して生成したエディタに挿入する状態の文字列。
  • $htmlはcaptionショートコードを付加していないaタグとimgタグで構成される文字列。

$shcodeの文字列を操作してcaption文字列に新しくspanタグでclassを付加するということも考えましたが、そうするとspanタグが何重にもネストしてしまうのであまり気持ちのいいもんじゃない。

ここの場合、上記のpタグのエラーの問題でcaption文字列を内包するpタグをspanタグに変換しています。
で、あまり目立たない文字列を目印につけて、本文を表示する段階で目印のついた文字列を包含するそのspanタグのclassに追加するということを考えました。
まずはフィルターフック image_add_caption_shortcodeを使って目印を付ける関数。

<?php
function my_caption_shortcode($shcode, $html){
	$tarstr=mb_substr($shcode,mb_strpos($shcode,'</a> ')+4);
	$tarstr=str_replace('\[/caption\]','',$tarstr);
	if(mb_strlen($tarstr,"UTF-8")>30){
		$ansstr='.'.$tarstr;
		$shcode=str_replace($tarstr,$ansstr,$shcode);
	}
	return $shcode;
}

add_filter('image_add_caption_shortcode', 'my_caption_shortcode');
?>
PHP
CopyExpand

これで、captionの文字数が30を超える場合には”.”がcaption文字列の先頭に着くことになります。4行目に\[/caption\]とありますが、これは鉤括弧のエスケープのしかたがわからなかったので、それぞれバックスラッシュを付けています。実際はこのバックスラッシュは付けていません。
そして実際に本文を表示させるテンプレート内では、上の方に載せているget_the_content関数で取得した記事を操作している部分にちょっと付け加えて、

<?php
	$tmpcont = get_the_content();
	$tmpcont = apply_filters('the_content', $tmpcont);
	$tmpcont=str_replace("div","span",$tmpcont);
	$pattern="/(<p class=\"wp-caption-text\">)(.*?)(<\/p>)/";
	$tmpcont=preg_replace($pattern,"<span class=\"wp-caption-text\">$2</span>",$tmpcont);
	$tmpcont=str_replace('wp-caption-text">.','wp-caption-text leftalign">',$tmpcont);
	echo $tmpcont;
?>
PHP
CopyExpand

7行目が付け加えた部分です。
これにてcaption文字列を内包するspanタグのclassに、左寄せを設定するleftalignを付加することができ、目的は達成できたんですが、こんなに面倒なことをしなくても実はすっきりできるような気がしないでもないです。

Leave a Reply!

JavaScript is necessary to send a comment.
You can edit and delete your comment if you input a edit key.
Edit key is necessary for attesting you when you edit and delete it.
The tag of HTML cannot be used in comment.
When you comment for the first time, it is displayed after the approval of the administrator.
Because I cannot speak English so much, it takes time to answer.
Required fields are marked *.

※Please enter more than 5 characters only alphabets.
※Edit or delete are possible for 2000 days after approval.

*

♠Simplistic Comment User Editable v4.0

♠When visitors leave comments on the site this site collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection.
♠This site does not use cookie when visitors leave comments and commenter edit comment.
♠This site uses Akismet to reduce spam. Learn how your comment data is processed.

Comments feed

Trackback URL : https://strix.main.jp/wp-trackback.php?p=25041

Sanbanse Funabashi
2010.10.24 sunrise

Top

スクロールさせるか画像をクリックすると元に戻ります。