Mar 27, 2006

Re^2: MT 3.2のAtom API

というわけで、BlogWriteの作者さまから非常に丁寧な説明をいただきました。ありがとうございます。

HepCat Dev and Test: Re: MT 3.2のAtom API

もろもろ勘案すると、Ogawa::Buzz: MT 3.2のAtom APIに載っけた修正に加えて、以下の修正を行えば、無事BlogWriteからMT 3.2のAtom APIを利用でき、過去記事の取得も正常に行えます。

--- lib/MT/Atom.pm.bak Fri Mar  3 15:18:34 2006
+++ lib/MT/Atom.pm Tue Mar 28 09:17:10 2006
@@ -9,6 +9,7 @@
 
 package MT::Atom::Entry;
 use base qw( XML::Atom::Entry );
+use MT::Util;
 
 sub new_with_entry {
     my $class = shift;
@@ -17,22 +18,15 @@
     $atom->title(MT::I18N::encode_text($entry->title,undef,'utf-8'));
     $atom->summary(MT::I18N::encode_text($entry->excerpt,undef,'utf-8'));
     $atom->content(MT::I18N::encode_text($entry->text,undef,'utf-8'));
-    my $mt_author = MT::Author->load($entry->author_id);
+    $atom->content->type('text/html');
+    my $mt_author = $entry->author;
     my $atom_author = new XML::Atom::Person();
     $atom_author->set('name', MT::I18N::encode_text($mt_author->name(),undef,'utf-8'));
     $atom_author->set('url', $mt_author->url());
     $atom_author->set('email', $mt_author->email());
     $atom->author($atom_author);
-    my @co_list = unpack 'A4A2A2A2A2A2', $entry->created_on;
-    my $co = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", @co_list;
-    my $epoch = Time::Local::timegm($co_list[5], $co_list[4], $co_list[3],
-                                    $co_list[2], $co_list[1]-1, $co_list[0]);
-    my $blog = MT::Blog->load($entry->blog_id);
-    my $so = $blog->server_offset;
-    $so += 1 if (localtime $epoch)[8];
-    $so = sprintf("%s%02d%02d", $so < 0 ? '-' : '+', 
-                  abs(int $so), abs($so - int $so)*60);
-    $co .= $so;
+    my $blog = $entry->blog;
+    my $co = MT::Util::ts2iso($blog, $entry->created_on);
     $atom->issued($co);
     $atom->add_link({ rel => 'alternate', type => 'text/html',
                       href => $entry->permalink });

content要素にtype属性を追加したほか、MT::Util::ts2iso()を使ってRFC3339準拠のタイムスタンプを生成・追加しました。また、無駄なDBアクセスを削減するためにMT::Entryのメソッドblog, authorを用いてみました。


とは言うものの、MT 3.2のサポートするAtom APIはold-fashionedなので、無理に上記のパッチをあててまでBlogWriteからAtom APIを利用する必要はないかもしれません。

日本語のコンテンツがすべてBase64でエンコーディングされている気がします。

に関しては、MTにバンドルされているXML::Atom 0.07ではprintableか否かの判定に失敗してmode="base64"で出力され、最近のバージョン(0.19?)では正しくmode="xml"で出力されるようになっています。

Mar 26, 2006

MT 3.2のAtom API

MT 3.2のAtom APIがうまくないらしいという話を聞きました。

ここギコ!: MovableTypeのAtom APIって動いてます?(誰か助けてください)

ひとまず、Atomサービスの一覧のURLを修正すべく、以下のようにパッチをあててみました。

--- lib/MT/AtomServer.pm.bak Fri Mar  3 15:18:34 2006
+++ lib/MT/AtomServer.pm Sun Mar 26 20:57:15 2006
@@ -31,7 +31,6 @@
         handle => \&handle,
     );
     $app->{default_mode} = 'handle';
-    $app->{is_admin} = 1;
     $app->{warning_trace} = 0;
     $app;
 }

このパッチ自体はこっち(MT_3_2_ja2_UO_Patch - ogawa - Google Code)にコミットしておきました。

BlogWrite自体使ったことがなかったのでよく分かりませんが、Endpointにhttp://www.example.com/mt-atom.cgi/weblogを指定して試してみました。私の試した範囲では、過去ログの取得機能がうまく動かないことを除けば、特に問題なく動いている様子です。

BlogWriteがC:\Program Files\witha\BlogWrite\api以下に出力しているログを見ると、get_postsには成功していることが確認できます。MTが返す結果がBlogWriteの期待する形式と違うのかもしれないなと思っているのですが、このあたりは他のAtomPP対応のサービスと比較してみないとよく分かりませんね。

ひとまず作者さまにトラックバックしておきます。

HepCat Dev and Test: BlogWrite 2.4.1.1公開

ところで、is_adminというフラグは、MTのアプリケーションURLを決定する際に、CGIPath、AdminCGIPathのどちらをベースURLとして利用するか判断する目的で用意されているものです。というかそう考えられます。CGIPathではhttpを、AdminCGIPathではhttpsをベースURLに指定したり、後者のPathにはBasic認証を施したりするのはreasonableでしょう。

AdminScript(mt.cgi)は後者であるべきなのは明らかですが、AtomScript(mt-atom.cgi)はどちらか判断が付きかねます。XMLRPCScript(mt-xmlrpc.cgi)は前者なのでAtomScriptも前者でよいというのが一つの考え方で、上記のパッチはそれに従ったものです。一方で、AtomScriptはAdminScriptと同様にMT CMSへのログインや制御を行うのでAdminScriptと同程度にsecureでなければならないというのがもう一つの考え方です。

だったら、$app->{is_admin}=1の状態で、$app->uri()を呼び出したらAdminCGIPathを使ったアプリケーションURLを生成して欲しいわけですが、実際にはAdminCGIPathを使ったAdminScriptのURLしか返しません。この点を修正したければ以下のようにするとよいでしょう。

--- lib/MT/App.pm.bak Fri Mar  3 15:18:34 2006
+++ lib/MT/App.pm Mon Mar 27 11:31:22 2006
@@ -1005,11 +1005,11 @@
 
 sub uri {
     my $app = shift;
-    $app->{is_admin} ? $app->mt_uri(@_) : $app->app_uri(@_);
+    $app->app_uri(@_);
 }
 sub app_uri {
     my $app = shift;
-    $app->app_path . $app->script . $app->uri_params(@_);
+    ($app->{is_admin} ? $app->mt_path : $app->app_path) . $app->script . $app->uri_params(@_);
 }
         # app_uri refers to the active app script
 sub mt_uri {

ただし、もし仮に「$app->{is_admin}=1の状態で、$app->uri()を呼び出したらAdminCGIPathを使ったAdminScriptのURLを返す」仕様に依存したアプリケーション・プラグインがあったとしたら正常に動作しないことになります。このため、MT_3_2_ja2_UO_Patch - ogawa - Google Codeでは、lib/MT/AtomServer.pmのis_admin属性を落とすという修正方法を採っています。

Mar 24, 2006

Upgrading Fedora Core 4 to 5 with yum

Fedora Core 5もだんだん様子が分かってきた。Xenでanacondaを使ってVMにインストールできる(らしい)のが、個人的にはとてもありがたい。比較的ミッションクリティカルな用途に使っている既存システムも、Fedora Core 4から5にyumを使ってアップグレードしてみた。

前準備として以下の作業を行う。

  • FC4の環境でyum updateする。とにかく最新のバージョンをいれておこう。
  • /etc/inittabを編集してrunlevel 3で起動するようにinitdefaultの値を設定し、再起動。
  • 使っていないカーネル関係のパッケージを削除する*1。yum-utilsがインストールされていれば、
    # package-cleanup --oldkernels
    を実行すればよい。なければ、面倒だが、
    # rpm -q kernel kernel-smp kernel-devel kernel-smp-devel
    などと実行して調べ、rpm -eで根気よく削除する。
*1 特に2.6.14未満のすべてのカーネルは削除しておく必要がある。そうしないとinitscriptsなどのパッケージがコンフリクトしてアップグレードできないはず。

あとは、Upgrading Red Hat Linux/Fedora Core with yumにあるように、Fedora Core 5のfedora-releaseパッケージをインストールし、yum upgradeするだけでよいようだ。

# rpm -Uvh http://download.fedora.redhat.com/pub/fedora/linux/core/5/i386/os/Fedora/RPMS/fedora-release-5-5.noarch.rpm
# yum -y upgrade

まともなネットワークとハードウェアがあれば2時間くらいで終了すると思うが、ここで帰宅、食事、風呂、歯磨き、睡眠を摂ってもよい。

…さて、多分無事にアップデートが終了しているはずなのでリブートする。SELinuxをenableにしている場合には、

# /sbin/fixfiles relabel
を実行しないと一部のアプリケーションで怒られる可能性がある。

最後にrunlevel 5がお好みなら/etc/inittabを元に戻した上で、

# /sbin/init 5
程なく、かっこ良くなったログインスクリーンが表示される(…といいね)。

Mar 22, 2006

さくらの専用サーバ環境のDNS(スレーブ)設定

DNSのホスティングサービスにZoneEditを使っていた(Ogawa::Buzz: さくらの専用サーバ環境のDNS設定)のだが、いまいち調子が悪い。

これまで数時間引けないことが3回ほどあった。

ひとまず別のサービスを模索してみるべく、afraid.orgを利用してみようかと思ったのだが、afraid.orgってスパムの温床になってるっぽい。

というのも、afraid.orgにドメインを登録するとそのサブドメインは誰でも作れる状態になってしまうからなのだ。言い換えると保有しているドメインがスパムドメインと誤認される危険性があるということだ。それは困るので、再びZoneEditに戻し、ZoneEditのDNSがfeasibleでなくなったときのためにスレーブサーバをさくらの専用サーバ上に立てることにした。

まず、/etc/rc.confを編集して以下の行を追加する。

named_enable="YES"

次にlocalhost用の逆引きzoneファイルを作る。

# cd /etc/namedb
# sh make-localhost

master/localhost.rev, master/localhost-v6.revを見て問題がないかどうか確認しておく。

次にnamed.confを編集する。私の場合は以下のように変更した。

 --- named.conf.dist Wed Mar 22 17:38:18 2006
 +++ named.conf Thu Mar 23 09:52:40 2006
 @@ -19,3 +19,3 @@
  // the proper IP address, or delete this option.
 - listen-on { 127.0.0.1; };
 + listen-on { 127.0.0.1; my.ip.add.ress; };
  
 @@ -35,7 +35,8 @@
  // benefit from its cache, thus reduce overall DNS traffic in the Internet.
 -/*
 +
   forwarders {
 -  127.0.0.1;
 +  210.188.224.11;
 +  210.188.224.10; 
   };
 -*/
 +
   /*
 @@ -127 +128,18 @@
  
 +zone "mydomain.net" {
 + type slave;
 + file "slave/mydomain.net";
 + masters {
 +  69.72.158.226; // ns2.zoneedit.com
 +  66.180.174.61; // ns3.zoneedit.com
 + };
 +};
 +
 +zone "mydomain.org" {
 + type slave;
 + file "slave/mydomain.org";
 + masters {
 +  69.72.158.226; // ns2.zoneedit.com
 +  66.180.174.61; // ns3.zoneedit.com
 + };
 +};

allow-transferを設定した方がよいかも。

次にnamedを起動する。

# /etc/rc.d/named start

しばらくしてslaveディレクトリに下にZoneEditから転送されてきたzoneファイルができているかどうか確認する。

/etc/resolv.confに以下の行を追加。

nameserver 127.0.0.1

他のnameserver行を削除してもよいが、誤ってnamedを殺してしまったり、再起動時にnamedが起動しなかった場合にはリモートからsshでログインできないなど致命的な事態に陥るだろう。だから残しておく。

最後にZoneEditのNameServersの項でさくらの専用サーバを登録しておく。ホスト名は逆引きのホスト名(XXX-XXX-XXX-XXX.r-bl100.sakura.ne.jp)にしておくとよい。

追記:
でも結局、さくらでスレーブサーバを動作させるのはやめて、afraid.orgをスレーブサーバとして利用する方法を採っている。これだとafraid.orgに勝手にサブドメインを切られることはないし、ZoneEditの応答性の問題の対処にもなる。

Mar 21, 2006

Wiki、はじめました。

少し間が空きましたが、間が空いている間に、Wikiをはじめてみました。

Main Page - Ogawa::Wiki

というのも、Movable Typeのプラグインなどを公開するのに、過去のエントリーを遡って更新しなくてはならないブログではいい加減つらくなってきたのです。

もう少し具体的に書くと、ブログでソフトウェアを公開する一つのスタイルとしては、一エントリーを一ソフトウェアの「公開ページ」にしておき、アップデートごとに再編集する一方、別エントリーで「更新情報ページ」を書くというのが一般的でしょう。でもそれでは公開ページが散逸しやすくて管理しづらいだけでなく、ちょっと前に作ったソフトウェアがなかなか参照してもらえなくなってしまいます。また、「更新情報ページ」は使い切りのブログでもよいけれど、「公開ページ」やソフトウェアのパッケージはバージョン管理機能がぜひとも欲しいところです。

別の用途でDokuWikiとかPukiWikiも使っていてそれなりによくできていることは知っているのですが、今回どうしてもデータをSQL DBにストアしたかったのとバージョン管理機能が欲しかったので、MediaWiki 1.5.7を使ってみています。ソースを見ていると「なんかちょっとアレかな~」と思わなくもないところもあり…しかしユーザーベースは最大のフリーWikiシステムではないかと思うので…つまるところ、まあ様子見です。

Movable Typeのプラグインのまとめページなどは早々にWikiに移行し、更新情報はエントリーとしてこのブログにポストしていく予定です。

例えば、Mapper PluginのWikiページは下のような感じ。

Mapper Plugin/ja - Ogawa::Wiki

discussionのところからコメントも付けられるし、トラックバックも送信できます。数寄者の皆様にはXML Feedもご用意しております。

Mar 14, 2006

Re: MovableType Mapperプラグインと locationプラグインの融合キボンヌ

何となく予想できた方面から万艦飾なリクエストが来ました(笑)。

ここギコ!: MovableType Mapperプラグインとlocationプラグインの融合キボンヌ

私も同じようなことを考えていました。ついでに言うとオレオレトラックバックサーバにしかトラックバックできないようにし、相互リンクでオレオレアクセス数を稼ぎ、広告収入をがっぽがっぽ...とかいきたいところなんですが...嘘です。

私なりに整理してみると、(1)ロケーション情報の入力源の充実、(2)ロケーション情報へのアクセスメソッドの提供、(3)トラックバックの実現、の3点があります。で、私の考えでは別のプラグインとしてこれらの機能を提供するのでもよいかな、というところです。

この別プラグインでは、まずエントリーやエントリーに添付された画像ファイルに記述されたロケーション情報をエントリー保存(公開)時にextractして、中間ストレージに保存します。トラックバックなどのNotification系のアクションは基本的に同じタイミングで行います*1。トラックバックの送信の有無をコントロールしたければ、ロケーションデータにトラックバックURLを関連付けておいて(その情報も中間ストレージに保存してもよい)、後で送信するという方法にする必要があるかもしれませんけどね。

*1 ところでAlps Clip!のMTプラグインは、グローバルフィルタ適用時、すなわち再構築時(≒ビューの生成時)にトラックバックを送信しますが、あまり良くないような気も。再構築するたびにトラックバックを送信する、悪魔のプラグイン...。Alps Baseの方ではURLでユニフィケーションしてトラックバックを捨てたりしているのでしょうか。MT::Entry::post_save()などのフックを利用された方がよいでしょう。

一方で、中間ストレージに格納されたロケーション情報へのアクセスメソッドもコンテナタグや変数タグとしてテンプレートから利用できるようにします。こちらは再構築時にテンプレートの記述にしたがって処理されるものとします。こっちのアクションは、Notificationとは異なり、中間ストレージへのアクセスだけで実現できます。

そうすると、Mapper Pluginの実現する変換処理は、このプラグインが管理する中間ストレージへのアクセスできさえすれば、コンテナタグやグローバルフィルタとして実現できてしまうので、独立したプラグイン(あるいはプラグインのサブのサブ機能くらい)でもいいかな、と。

さて、ねねさんのエントリーでは(1)~(3)に加えて、テンプレートでの制御(=プログラミング)のアイディアが提示されています。これは面白いのですが、ここはConcernをseparateすべき部分だと思っています。

テンプレートはエントリー保存時に参照されるものではなく、再構築時(≒ビュー生成時)に参照されるものです。言い換えると、エントリー保存時のアクションをテンプレートに書くべきではありません。これを厳密に守るならエントリーにプログラム記述する方がむしろ筋が良いわけで、例えば、Alps Clip!では、mapタグとmap_tbタグがあるおかげで、ユーザがエントリー内で処理をプログラムできているんだぜという言い方もできます。とは言え、これ以上に複雑な制御をエントリーに書かせるのは無理があるのは確かです。オルタナティブとしては、プラグインの設定画面のフォーム上でトラックバックの上位プロトコルをプログラムできるようにするとよいかも...と思います。

あと、ロケーション情報のストレージとアクセスメソッドはRightFieldsにオフロードしてしまうのととても簡単なのですが、そうすると導入時障壁が高くなってしまうのが悩みでもあります。Tagwire PluginのときにPluginDataを使ってネチネチ書いたのは(まったくもって苦痛な作業でしたが)、この点を当初重視していたためなのです。が、結果として速度やダイナミックパブリッシングからの可用性を犠牲にしてしまいました。Tim Appnelも以前mt-dev : MovableType Plugin Developersあたりで何か叫んでいましたが、本当はMovable Typeがユーザ定義のオブジェクトを管理する機能を持っていればいいんですけれど。

ここギコ!: Re^2: MovableType Mapperプラグインとlocationプラグインの融合キボンヌ

中間ストレージに吐いておくのは、後で別用途でソートしたりする際にも軽くなるので、よいかなと思いました。 ただMovableTypeって、中間ストレージをプラグイン等で自由に作れる公式仕様ってあるんでしたでしょうか。 なかったので今までkeyword属性をいろんな用途に使いまわしたり、RightFieldsとかが画期的だったりしたのかなと思ったのです。

Movable Typeが提供している機能としては、MT::PluginDataがあります。Storableなどを使ってシリアライズしたデータをBLOBとしてDBにストアするという単純なものです。本来はプラグインのconfigurationを保存しておく目的のものですが、事実上いかなる用途にも使えます。細かい話をすれば、MT 3.1と3.2ではシリアライザの仕様が違っていてプラグイン開発者泣かせです。

RightFieldsやTags.AppなどのようにDB上に自前のテーブルを作成することも当然できます。前者はmt_entryテーブルを拡張する任意のテーブルを定義できますが、1エントリーに1レコードしか対応付けられないという制約があります。後者はタグ用のテーブルを定義し、1エントリーに複数のレコードを関連付けられます(がもちろんタグしか格納できません)。彼らが「勇者」たる所以は、「たかが一プラグインのためにここまでするのか」という点に尽きます。

Six Apartでは、開発者コミュニティで不満の出ていた、プラグインのブートストラップ周りを弄っているようですし、ユーザ定義の永続オブジェクトもサポートしてくれるんじゃなかろうかと思っています。それまではあまり深入りしたくない気もしますけどね。

作成のフック利用でもいいと思うんですが、エントリ作成でなく更新時に新しい位置情報入れたりするケースもあると思うので、Entryオブジェクトのpinged_urlに突っ込んじゃってもいいと思います。

MT::Entry::{pre,post}_save()は新規作成に限らず、エントリー保存時に呼び出されるフックなので、そのタイミングでto_ping_urlに突っ込めばMTのトラックバック送信機能を使ってトラックバックを打つことができます。Alps Clip!のようにプラグインが自前で送信してもよいですし。また、pinged_urlをチェックして重複トラックバックを検査するというアイディアは、別の単体プラグインのアイディアとしても悪くないなと思いました。

そうではなくて、トラックバックは保存時の処理であって、エントリ再構築の中で行うべき処理ではないという意味の事であれば、個人的には所定の機能が得られればどちらでもよいのかなあと思います。

しかし、ダイナミックパブリッシングの時には再構築自体行われないのです。ですから、ビューを生成する作業を再構築時もしくはダイナミックパブリッシングによるページ生成時に行い、それ以外の作業を保存時に行う必要があります。


作るべきものはだんだん明確になってきたのですが、全然時間が取れません。地下鉄プログラミングを再開しなくては!!

Mar 13, 2006

Mapper Plugin 0.10公開

Ogawa::Buzz: Mapper Plugin公開を0.10にバージョンアップしました。

Mapper_Plugin - ogawa - Google Code

トラックバックやTechnoratiを見ていると、「住所では意図したのとずれた場所しかポイントできないので座標で指定したい」というご指摘がありました。

ブログに地図を載せてみた : blog::made in SAGA

このご要望に対応してみました。0.10では、住所だけでなく、[map:x139.808004y35.679714]、[map:35.679714,139.808004]のように緯度・経度のペアを指定することができます。

Alps Clip!のプラグインも座標指定に対応していますが、60進法の値(分・秒)で指定する必要がありました。私の好みは小数点以下は10進で表現する方式なので、Mapper Pluginもそうなっています。で、これは実ははてなマップのマップ記法と同じです。はてなマップ記法に慣れている方には都合がよいでしょう。

また、座標情報を正確に調べるには、Google ローカルと下記のBookmarkletを利用するのが簡単です。

Ogawa::Buzz: Pin It!: Googleマップで任意の場所にピンを立てるBookmarklet

他にトラックバックでのご意見としては、「InfoWindowに住所だけでなく、補足の情報も記載したい」というものもありました。

101Blog: Mapper Plugin - Ogawa::Memoranda

時間がないためすぐには無理ですが、いずれ対応したいと思います。

他にも改善のためのアイディアをお持ちの方は遠慮なく、コメント・トラックバックをお送りいただければと思います。

Mar 9, 2006

XML2JSONサービスを使ってFlickr Badgeを作る

XML を JSON に変換するサービス - ベータ版を公開 :: Drk7jpの意義がいまひとつ分からなかったので、ひとまずFlickr Badgeを作ってみた。

<div id="flickr-badge"></div>
<script type="text/javascript">
var flickr_method = 'flickr.people.getPublicPhotos';
var flickr_api_key = 'your flickr api key';
var flickr_user_id = '00000000@N00';
var flickr_per_page = 5;
var flickrUrl = 'http://www.flickr.com/services/rest/?method=' + flickr_method
    + '&api_key=' + flickr_api_key
    + '&user_id=' + flickr_user_id
    + '&per_page=' + flickr_per_page;
 
var flickrBadge = {};
flickrBadge.init = function() {
    var name = 'flickrBadge';
    var proxy = 'http://app.drk7.jp/xml2json/';
    var script = document.createElement('script');
    script.charset = 'utf-8';
    script.src = proxy + '&var=' + name + '&url=' + encodeURIComponent(flickrUrl);
    document.body.appendChild(script);
};
flickrBadge.onload = function(data) {
    var photos = data['photos']['photo'];
    var res = '';
    for (var idx in photos) {
 var photo = photos[idx];
 res += '<a href="http://www.flickr.com/photos/'+ flickr_user_id + '/'
     + idx + '/" title="' + photo["title"]
     + '"><img src="http://static.flickr.com/' + photo["server"]
     + '/' + idx + '_' + photo["secret"] + '_s.jpg" /></a>';
    }
    var ele = document.getElementById('flickr-badge');
    ele.innerHTML = res;
};
 
if (window.addEventListener) {
    window.addEventListener('load', flickrBadge.init, false);
} else if (window.attachEvent) {
    window.attachEvent('onload', flickrBadge.init);
} else {
    var old = window.onload;
    window.onload = (typeof old != 'function') ?
        flickrBadge.init : function(e) { old(e); return flickrBadge.init(e);};
}
</script>

うーん、動くね。この例の場合には、Flickr ServicesへのリクエストがXML 2 JSON serviceでキャッシュされるのはありがたい。だけどこのコードをユーザが書くのは少し無理があるような...。

追記: またもInternet Explorerでうまく動かないや。後で修正しよう。

→修正完了。ポイントは、script要素のappendをドキュメントのロード後まで遅延したということ。Mapper Pluginもそうなのだけど、IEやSleipnirでは必須っぽい。

Mar 5, 2006

Mapper Plugin公開

エントリーなどに含まれる「mapタグ」*1をマッピングサービスを利用した地図画像に変換するプラグインを公開します。

*1 mapタグとは、Alps Clip!はてなマップで使用されている「[map:address]」という形式の文字列を指します。addressには、「東京都江東区三好4-1-1」のような「住所」での表記を記述できるほか、「x139.808004y35.679714」「35.679714,139.808004」のような「座標」での表記も記述できます。

Mapper_Plugin - ogawa - Google Code

このプラグインは、MTMapperというコンテナタグを実現します。このコンテナタグに含まれるテンプレート中で以下のパターンにマッチする文字列があれば、それをGoogle Mapsなどのマッピングサービスを利用した地図画像に変換します。

Alps Clip!・はてなマップライク:
<div>[map:address]</div>
<p>[map:address]</p>
adr microformatライク:
<div class="adr">address</div>
<p class="adr">address</p>

例えば、以下のようなmapタグを記述しておくと、

<p>[map:東京都江東区三好4-1-1]</p>
<div class="adr">東京都江東区三好4-1-1</div>

以下のようなGoogle Mapsによる地図画像が描画できます。

Mar 3, 2006

Re: ALPSLAB clip! MTプラグイン

Geocoderコミコミでわりと便利そうなALPSLAB clip!のMovable Type用プラグインですが、設計に関して少しコメントしておきますね(まだ私は使っていません)。

ALPSLAB スタッフブログ:MT プラグインをハックされる方へ

  1. このグローバルフィルターはMTEntriesコンテナもしくはその内部に記述できる変数タグ(MTEntryBody, MTEntryMoreなど)で使用されるという暗黙の仮定があります。それ以外の場所で利用すると正常に動作しませんが、エラーチェックが行われていません。また、グローバルフィルターにせず、コンテナにするというのも一つの手。グローバルフィルターでは変換の適用順が明示的に指定できないという欠点がありますし、コンテナならば任意のテンプレート片に含まれるmapタグを処理できます。
  2. map_tbはトラックバックping送信後のエラーチェックをしていません。また、url, dateなどEUC-JPに変換する必要のないフィールドも変換しています。
  3. MT::Utilにユーティリティルーチンがあります。利用するともう少し簡単に書ける部分があります。

さてここで、Google Mapsファンなんだけど、MTGoogleMapsはGeocoder付きじゃないんで使いづらいよ、IEだと一ページに一枚しか地図が表示されなくて使いものにならないよ、とお嘆きの老若男女に朗報です。

ALPSLAB clip!と同様にmapタグを検出してGoogle Mapsを表示するプラグインを作りま……す。とは言ってもまだ一行も書いていないのですが。理想的には、pluggableにして出力はGoogleでもALPSでもYahoo!でもlivedoorでもできるようにしたいところですね。

追記:
一応デケタ。Mapper.pl。明日塩原温泉に浸かりながらリリース用のエントリを書く予定。

Mar 2, 2006

平成の大合併

この3月は平成の大合併のピークです。特例債利権をめぐるチキンレースも佳境に入ったということです。

平成の大合併(日本列島お国自慢)

うちの地元のお隣でも元旦に新・岐阜市が誕生しましたが、その裏には全米が泣いた経緯があります。

岐阜広域合併協議会ホームページ

岐阜広域合併協議会ホームページ

岐阜市・柳津町合併協議会ホームページ

とは言うものの、わずか人口1万2千の柳津町はジャスコシティ柳津とカラフルタウン岐阜という2つの巨大商業施設(とついでに岐阜流通センター)を有していますし、特例債もゲットできるわけですから、それなりに円満な吸収合併と言えます。羽島市が当初の計画通りちゃんと合併していれば、岐阜羽島駅が岐阜市になったはずなのですが…。

翻って私の出身地を見ますと、やはり3月27日に大垣市を含む1市2町(墨俣町、上石津町)で新・大垣市になります。

大垣市ホームページ:大垣市 1市2町による合併

当初の計画では1市9町だったわけですが、7町離脱で三点飛び地による合併です。三点飛び地の前例としては新・高崎市がありますが、墨俣町、上石津町は地を這うような財政力な上、下水整備事業という足かせがあり、特例債を考慮に入れても大垣市に何のメリットがあるのかさっぱり分かりません。また、墨俣町では住民投票とか民主的なプロセスを経た気配がない(町議会がそれだと言えばそうなのだけど、いったい共産党は何をやっていたのだろうか)のですが気のせいですか? あの金の鯱付きの天守閣ができたときも同じだった気がしますが? 「天守閣付きの一夜城を建てるのが町民の悲願だった」に続いて「市になるのが町民の悲願だった」とか言うつもりでしょうね。

…そんな悲願、10何年住んでて一度も聞いたことねえよ。

ちなみに墨俣町は面積が3.39キロ平米しかありません。3月1日に高知県の赤岡町が合併によって香南市になったおかげで、現在日本最小面積を誇る自治体です。27日間の天下ですが。

香南5町村合併協議会ホームページ

3月27日からは、3.47キロ平米の富山県中新川郡舟橋村がナンバー1となります。がんばれ、舟橋村。

舟橋村

ついでなので、関西国際空港があるコンパクトシティ、大阪府泉南郡田尻町にも言及しておこう。平成2年には1.94キロ平米しかなかったのが、今は3.86キロ平米まで増量している。

田尻町

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com