WordPress(ワードプレス)でbrBrbrでbrさせたくないところが出来てしまったとき。

wordpressでbrBrbrのプラグインを使用している場合に、入力欄にソースコードを入力した場合に発生する表示崩れの回避方法です。


wordpressの入力欄はデフォルトだと連続した<br>が勝手に<p>に変換されてしまいます。そこで皆さん改行が普通に使えるよう色々と対策を施すわけですが、弊社ではbrBRbrというプラグインを使って、連続した改行を実現していました。

それが今回ちょっとした不具合発生です。お客様から、独自にtableで組んだ表を、ぺたりと張るだけで反映されるようにしたいというご要望。

ところが上記の状態で入力欄にソースコードを普通に貼るとソース上での改行が全て<br>に変換され、見た目上とんでもないことになります。

「いやっ、ちょっ・・・スペース使い過ぎwwww」

みたいな状態になるのです。

で、以下その対策。今回は、プラグインのソースコードを少しいじらせていただきました。

あ、最近書いてなかったので忘れかけていましたが、僕の肩書きは元デザイナーのディレクターで、プログラムは見よう見まね。門前の小僧が習わぬ経を読んでるつもりだろうけど所々間違ってるだろオイ、っていう感じです。

なので、勘でやってみて動けば御の字。参考にされる方はお気をつけくださいませ。

さて、brBrbr.phpを開くと以下のような部分があります。

function brBrbr($brbr) {
	$brbr = str_replace(array("\r\n", "\r"), "\n", $brbr); // cross-platform newlines 
	$brbr = str_replace("\n", "<br />\n", $brbr); // cross-platform newlines 
	$brbr = preg_replace('!(</?(?:table|img|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|textarea|input|blockquote|address|p|math|script|h[1-6])[^>]*>)\s*<br />!', "$1", $brbr);
	$brbr = preg_replace('|<blockquote([^>]*)>|i', "</p>\n<blockquote$1><p>", $brbr);
	$brbr = str_replace('</blockquote>', "</p></blockquote>\n<p>", $brbr);
	$brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/ise', "clr_br('$0')", $brbr);

	$brbr="<p>\n".$brbr."</p>\n";
	return $brbr; 
}

function clr_br($str){
	$str  = str_replace("<br />","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
}

恐らく先頭の数行で改行コードを<br>に変換しているのだと思われますが、最初のfunctionの末尾付近、どうもそれを除外してるっぽい記述が見られます。
このへんですね。

	$brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/ise', "clr_br('$0')", $brbr);

ここは恐らく、特定のタグに囲まれた部分については、<br>取っちまおうぜ(意訳)っていうことだと判断しました。このいわゆる正規表現的な部分の中の見覚えのあるタグっぽいとこさえ書き換えればいけんじゃね?と思い試してみたら行けました。行けたんですよ。

さてこれだけだと全ての<br>が取り去られてしまいます。それだと、当初のソースコードに<br>が入っていた場合それまで一緒に消えています。それはまずい。

ってことで、当初より入っている<br>が消えない方法はないか摸索しました。

どうやら、<br>をクリアしているのは別functionでどうもこの辺のもよう。

function clr_br($str){
	$str  = str_replace("<br />","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
} 

で、考えました。後から挿入された<br>は改行コードを変換する形で挿入されるので、上記のプログラム中の表現で言うと必ず<br />\nの形を取るのではないか。

そこで、上記のbrクリアのfunctionを以下のように書き換えました。

function clr_br($str){
	$str  = str_replace("<br />\n","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
} 

消す<br>を改行付きのものに限定したわけです。これでまんまと元の<br>を残すことに成功しました。

そして今回はtableを貼りつけたいというご意向ですので、tableの場合には・・・という処理を書き加えます。で、完成したソースは以下

function brBrbr($brbr) {
	$brbr = str_replace(array("\r\n", "\r"), "\n", $brbr); // cross-platform newlines 
	$brbr = str_replace("\n", "<br />\n", $brbr); // cross-platform newlines 
	$brbr = preg_replace('!(</?(?:table|img|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|textarea|input|blockquote|address|p|math|script|h[1-6])[^>]*>)\s*<br />!', "$1", $brbr);
	$brbr = preg_replace('|<blockquote([^>]*)>|i', "</p>\n<blockquote$1><p>", $brbr);
	$brbr = str_replace('</blockquote>', "</p></blockquote>\n<p>", $brbr);
	$brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/ise', "clr_br('$0')", $brbr);
	$brbr = preg_replace('/(<table.*?>)(.*?)<\/table>/ise', "clr_br2('$0')", $brbr);
	$brbr="<p>\n".$brbr."</p>\n";
	return $brbr; 
}

function clr_br($str){
	$str  = str_replace("<br />","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
}
function clr_br2($str){
	$str  = str_replace("<br />\n","",$str);
	$str  = str_replace('\"','"',$str);
	return $str;
}

これで完了。

全ての場合に当てはまるわけではないのですが、その都度、必要に応じて上記の流れを調整することで、ある程度の対応が可能となるのではないでしょうか。

お役に立てば幸いです。