印刷用表示へ切り替え 通常表示へ切り替え 更新履歴を表示 更新履歴を隠す
MovableType Movable Type で長年日記

Movable Type の日付別アーカイブを長年日記にする。

■ ■ ■

このサイトでは,日付別アーカイブを作り,記事やカレンダーの日付部分をクリックすると表示されるようにしている。しかし,1日にいくつも記事を書くわけではないので,1個か2個しか表示されずとても寂しい。そしてほとんど使い道がない。

そこで,前年以前の同じ日付の記事を表示することにした。トップページのメインインデックスでは去年の記事を表示している(nlog(n): おかげさまで1周年 - 去年の今日を表示する)。その日付別アーカイブバージョンである。

tDiary では「長年日記」 (tDiary.org - 「長年日記」をmain trunkにマージ),Hyper NIKKI System Project では「n年日記」と呼ばれている(h14m.org 公式日記)。そらねっと通信局さんがやっているので,tDiary はいいなぁと思っていたのだ。

使えそうなプラグインとしては,MTOnThisDayMT-SomeDays がある。しかし,MTOnThisDay を日付別アーカイブに使っても,表示されるのは構築された日になってしまい,MT-SomeDays は思ったとおりに動かなかった。そこで,PerlScript プラグインを使って実装することにした。同様のことは Compare プラグインでもできるかも知れないが,以前の苦い経験から試していない。

アイデアとしては nlog(n): 月別アーカイブ一覧で表示月を強調したい と同じである。ただし,準備が必要。

実装環境は Movable Type 2.661 (+日本語化パッチ)である。以下の説明で「日付別アーカイブ」「日別アーカイブ」の2つの表現が出てくるが,同じものである(気分でそうなっちゃった)。

日別アーカイブテンプレートを作る

デフォルトでは,日別アーカイブや月別アーカイブは1つのテンプレート「Date-Based Archive テンプレート」から生成される。まずは,日別アーカイブテンプレートを月別アーカイブテンプレートから分離する必要がある。やり方は 小粋空間: アーカイブテンプレート作成方法 さんの通り。このサイトでは週別アーカイブを作っていないので,週別の設定は変更しないでおく。日別アーカイブだけを独立させて,テンプレート名は「Daily Archive」にした。

アーカイブの種類 テンプレート名
月別アーカイブ Date-Based Archive
週別アーカイブ
日別アーカイブ Daily Archive

日別アーカイブの編集

独立させた日別アーカイブを編集して,長年日記にする。ポイントは次の通り。

  • MTEntries を MTArchiveList で囲む
  • MTArchiveList の外側で日別アーカイブの日付を覚えておく
  • MTArchiveList の内側では,覚えておいた日付と処理する記事の比較を行い,同じだったら表示する

MTArchiveList で囲む理由は,アーカイブのコンテキスト処理から逃れるためである。通常,日別アーカイブ内で MTEntries を使った場合,その日しか表示されない。他の日を表示するには,日付に限定されているコンテキストを解除する必要がある。

MTArchiveList の外側で日別アーカイブの日付を覚えるには,MTSetVar を使う。ただし,記憶する値が定数ではなく,MTArchiveDate タグの値という変数だという問題がある。タグが入れ子になってしまうのだ。そこで MTTagInvoke プラグインを使う。nlog(n): 月別アーカイブ一覧で表示月を強調したい と同じ方法である。以下のように,赤字部分を追加する。

<MTTagInvoke tag_name="MTSetVar" name="thisday">
<MTTagAttribute name="value"><$MTArchiveDate format="%m%d"$></MTTagAttribute>
</MTTagInvoke>
<MTArchiveList>

<MTEntries>
<MTPerlScript>
  $a = '<$MTGetVar name="thisday"$>';
  $b = '<$MTArchiveDate format="%m%d"$>';
  if ($a eq $b) {
    print <<HERE_DOCUMENT;


(MTEntries の内側はそのまま)

HERE_DOCUMENT
  }
</MTPerlScript>

</MTEntries>
</MTArchiveList>

「print <<HERE_DOCUMENT;」では,最後のセミコロン「;」を忘れてはならない。また,最後の「HERE_DOCUMENT」の後ろにはセミコロンを入れてはならず,また行頭に空白を入れてはならない。

これでメインの修正は完了。再構築して動作確認を行う。

再構築に失敗するときは,MTEntryTitle, MTEntryBody にシングルクォートが含まれている可能性がある(nlog(n): 突然の再構築失敗は去年の記事が原因)。シングルクォート「'」は,文字参照形式で「&apos;」と書かなければならない。応急的には encode_xml をつければよいが,別の問題が発生するので注意が必要だ(nlog(n): encode_xml 属性の扱いの難しさ)。

ここから以下は「趣味」の修正である。

日付表示を修正する

日別アーカイブを長年日記形式にすると,そのアーカイブは「日」だけが同じで,違う「年」が複数並ぶことになる。そこで,一番上には「月日」を表示し,それぞれの記事には「年」だけを表示するのがよい。

「月日」の表示は,MTArchiveList の前に書いておく。

<div class="date">
<a href="<$MTArchiveLink$>" title="<$MTArchiveDate$>"><$MTArchiveDate format="%B %e"$></a>
</div>

「年」の表示は, MTArchiveList の中の日付部分を修正して表示する。%a を追加して曜日を表示するようにしている。

<MTDateHeader>
<div class="date">
<a href="<$MTEntryPermalink archive_type="Daily"$>" title="<$MTEntryDate format="%a %Y"$>">
<$MTEntryDate format="%a %Y"$></a></div>
</MTDateHeader>

記事に色づけする

長年日記の表示にすると,今日の日別アーカイブと1年前の日別アーカイブがほとんど同じになってしまうのでつまらない。そこで,今年分にだけ別の色をつけることにする。色づけ対象は blogbody,色はスタイルシートで指定することにする。スタイルシートには「thisyear クラス」を新設して色指定をしておく。色はお好みで何でもよい。

        .thisyear { background-color: #D7D4FF; }

やりたいことは,「アーカイブとしての今日」の場合に

<div class="blogbody thisyear">

「アーカイブとしての今日以外」の場合に

<div class="blogbody">

とすることである。div のクラスを複数指定したい場合は,スペースで区切る。色づけの指定が両方のクラスにある場合は,後のクラスの指定が有効になる。

さて,今年分だけを区別するには,「アーカイブとしての今日の年月日」を覚えておく必要がある。上で
あらかじめ「月日」を覚えさせたのと同様の方法を使う。変数の名前は「thisdate」にした。名前付けとしては,上で使った「thisday」は「日」,ここで使う「thisdate」は「年月日」の気持ちが入っている。MTPerlScript 内のコードは次のようになる。

$aa = '<$MTGetVar name="thisdate"$>';
$bb = '<$MTArchiveDate format="%Y%m%d"$>';
$blogbodystyle = $aa eq $bb ? ' thisyear' : '';
...
<div class="blogbody$blogbodystyle">
...

ヒアドキュメント「print <<HERE_DOCUMENT ... HERE_DOCUMENT」の内部では,Perl の変数の展開が行われる。つまり $blogbodystyle は,今日なら「(1文字スペース)thisyear」,今日でなければ「」(空白)になる。

クリックで年を移動
クリックで年を移動


年をクリックするとハイライトが移動するので,まあまあ面白い。

追加修正部分のまとめ

趣味の修正を含めたコードは次の通り。追加部分は赤,変更部分は青で示した。「...」は省略記号で,もとのソースのままであることを示している。

<div class="date">
<a href="<$MTArchiveLink$>" title="<$MTArchiveDate$>">
<$MTArchiveDate format="%B %e"$></a>
</div>

<MTTagInvoke tag_name="MTSetVar" name="thisday">
<MTTagAttribute name="value"><$MTArchiveDate format="%m%d"$></MTTagAttribute>
</MTTagInvoke>
<MTTagInvoke tag_name="MTSetVar" name="thisdate">
<MTTagAttribute name="value"><$MTArchiveDate format="%Y%m%d"$></MTTagAttribute>
</MTTagInvoke>
<MTArchiveList>

<MTEntries>
<MTPerlScript>
  $a = '<$MTGetVar name="thisday"$>';
  $b = '<$MTArchiveDate format="%m%d"$>';
  $aa = '<$MTGetVar name="thisdate"$>';
  $bb = '<$MTArchiveDate format="%Y%m%d"$>';
  $blogbodystyle = $aa eq $bb ? ' thisyear' : '';
  if ($a eq $b) {
    print <<HERE_DOCUMENT;

<MTDateHeader>
<div class="date">
<a href="<$MTEntryPermalink archive_type="Daily"$>" title="<$MTEntryDate format="format="%a %Y"$>"><$MTEntryDate format="%a %Y"$></a>
</div>
</MTDateHeader>

...
<div class="blogbody$blogbodystyle">
<$MTEntryBody$>
...
</div>
HERE_DOCUMENT
  }
</MTPerlScript>

</MTEntries>
</MTArchiveList>

まとめ

長年日記表示にすると,日付別アーカイブの使い道が増えて楽しい。これはいいことなのだが,問題もある。再構築に時間がかかることである。1つの日付別アーカイブを再構築する毎に,すべての記事の日付をスキャンしているからである。

新しい記事を追加したときには,その記事の日付別アーカイブは再構築されて前年を含む長年日記となるが,前年の日付別アーカイブは再構築されないので,翌年を含む長年日記にならない。過去の日付別アーカイブは別途再構築してやる必要があるが,一括再構築すると時間がかかりすぎて戻ってこない。mt-rebuild.pl でバッチ再構築するのがよい(nlog(n): cron でインデックスを再構築)。例えば次のようにコマンドを入力すればよい。

$ mt-rebuild.pl -mode="archive" -archive_type="Daily" -blog_id=1

2006年8月8日追記:
上記のコードは,ヒア・ドキュメント部分に問題があるので修正しました(nlog(n): 長年日記のコードを修正)。

Posted by n at 2006-04-22 22:41 | Edit | Comments (1) | Trackback(0)
Trackbacks

  • 「手違いで複数トラックバックを送ってしまった!」という場合でも気にしないでください (重複分はこちらで勝手に削除させていただきます)
  • タイムアウトエラーは,こちらのサーバの処理能力不足が原因です (詳細は トラックバック送信時のエラー をご覧ください)
  • トラックバックする記事には,この記事へのリンクを含めてください(詳細は 迷惑トラックバック対策 をご覧ください)
Comments

ご無沙汰です。

かー、久々にやってみたいハックを発見・・・でも時間がない&腰が重い・・・。それでもやりたいー・・・くー。
前向きに。

Posted by: zRyu at April 24, 2006 23:57
Post a comment
  • 電子メールアドレスは必須ですが,表示されません (気になる場合は「メールアドレスのような」文字列でもOKです)
  • URL を入力した場合はリンクが張られます
  • コメント欄内ではタグは使えません
  • コメント欄内に URL を記入した場合は自動的にリンクに変換されます
  • コメント欄内の改行はそのまま改行となります
  • 「Confirmation Code」に表示されている数字を入力してください (迷惑コメント対策です)


(必須, 表示されます)


(必須, 表示されません)


(任意, リンクされます)


Confirmation Code (必須)


Remember info (R)?