WordPressの記事一覧の抜粋でAAが崩れないようにした

2014年12月28日

前回の続きのような記事ですw

前回は、Wordpressの記事一覧の抜粋で改行がちゃんと反映するように修正したんだけど、
それだけだと、AA(アスキーアート) の表示が崩れてしまうのでござる。

原因は、当ブログでは顔文字などのAAを表示する場合
CSS で AA表示のための専用 font-family を使用してるのだが、
記事一覧の抜粋だと、そのCSSを使ったタグが削除されるちゃうから。

当ブログの AA 用 CSS

とりあえず、当ブログの CSS がどーなってるのかというと、

/* AA表示用の font-family */
.aa{
    font-family: 'MS Pゴシック', 'MS PGothic', 'MS Pゴシック', 'MS Pゴシック', MSPゴシック, MSPゴシック, IPAMonaPGothic, 'IPA モナー Pゴシック', 'IPA mona PGothic', 'IPA MONAPGOTHIC', Mona, Monapo, sans-serif;
    line-height: 1.2;
    letter-spacing: normal;
}

↑ こんな感じ。(line-height の値は、フォントサイズによって変えた方がいいかも)

記事内で AA を表示する場合は、

崩れたAA

↑ こんな風に記述すれば、

少なくとも Windows 環境であれば
↓ こんな風に見える。

きれいなAA

まぁ、個人的に複数行にわたる AA は、ほとんど使用しないが、
1行のAA でも、フォントによって見た目はかなり変わる。

1行AAの場合、ちょっとした違いにしかならないけど、なんとなく嫌だ・・・

前回のソースを改変

というわけで、前回の「the_break_excerpt」を改変することにした。

functions.php

function the_break_excerpt( $content=null ) {
    global $more;
    $more = true;    // more タグ無視で指定した文字数まで出力( more で切る場合は false に)

    $length = 120;    // 抜粋文字数(p、br タグを含む文字数)

    if( !$content ) {
        $content = apply_filters( 'the_content', get_the_content("") );
    }
    $content = preg_replace( "/\r\n|\r|\n/", "", trim( $content ) );

    // 顔文字が使われてたら、配列に入れて記録しておく
    preg_match_all( "/<[a-zA-Z]+?\sclass=\"aa\">.+?<\/[a-zA-Z]+?>/", $content, $aa_array );

    // <p><br>タグは残して、他のタグを削除
    $content = strip_tags( $content, "<p><br>" );
    // <img ~>などを<p>で囲ってた場合、<p></p> の形で残るので削除
    $content = str_replace( "<p></p>", "", $content );

    $content = mb_substr( $content, 0, $length );    //文字列を指定した長さで切り取る

    // <p><br>タグの途中で文字列が切れた場合、中途半端に残ったタグを < が出てくるまで後ろから1文字づつ削除
    while( strrpos( $content, "<" ) > strrpos( $content, ">" ) ) {
        $content = mb_substr( $content, 0, -1 );
    }
    // 最後が<br>だったら削除
    if( substr( $content, -6 ) == "<br />" ) {
        $content = mb_substr( $content, 0, -6 );
    }
    elseif( substr( $content, -4 ) == "<br>" ) {
        $content = mb_substr( $content, 0, -4 );
    }

    // 三点リーダー付ける
    if( substr( $content, -4 ) == "</p>" ) {
        $content = mb_substr( $content, 0, -4 );
        $content .= " ...</p>";
    }
    else {
        $content .= " ...";
    }

    // <p>タグの終了タグが無くなってた場合は終了タグを補完
    if( strrpos( $content, "<p>" ) > strrpos( $content, "</p>" ) ) {
        $content .= "</p>";
    }

    // AA が使われてた場合にAA用のタグを戻す
    foreach( array_unique( $aa_array[0] ) as $aa ) {
        $aa_notag = strip_tags( $aa, "<p><br>" );
        $content = str_replace( $aa_notag, $aa, $content );
    }
    return $content;
}

12~13行目と48~52行目を追加。

最初にAAの部分だけ配列に残しておいて、タグ削除・抜粋の抜き出しをした後に、AAを戻す仕組み。

AAを戻す際に、同じ AA が繰り返し使われてた場合
str_replace で何度も同じ置換をしてしまうところで結構悩んだ・・・

よくよく考えたら、array_unique で配列から同じAAを削除すればいいだけだったw

問題点

  1. 抜粋でAAが途中で途切れてた場合

    本文の行頭から120文字を抜き出してるので、途中で AA が挟まってた場合は対応できない。
    120文字を超える AA も当然、無理。

    まぁ、これは仕方ない。

  2. 同じ顔文字が、別々のタグで囲まれてる場合

    例えば、

    <span class=”aa”>(・∀・)</span><div class=”aa”>(・∀・)</div>

    こんなのが書かれていた場合、出力結果は、

    <span class=”aa”><div class=”aa”>(・∀・)</div></span><span class=”aa”><div class=”aa”>(・∀・)</div></span>

    こうなる・・・
    まぁ、レアケースだし、表示上、致命的とも言えないので、とりあえず放置で・・・

結果

修正前

ブログ記事の抜粋(AA修正前)

修正後

ブログ記事の抜粋(AA修正後)

微妙な差ではあるが、やはり 顔文字の部分がちょっと違う。

とりあえず、意図した通りの表示になったので、満足。

WordPress

Posted by るな