エントリーにpタグとbrタグが入る仕組み(その1:コード解析)

エントリーにpタグとbrタグが入る仕組み(その1:コード解析)

Posted at October 13,2004 12:08 AM
Tag:[Entry, Perl, Tag]

我楽さんのBlockquoteタグにデフォルトで改行が入るようにする。(のそれた話)がきっかけという訳ではないのですが、私もエントリーのblockquoteタグに改行が入ったり入らなかったりすることがあり、Movable Typeにおけるbrタグ挿入の振る舞いについて前々から調べてました(時間かかりすぎ?)。

ということで書けそうなレベルまでなんとか到達しましたので、シリーズもので書きます(単なるネタ増やしです(笑))。ほとんどPerl&正規表現メモになってしまいました。Perlプログラマの方には既知の部分しかありませんので予めご容赦ください。また認識誤り等ございましたらお許しください。「難しい」という方は最後のまとめだけお読み頂ければ幸いです。

エントリー入力画面で、下にある「テキストエリア」というセレクトボックスが「Convert Line Breaks」になっている場合、「保存」または「確認」をクリックすると改行部分には自動的に <p>~</p> または <br /> が挿入されます。

この処理を行っているのが

lib/MT/Util.pm

の html_text_transform という下記の関数です。

 1:sub html_text_transform { 
 2:    my $str = shift;
 3:    $str ||= '';
 4:    my @paras = split /\r?\n\r?\n/, $str;
 5:    for my $p (@paras) {
 6:        if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|blockquote|address|div|hr)@) {
 7:            $p =~ s!\r?\n!<br />\n!g;
 8:            $p = "<p>$p</p>";
 9:        }
10:    }
11:    join "\n\n", @paras;
12:}

処理は行番号毎に下記のようになっています。

  1. 引数であるエントリー文字列をローカル変数 $str に保持(他の処理から"@_"という省略された変数で引き継いでいます)。
  2. $str が空き、つまりエントリーが空きでなければ取得(この文は $str = '' || $str; と同義でしょうか)。
  3. $str を改行二つ(つまり空行)が入っている箇所で分割します。例えばエントリーに空行が3ヶ所あれば4つの(いわゆる)段落に分割されます。分割されたものは @paras という配列に保存されます。改行文字は文字コード(Shift_JIS、EUC等)によって "\r\n" と "\n" の2種類があり、
    \r?\n\r?\n
    と書くことで両者に対応しています。"?" は直前の文字、つまり "\r" が0回または1回出現することを示しています。つまり上記の正規表現は、
    \r\n\r\n または \n\n
    のいずれかを示しています("\r\n" と "\n" が混在することは多分ありません)。
  4. 分割された単位で下記の処理を繰り返します。この行では @paras から一段落分ずつ取り出し、変数 $p に設定しています。
  5. 該当するタグ(ここではh1、h2、h3?hr)にマッチしないか判定。 まず "m@?@" という構文はパターンマッチを表しており、段落中に "?" にある文字列が含まれていれば処理結果は「真」、つまり以降の処理を実施します。パターンマッチはPerlでは、
    /正規表現/
    という書き方が一般的です。ただし上記の場合、正規表現部分に "/" が含まれるとパターンマッチの文字列と区別するためにエスケープ("/" の前に "\")を付与しなければなりませんが、パターンマッチの区切り文字は変更することができます。該当の処理では、
    m@正規表現@
    という形式に変えているようです("/正規表現/" の場合は先頭の "m" を省略できます)。 またタグらしき文字列を区切っている "|" はいずれかに該当すれば良い、いわゆるOR条件演算子です。 "^" は文字列の先頭からマッチすることを示します。"<"はタグの開始文字そのものですので、"^" との組み合わせで段落の先頭が "<" で始まることがマッチする条件となっています。 さらに "<" と次の "/" が連続することで終了タグを示していますが、開始タグであることも条件に含めるために "/" の後に "?" を用いています。"?" の意味は3の説明の通りです。これで開始・終了タグである
    "<?" または "</?"
    のいずれも条件に含まれることになります。 "(?:?)" は後方参照(説明は省略します)を行わないことを指しています。後方参照の解除はメモリの節約です(と書かれてました)。

    以上をまとめると、各段落の先頭が"<h1"、あるいは"</h1"等、条件式に書かれている開始・終了タグにマッチしないことが、この行の条件となります。マッチしなければ次の行を実行します。
  6. 改行文字を "\n<br />\n" に変換。雰囲気で変換しているのは分かりますが先と同様、"?" を\rの直後に用いることで "\r\n" または "\n" を対象としているのが分かります。また文字列置換は、
    s/置換前の文字列/置換後の文字列/g;
    が一般的ですが先と同様、"/" のエスケープを避けるために、
    s!置換前の文字列!置換後の文字列!g;
    としているようです。最後の "g" は処理の繰り返しを表します(条件にマッチする限り置換処理を繰り返します)。
  7. 段落の最初と最後に <p>~</p> を挿入
  8. 分割した段落を "\n\n"(空行)で結合して元に戻す

処理内容は以上です。まとめると、

  • pタグ:段落の先頭と最後に挿入(空行で区切られたものが「段落」となります)
  • brタグ:段落内の改行部分に挿入。ただし条件式にかかれている文字列にマッチしない場合は挿入されない

ということになります。図に単純な例を示します。文章の前後には改行はないものとします。リスト内の「←空行」は便宜上の表示ですので文章には含まれません

【変換前】

あいうえお
        ←空行
かきくけこ
さしすせそ

【変換後】

<p>あいうえお</p>
             ←空行
<p>かきくけこ<br />
さしすせそ</p>

タグを用いた例については次回に記します。(つづく

参考:Perl スクリプト読解講座
関連記事
zenback
人気エントリー
トラックバックURL


トラックバック

Util.pm?絵文字入力その後? from Platinum
前絵文字入力を頑張っていたんだけど、今度は『短縮コード(独自タグ?)』で入力した... [続きを読む]

Tracked on December 26, 2004 12:59 PM

「改行を変換する」で、br /ではなくbrを入れたい from デースケドガーJP Lasty.org
lib/MT/Util.pmにある、html_text_transformという... [続きを読む]

Tracked on February 1, 2005 11:45 AM

[カ]変な改行の修正。 from 惜賭馬 Blog
以前のブログにて、スロのテンプレを作るのに、<ul>とか<dt... [続きを読む]

Tracked on March 21, 2005 9:45 PM

MTで気になること (pタグとblockquoteタグの取り扱いについて) from E.L.F!?$\~JunKtion
MTで、前々から気になることがある。 何かっつうと、MTってデフォルト状態だと、... [続きを読む]

Tracked on September 16, 2005 5:28 PM

エントリにpタグとbrタグが挿入される仕組みについて from naclog
エントリーにpタグとbrタグが入る仕組み(その1:コード解析) 正規表現ができないと分からない模様。 とりあえずメモ、と。 ... [続きを読む]

Tracked on March 26, 2007 3:04 AM

エントリにpタグとbrタグが挿入される仕組みについて from naclog
エントリーにpタグとbrタグが入る仕組み(その1:コード解析) http://www.koikikukan.com/archives/20... [続きを読む]

Tracked on April 2, 2007 4:09 AM

Movable TypeのBlockquoteタグ from *cosmos* blog
blockquoteタグが面倒だったんです。 改行をしてくれないために、わざわざ自分でタグを入れたりして。 なんとかならんのか!?と思って調べたら・・・... [続きを読む]

Tracked on March 25, 2008 12:10 PM
コメント

お知らせありがとうございます。^^

が、ちんぷんかんぷんっす。
ニュアンスは何となくわかるんですがね?。^^;

[1] Posted by Border. : October 13, 2004 10:03 AM

いえいえ。
必要な情報は最後の5行くらいですので、他は読み飛ばしてくださって結構です。

[2] Posted by yujiro : October 13, 2004 11:06 AM
コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)