高見知英のかいはつにっし(β)

高見知英のアプリケーション開発日誌 のほか、地域活動などの活動報告ブログ。

出来た!

ブロック要素のないすべての行に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しか考慮していません。NucleusXHTMLなので、これで良いのです。

動作説明

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