ブロック要素のないすべての行に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:空行を意味段落の区切りと見なし、つながっている行すべて