ブロック要素のないすべての行にpをつけつつ、意味段落*1をdivで囲む というもの。
# 段落を付加する
$nest = 0;
$lines = explode("\n", $text);
$TAGS = "(h[1-6]|p|ul|ol|dl|blockquote|address|pre|table|div)";
$res = "";
$divs = FALSE;
for($i = 0; $i < count($lines); $i++)
{
if(!preg_match("/^\s*$/", $lines[$i]))
{
# ブロックタグ 開始
if(preg_match("/<$TAGS.*?>/", $lines[$i])) $nest++;
# divを開始する? divの外であり、h\d行・hr以外なら開始
if(!$divs && !preg_match("/<h[r1-6]>/", $lines[$i]))
{
$res .= "\n<div class=\"section\">\n";
$divs = TRUE;
}
# 行挿入 ブロックのネスト中・hrならそのまま、それ以外なら段落にして
if($nest || preg_match("/<hr.*?>/", $lines[$i]))
$res .= "$lines[$i]\n";
else
$res .= "<p>$lines[$i]</p>\n";
# divを終了する? divの中であり、次の行が空行・h\d行・hrのいずれかなら終了
if($divs && preg_match("/(?:<h[r1-6]>|^\s*$)/", $lines[$i + 1]))
{
$res .= "</div>\n";
$divs = FALSE;
}
# ブロックタグ 終了
if(preg_match("/<\/$TAGS.*?>/", $lines[$i])) $nest--;
}
}
$text = $res;NP_HatenaLike、これで、リニューアル時には公開できそうです。
なお、最初のほうにある$TAGSの内容をみれば分かるように、タグはすべて小文字=XHTMLしか考慮していません。NucleusはXHTMLなので、これで良いのです。
動作説明
pタグの挿入
まず、pタグの挿入はブロック要素内でないすべての行にpを挿入しますので、最初と最後でpreg_match("/<$TAGS.*?>/", $lines[$i])・preg_match("/<\/$TAGS.*?>/", $lines[$i])として、ブロック要素内かどうかを判断します(dt・dd・li・tr・tdなどは、かならず他のブロック要素に内包されているので、判定する必要はありません)。
他のブロック要素の中でなく、さらに<hr />のない行ならば、pで囲みます。それ以外の場合はそのまま、変数$resに格納しておきます。
意味段落の挿入
次に、意味段落を示す<div class="section">(以下、”意味段落”)の挿入。意味段落を開始しておらず、現在の行がh1〜6・hrでなければ段落の開始として、<div class="section">を挿入。
次の行が空行・h1〜6・hrのいずれかであれば、意味段落の終了と見なし、divを終了します。
空行そのものは一切処理しません。
すべての行がpタグで囲まれたり、</div>だけ挿入されたり、結構手こずりましたが何とか成功です。
*1:空行を意味段落の区切りと見なし、つながっている行すべて