« 2007年08月 | メイン | 2007年10月 »

2007年09月 アーカイブ

2007年09月28日

結局ブログ内検索はどうすればいいのか?

テンプレートのところはツッコミ来るかなぁと思っていましたがまぁいいや! って書いたらやっぱり来ましたね。(o)さんは絶対にそこんとこ見逃しちゃぁくれません!

あと実験に関して付け加えると、やや公正さに欠けると思います。2.が「ブログ記事のメタデータ」モジュールのみ外した状態になっているのは比較上問題があります。利用するテンプレートの個数が異なりますから。それなら最初からflatteningしたテンプレートを使って比較すべきです。

たしかにモジュール読み込む時間分不公平でしたごめんなさい。

引き続きブログ(サイト)内検索を考える

「検索」についてはあれこれこれまでもやっていて、このブログにはHyper Estraier入れて、エントリーの保存時にインデックスを更新するプラグインを書いて利用してるので(出力の方はPHPにしてて起動のストレスもあんまりなくて)速度的には問題ないと感じてるのですが、皆がみんな導入出来るわけでもないわけで。

今週2本検索プログラム書いてみました。まだまだチューニングできるかと思うので もうちょっと何とかなったら公開しますね。

結局、検索に対する要求をmt-searchが満たせない(とWeb屋としての僕が思う)のは、

  • 表示件数はともかく、何件マッチしたかが知りたい
  • せめてページ送りができると嬉しい
  • 検索語がハイライトとかできるといいな
  • 検索結果の表示順にキーワードの出現頻度とかを考慮して欲しい
  • HTMLタグまで検索に含まれるのはどうにかして欲しい
  • 1ページにある程度の件数は欲しい

* 「結局ブログ内検索はどうすればいいのか?」Googleを使えってのはとりあえず考えないこと前提で (話がそれまくるので) 。

最後の話については、例えば(僕の知っている)視覚障害者の人は「ページ内検索」を良く使います。(cmd(ctrl)+F)で検索結果ページに対してページ内検索をかけて欲しい情報を探して移動するような使い方。

こういうことを考えると、ページ送りがあるにしても1ページにある程度の件数が欲しくなります。マッチするページが多ければ多い程。

で、もちろんmt-searchはタグ検索とか色々な役割を担っていてこれはこれで必要な機能を実現するために必要なものですが、(o)さんもご指摘の通り相変わらずふざけるなってくらい遅いですということなので、検索については案件毎に作ったりしていたのです。

で、今回MT::Objectのサブクラスを作ってテーブルを拡張してたりすると、そのテーブルがmt-serarchでは反映されてくれないということで(当たり前なんですけど、毎回オリジナル検索作るのも馬鹿げてると思ったので)汎用的なのを作ってみました。

結局、(MTにおける)サイト内検索の速度ってのは

  1. PerlCGIの起動の速度の問題
  2. 純粋な検索速度の問題
  3. テンプレートの再構築速度の問題
  4. データの転送とブラウザのレンダリング速度の問題

の4つの要素が絡むのかと思うわけですね。

1つめはFastCGI(mod_perl)かPHPを使うことで改善されます。問題は2番目と3番目かな。あと4番目もMT4のデフォルトテンプレートだと「ブログ記事のメタ情報」以前に、エントリーの本文とか(貼付けてある画像も表示されるし)これ全て検索結果に必要? って思うものが含まれています。もちろん、タグでの絞り込みとかにはいいんでしょうが。

さて、今回は2つめの件、つまり純粋に高速検索を実現するにはどうするかを考えてみました。

方法1. mt-searchと同じくループで回してマッチング

検索すべき文字列を一つのテーブルに放り込む。その際にHTMLタグは削除してしまう。但し画像のALT属性とかは検索対象にするようなフィルターを噛ましてから放り込む。

後は普通にループでマッチングを調べる。但し正規表現でなくindex関数を使って文字列が含まれるかどうか調べる。

最大検索数は設けるものの、その件数に達するまではループさせてページ送りを実装する。ここが一つの問題で、マッチした件数を調べるためにループを継続しないといけないのです。なぜなら「この文字列を含むレコード数」を簡単に調べる方法が現状のMTでは無いから。結局MySQLとかでLIKE検索した方が圧倒的に速いのです。

ただ、経験上ループ自体は(対象エントリーが数百であれば)そんなに時間かからないと感じているので、まぁやってみようかと。

あと、高速化のために、テーブルには表示用のデータ(ページの概要, メタデータとか)を一緒に保存しているので、ループでマッチすると同時に検索結果用のデータも取得できる。

体感速度は結構速いです。何よりも、環境を選ばないのがメリット。MTが動いていれば動作します。

方法2. 形態素解析で分かち書きして検索インデックスを作る

テーブルに放り込むところは方法1をベースにして、検索対象のテキストを mecab で分ち書きして記号や助詞助動詞、非自立とか不要そうなものを除いてデータベースに入れる。テーブルには単語とその出現回数、エントリーのID等や更新日(無駄なインデクシングを避けるため)を入れておく。

例えばMT4インストール後に自動的にできるエントリーを分かち書きして不要なものを除いた結果はこんな感じ。

Movable Type 4 0 ようこそ この ブログ 記事 Movable Type 4 インストール 完了 時 システム 自動的 作成 ブログ 記事 新しく MT 4 管理 画面 早速 ブログ 更新

インデクシングする時は英文字は小文字にする(MySQL環境だとMTのPerl APIから検索する時に区別してくれないようなので、数があわなくなる)。

各ワードと出現回数はこんな感じになる。

出現回数
mt1
記事3
システム2
インストール2
ブログ4
作成1
完了2
画面1
type2
自動的1
movable2
更新1
管理1
新しく1
この2
早速1
43

これに、更新日とかオブジェクト(エントリーのIDとか)を一緒に保存。こうしておけばマッチするエントリーの数は


my $match = Itasenpara::Itasenpara->count( { blog_id => $blog_id ,
                                             keyword => $query } );

で得られるし、トータル数を得ておいてからオフセットとリミットを指定して検索できるから必要な数だけロードしてあとはページ送りを実装してやることができるよね。

* Object名はItasenpara(イタセンパラ) にした! Namazuにインスパイアされて!?


my @entries = MT::Entry->load( blog_id => $blog_id, {
    'join' => [ 'Itasenpara::Itasenpara', 'object_id',
    { keyword => $query },
    { 'sort' => 'word_count',
    direction => 'descend',
    unique => 1,
    offset => $offset,
    limit => $limit, } ]
});

マッチした数等を表示

ページ送りの実装

もちろんいいことばかりじゃないけど、メリットは単語の出現回数順に表示できるところと高速なところ。デメリットは再構築に時間がかかるところ。但し一回全再構築してしまえば更新日付をチェックしてインデクシング不要ならスキップするようにしたのでまぁ高速な検索のトレードオフというか、今気づいたけどそれこそインデクシングはバックグラウンド処理ですればいいんだ、そうだよね、きっと。

あとは複数ワードのAND検索とかOR検索だけど、素直にSQL書いた方が速いような気がしてます。ってか、もうちょっとスピード出るかと思った...

mecabをインストールする時点でHyper Estraierのパターンと同じく導入に条件が入る。だからこそ「方法1. mt-searchと同じくループで回してマッチング」のような方法もあわせて選択できるようにしておくのがいいかな、と。Namazuだったらインストール済みサーバーも多いんだけど、UTFのことがあってインデクシング用プラグインとか書く気が起こらないんだよなぁ。


追記: 結論としては、2の方法でインデックスを作成しておいてPHP/Perl(FastCGI)で検索、という方向が良いように思う(分かち書きが無理な場合は1の方法+PHP検索)。っていうかさっきはじめてPHP対応のMTプラグイン書いてみて、何とかいけそうだなと思ったので。

カテゴリー: MovableType

2007年09月26日

「検索結果テンプレート」の修正でMTの検索結果表示にどの程度の効果があるか?

サーバーへの負荷もさるところながら、「利用する人のストレスのことも考えると検索結果が表示されるまでにどのくらいなら待てるものなのだろう」などと考えながらMTの検索を独自に実装しようと思って昨日のエントリー (MTからデータベースへのクエリの発行回数を減らす (mt-search.cgiを例にとって)。) を書いていたのだが、昨日のエントリーではMySQLのログ見ただけだったので実際に検証してみた((o)さんからツッコミもあったことだし)。えーっと、ちなみに数字は「再構築」に要した時間。検索に要した時間ではないので。

このブログのエントリーをエクスポートして、ほぼデフォルト状態のMT4にインポート。

Time::Hiresモジュールをインストール、ぴろりさんのMTStopWatchを入れてキーワード「MT」で検索して計測。

ちなみにキーワード「MT」だと約380件のエントリーのうち、(MaxResultsを設定しない場合) 100件強がマッチする。

MaxResultsを20, 40, 80にそれぞれ設定して以下の3タイプのテンプレートで検索実行

  1. 昨日のエントリーで紹介した、タイトル+リンクのシンプルな検索結果。
  2. 「ブログ記事のメタデータ」モジュールのみ外した状態。つまりコメント数やトラックバック数だけが出ない。あとはデフォルトテンプレートのまま。
  3. デフォルトの「検索結果」テンプレートそのまま。

10回実行して平均値を算出。単位は「秒」。数字自体は環境に大きく依存するので違い (差) に着目。

MaxResults 20
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1150.1480.418
20.1070.1560.353
30.1090.1530.351
40.1080.1490.352
50.1120.1460.361
60.1190.1570.36
70.1090.1560.352
80.1150.1550.361
90.1120.1580.355
100.1060.1580.362
平均0.1110.1540.363

MaxResults 40
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1270.2120.660
20.1260.2010.601
30.1320.2040.626
40.1310.2060.617
50.1280.2000.609
60.1320.2070.607
70.1270.2000.605
80.1270.2010.610
90.1310.1980.610
100.1260.2100.620
平均0.1290.2040.617

MaxResult 80
テンプレートタイトルと
リンクのみ
メタ情報なしデフォルト
10.1770.3171.276
20.1670.3851.145
30.1870.3191.143
40.1730.3191.412
50.1750.3191.266
60.1790.3221.148
70.1690.3331.139
80.1660.3181.135
90.1660.3261.142
100.1690.3311.142
平均0.1730.3291.195

もちろん処理全体に占める「再構築」時間の比率にもよるだろうが、この位差が出るのであれば「下手な最適化」でもないと思うけどなぁ。もちろん検索結果の上限値を設定すること自体に異論はないですけど。

*一応汎用的で高速な検索については現在作成中。

カテゴリー: MovableType

2007年09月25日

MTからデータベースへのクエリの発行回数を減らす (mt-search.cgiを例にとって)。

SQLを意識せずにプログラミングできるのが僕がMTを好きな理由の一つであるけれども。

たまにはMTがどんなクエリを発行しているか見てみよう。

MySQLを起動、mt-search.cgiで検索して、MySQLのログを覗いてみる。行数は起動の際のログも含めた行数。

MySQLのログはMAMPの場合、/Applications/MAMP/bin/startMysql.sh に


--log=/Applications/MAMP/logs/mysql_log

とか追加すればログが保存されるようになる。

MT4デフォルトの「検索結果」テンプレートだと、

  • 1件がマッチするキーワードでの検索: ログは122行(41クエリ)。
  • 100件がマッチするキーワードでの検索:ログは1310行!(437クエリ!)。←何ということでしょう!?

CGIの起動がネックだとか、LIKE検索せずにPerlのマッチングだけでやているから遅いとか色々と各所で指摘はされているけれども、SQLのクエリーの数だけでも相当なものだ(特にヒット数が多い場合)。

次に、「検索結果」テンプレートの「ブログ記事の概要」モジュールのところを削除して、


<p><a href="<MTEntryPermalink>"><MTEntryTitle></a></p>

のようにタイトル部分がリンクするようなシンプルな検索結果が表示されるようにする。

  • 1件がマッチするキーワードでの検索: ログは98行(33クエリ)。
  • 100件がマッチするキーワードでの検索:ログは98行(33クエリ!)。←何ということでしょう!?

これだけ差があるとCGIの起動とかPerlのマッチング云々以前に、DBが高速でない場合には明らかなレスポンスの差につながると思われる。さて、この差はなんだろう?

アクセスするテーブルが多い程クエリは増える。

犯人はコイツ↓

ブログ記事のメタデータ

MTのデータベースの構造を見てみた人なら知っていると思うけど、「コメント」や「トラックバック」、「カテゴリ」といった情報は mt_entryテーブルとは別のテーブルになっている。特に「トラックバック」や「カテゴリ」はそれぞれ mt_trackback & mt_tbping, mt_placement & mt_category というように2つのテーブルにアクセスしないといけない。あと「タグ」もそう。

よって、デフォルトの「検索結果」テンプレートにおいてマッチ数が多いときにログ(クエリ) を膨らませているのは、この「トラックバック」と「コメント」である。

もちろん、検索に限らず例えばダイナミックパブリッシングにおける一覧ページ系においてはできるだけ複数のテーブルを参照しないようなテンプレートの作り方をすれば少なくともDBへ発行するクエリの数は減る。エントリー(ウェブページ)であれば、概要欄やキーワード欄、追記欄等は同一のテーブル内。だから、記事のメタ情報について「タグ」や「カテゴリー」を利用しているけど、エントリーの概要欄やキーワード欄、追記欄を利用していない、という場合はこれらのフィールドをできるだけ活用して他のテーブルにクエリを投げる回数を減らしてやるとちょっとだけ幸せになれるかも。

もちろん、テンプレートのメンテナンス性とか管理画面のユーザビリティ的にとかそのあたりとトレードオフになる場合もあるけれど、MTのテンプレートを仕事で書く人は覚えておくべき基本の一つかもね。

カテゴリー: MovableType

2007年09月24日

イマドキノワカモノ、介護福祉、ウェブアクセシビリティ、同窓会の役割。

「介護福祉」を学ぶ学校の取材に行ってきた。

視覚障害者を誘導? するときは、自分の右腕を左手でつかんでもらって左側一歩手前に位置して言葉をかけながら一緒に歩く。

なぜなら右手で杖を持っている人が多いので。だから利き腕が逆の人だったら反対に右側一歩手前に位置するのだ。

アイマスクをして歩いてみると、いかに「段差」が鬱陶しいか良くわかる。

話をした彼女・彼らの多くが身近な体験をきっかけにして進路を選択している。

「両親が共働きで、祖父母に可愛がってもらった」そして「祖父母が体調を崩してケアが必要になった」、とか、「過疎化で高齢者が多いところで育った(で、近所のじいちゃんばぁちゃんに可愛がってもらって、何か恩返しがしたい)」とか。皆がハキハキと、しっかりいた口調で語ってくれて少々驚いた。自分の学生時代のなんと目的意識の無くいい加減だったことよ。

皆、しっかりと挨拶するし「イマドキノワカモノ」って言葉のイメージが反転した一日だった。

1回生の夏、介護福祉の実習にはじめて行く段階で、必ず何人かは音を上げるそうだ。先生が巡回指導に行くと先生の顔を見て泣き出す人も多いらしい。ただ、2年生になると顔つきが変わってくる(取材に行ったのは短期大学)。1回生の夏をこえるのが一つのヤマなのだそうだ。何かそのあたりは話を聞いてよく理解できた。

介護福祉の仕事は人材不足。資格や就職のことを考えて進学してくる人たちが多い。地方自治体が奨学金とか色々整備しているが、むしろ必要なのはそうやって「泣ける」場なのかもしれない。学校だったら実習から戻れば仲間も先生もいる。一旦社会に出ればそういった場は殆どなくなってしまう。

介護福祉を学ぶ学校がそういう役割を果たせればといいのかな、と思った。介護福祉に限らないけど、社会に出れば辛いことやしんどいことも多いだろう。同窓会ってのは単なる思い出を肴に酒を飲む会じゃないんじゃないかな、ということを何となく考えた。

少人数であるが故、みんな仲が良くて明るい(少なくとも僕が感じた限りはそう感じたし、多くの学生たちの言葉からもそういった言葉が発せられたし)。「学校」にこそそういう役割が果たせるのではないだろうか。

「全入時代」である。大学や短大の価値ってのは、そんなところにも見いだせるんじゃないか?

転じて、自分の仕事を鑑みるならば、「ウェブアクセシビリティ」を技術的な側面で考えるだけじゃなくて、ましてや「ユーザー」のことを考えるだけにとどまらず、障碍者や高齢者を支援する人たちの目線を含めて考えることが大切なんじゃないかな。そんなことを感じた一日。

カテゴリー: アクセシビリティ, 駄文・雑文

2007年09月22日

Web屋さんの現場的発想のCMSとは?

もちろん商用のCMS製品全てについて知っているわけではないのだが、Web屋の現場で感じることを少し。

「オーサー」の自由度を増すとサイトは崩れて行く

「オーサー」即ちCMSに情報を登録する「発信者」のこと。Movable Type(主にバージョン3系の話)をCMSとして使っていただくと必ずといっていいくらい「表は簡単に貼付けられないの?」とか「画像貼ったり文字に色付けたりしたい」とかいう話が出る。そして、JavaScriptベースのWYSIWYGエディタを組み込んだり、ということになって「ほらこうすると"MS Word感覚"で更新できますよ」みたいなことに落ちつく。

"WYSIWYG"は諸刃の剣

ところが、"MS Word感覚"ってのがくせ者で、実はMS Wordで(特に見栄え面で)センスの良い文章を作成できる人って少ないのです。だから、デザインの自由度をあげると殆どのケースでサイトの統一感は失われていき、せっかくCMS導入してリニューアルしたのに...ってことになりがちだ。

かといって、「WYSIWYGは使えません」だと、「自由度低すぎ」「これも出来ないの?」「あれも出来ないんだ...」という評価になるんだ。

「不自由」と「自由」の落とし所がポイント

そこで、実際は「プロの作成したできるだけ多くのパターンから選択してからページ制作を始めてもらう」「選択したパターンはあまり変えることはできない」というところにだいたい落ち着く。これまでは、MT::App:CMSのテンプレートをある程度簡単にカスタマイズしたりしていたのだが、独自のテンプレートタグを定義して(例:「CMS_Add_Field type=textarea height=200」みたいなタグを書いて)フィールドを増やしていた。

ただ、これではやはりクライアントに渡した後はお手上げになるし、覚えることばかり増えて大変だ。

Movable Type4でどこまで出来るか

MT4からは「ウェブページ」が作れるとか「アップロードしたファイルが管理できる」とか「ブログをまたがってページを出力できる」とか色々なフィーチャーがあって「CMS」狙ってるな!? って匂いはすごくするんだけど、やっぱりまだWeb屋さんの現場ではクライアントニーズにあわせたCMS自体のカスタマイズは必要だ。さもなければ不便に目をつぶって(現実路線としてお金もそんなにかけられないし) 「運用でカバー」ということになるだろう。

そこで、管理画面のGUI操作で「本当の意味で」簡単にカスタマイズが出来るものを作ろうとしていて、まだ限定的ではあるが、Movable Type4「CMS化」プロジェクトを進行中で、エントリー編集画面のカスタマイズあたりはほぼ完成した。

提供する側には「自由度が高くてオーサーのニーズに応えることが容易にできる」、一方で「オーサーは自由度は限定的だが、やりたいことは予め容易された手順で簡単にできる」ものを狙っている。

エントリー(ページ)の編集画面に一行テキスト、複数行テキストエリア、ラジオボタン、チェックボックス、セレクトメニュー、ファイル添付の各フィールドを自由に配置できる。アップロードしたファイルはエントリー(ページ)と関連づいていて、エントリー(ページ)を削除すると同時に削除される。添付したファイルはMTのassetテーブルにも格納される。

ちなみに、このサンプルのテンプレートタグの該当部分はこんな感じになっている。フィールドを増やしたり減らしたりしてもそれなりに対応できるからこんな風に自由にフィールドを増減しながらエントリー(ページ)を作ることも可能。


<MTExtFields>
    <MTIfExtFieldType type="text">
        <h2 style="font-size:120%;font-weight:bold"><$MTExtFieldText$></h2>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="textarea">
        <p><$MTExtFieldText$></p>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="file">
        <MTIfExtFieldNonEmpty>
            <MTIfExtFieldTypeImage>
                <p><img src="<$MTExtFieldFilePath$>" alt="<$MTExtFieldAlt$>" width="<$MTExtFieldImageWidth$>" height="<$MTExtFieldImageHeight$>" /></p>
            <MTElse>
                <p>Download:<a href="<$MTExtFieldFilePath$>"><$MTExtFieldAlt$></a></p>
            </MTElse>
            </MTIfExtFieldTypeImage>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="radio">
        <MTIfExtFieldNonEmpty>
            <p><$MTExtFieldText$></p>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="select">
        <MTIfExtFieldNonEmpty>
            <p><$MTExtFieldText$></p>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
    <MTIfExtFieldType type="checkbox">
        <MTIfExtFieldNonEmpty>
            <p>チェックボックスにチェックが入っています</p>
        <MTElse>
            <p>チェックボックスにチェックが入っていません</p>
        </MTElse>
        </MTIfExtFieldNonEmpty>
    </MTIfExtFieldType>
</MTExtFields>

とはいえ、自由過ぎると色々な問題が出てくるので...

フィールドをカスタマイズした編集画面は「エントリー(ページ)テンプレート」として保存できるので、「オーサー」は予めカスタマイズされたテンプレートを選択してページを作るだけ。現状「テンプレート」編集権限の無い人には、フィールドの増減や並び替えは出来なくしてある。

CMSが機械的に吸収出来る部分は吸収して「オーサー」に覚えてもらうことを減らすことも重要

せっかくCMSを入れても、結局「テキスト入力時には、アクセシビリティにも考慮して以下のことに気をつけましょう」なんてやってるケースが殆どかと思うけど、英数字の全角 or 半角とかそんな統一くらいはCMSでやって欲しいってのが本音な筈だよな。

以下のようなプラグインを使うことで、このあたりも入力する人にできるだけ考えさせないようにすることも重要(MT4では画像アップロード時のalt欄のところが動かないけれどテキストフィルターは正常に動作する)。

いずれにしても、現状でこのようなMT4ベースのCMSカスタマイズ案件を進めていて顧客の要望も(もちろん現場のスタッフの要望も)聞きながらつくっているので、「現場で出てくる不満」をクリアするものに仕上がってきている実感はあるけれども、まだ欲しいものが色々あるので引き続き制作を進めて行きたい。

カテゴリー: Web制作・ビジネス

2007年09月21日

利用規約なんて飾りです。偉い人にはそれが分からんのです。

嫌な思いをするのは結局中の人なんだよな。先に謝っておくよ。ごめんなさい(でも社内のことは社内で片付けてください)。

まずは前振り。「引用」と「肖像権」とについて。

色々なサイトのスクリーンショットを 自分のサイトで使用すると法的に問題があるのでしょうか? 私個人としては常識の範囲内なら良いとは思うのですが。 良いと思う、悪い.. - 人力検索はてな

他人のサイトの画像をそのサイトの紹介や批評にする際に自分のページに掲示することは、引用といって法的に認められた権利です。

ふむふむ。ってかそれは知っている。

確実にアウトとなるのはそのHPにタレントの写真が用いられていた場合です。その場合は肖像権の侵害となり、訴えられることになるでしょう。

「確実にアウトになるんだ?」まぁその辺りは当事者が考えなよ。ってか、確実にアウトだったらmalaが可哀想だろ。誰か全力で反論してやれよ。

*俺自身は「確実にアウト」になると考えるわけではなくて、それは「権利」を持っている側が訴えることが前提となるわけだから、今回はおそらくそうはならないだろう(火種が大きくならない限りは...てかそれほどの影響もあるまい)。いずれにしてもかなりグレーだと考えるわけだよ。憲法読めとか引用知らんのかとかありがとうございます(大きなお世話だけどさ)。

たださぁ、「だからスクリーンショットも張った。」って本人も言ってるじゃん。覚悟の上で言ってるんだろ? 周りが察してやれよ。

ここから本題。NOWAの利用規約を見てみような。 (利用規約は飾りじゃないだろう?)。(強調は俺ね)

第6条 (責任及び注意義務について)

利用者は、自己の責任に基づき本サービスを利用するものとし、利用者が公開するブログについて、全ての責任を負うものとします。また、利用者は弊社に対し、他人の著作物を使用したことなどが原因で紛争、損害賠償の請求などが起こった場合の損害、責任について一切を免責するものとします。(後略)

第7条 (禁止行為)

利用者の本サービスの利用にあたって弊社は以下の行為を禁止します。利用者がこれらの禁止行為を行った場合、弊社は当該利用者のブログを削除し、以後の利用を禁止する場合があり、それによって利用者が何らかの損害等を被ったとしても、一切の責任を追わないものとします。

・本規約に反する行為
・法律・規則・条令等の制定法に反する行為
(中略)
・利用者以外の自然人・法人・団体・組織等の第三者の名誉や社会的信用を毀損したり、不快感や精神的な損害を与える行為
(中略)
・利用者以外の自然人・法人・団体・組織等の第三者の所有する知的所有権を侵害する行為や、著作権の侵害を誘発する行為
・その他弊社が不適切であると判断する行為

サービス提供側が責任を負わないと書くのはもちろんよく分かる。会社が云々とか書いてすいませんでした。

なので、法律云々は置いておいて (最終的には裁判でもしてみなければ結論は出ないかもしれないが、タレント事務所とサービス提供者がどんな契約をしているかが重要だろうし、それを知る術がないので置いておく、という意味)、「これは完全にエンジニアが無知で無能でクズ。アホでバカ。低脳でワーキングプア。」ってのが 「利用者以外の自然人・法人・団体・組織等の第三者の名誉や社会的信用を毀損したり、不快感や精神的な損害を与える行為」にあたるかどうかってのと「第三者の所有する知的所有権を侵害する行為や、著作権の侵害を誘発する行為」の2点についてどう考えるべきかについてサービス提供者の見解が聞いてみたい。って言うだけ無駄だろうがね。

規約が飾りだったら規約なんか書かなくていいんじゃね? そんなWebサービスだったら辞めちゃえば?

*もちろん、エントリーを書いた時点でこのあたりを熟読して論理的に考察していたわけでないことは認めるよ。それが気に触ったのならごめんなさいね。

ついでだからアメブロの利用規約も見てみよう。

第11条(知的財産権等)
本サービスを構成する文章、画像、プログラムその他のデータ等についての一切の権利(所有権、知的財産権、肖像権、パブリシティー権等)は、会員自身が作成したものを除き、弊社又は当該権利を有する第三者に帰属しています。
会員は、会員自身が作成した著作物を本サービスを通じて掲載した場合、弊社が宣伝告知等に利用することを許諾するものとします。また、かかる使用に際して、当該会員は著作者人格権を行使しないものとします。

なるほど、著作者人格権は行使できない、と。但しこの利用規約をベースにタレント事務所と契約していないだろうし、タレント事務所等とは別の何らかの契約を交わしているだろうよ。アメブロの「タレントブログ」にどの程度の縛りがあるかは知らないが、メディアにタレント使う時には制限事項や契約期間とかの縛りとか細かに書いた契約書交わすのが普通だよね。

第12条(禁止事項)
全利用者は、本サービスの利用に当たって、以下各号の行為又はそのおそれがある行為を行ってはならないものとします。
(1)弊社又は第三者の所有権、著作権を含む一切の知的財産権、肖像権、パブリシティー権等の正当な権利を侵害する行為
(中略)
(3)公序良俗に反する行為
(4)法律、法令等に違反する行為
(中略)
(7)サービスの信用を失墜、毀損させる行為
(後略)

「全利用者」の定義としては

「全利用者」---弊社が情報提供するサービスを利用する全ての者

とあるので、アメブロのサービスを利用してブログを書く者に加えて、閲覧する者、引用する者、又二次的に情報を加工若しくは利用する者(WebサービスとしてのRSSリーダーとか) 等が含まれると考えるべきなのだろう。

考えておくべき内容としては「サービスの信用を失墜、毀損させる行為」というあたりだろうよ。CAは黙ってんの? 大人だねぇ。CAが大人で良かったよな。

最後に、これもまたついでに (これがまぁ一番どうでもいい話題だけどね) はてなの利用規約。

第6条(禁止事項)
2.ユーザーは、本サービスを利用するに際し、以下のような社会的に不適切な行為を行ってはなりません。
(中略)
4.迷惑行為、嫌がらせ行為、誹謗中傷行為、正当な権利なく他者に精神的被害・経済的被害を与える行為

NOWAやアメブロは分かりやすかったが...(守られてるかどうかは全く別だが)「正当な権利」の定義が知りたいと思うが「正当な権利があれば他者に精神的被害・経済的被害を与える行為は可」と読めたりしてこのあたりは現状を踏まえて敢えてこうしているのだろうか? だったらこれ書いた人に拍手。いや、良い意味で(「はてな」ってそのあたり考えるとすげぇ会社だよ、いやマジで)。

まぁ、あんたがたの会社にはこういった規約を真面目に考えて作ってる人がいるわけだ(虚しい仕事だろうがね)。

もう一度言おう。意味が無いなら消しちゃえば?

ハッカー格好いいから、スーツの意見なんか無視しちゃえばいいし、エンジニアに恥をかかせる会社もこき下ろせばいいってか? まぁ好きなようにやればいいじゃん。良い意味で。

最後にさぁ、こんなの作ってらっしゃるようですがねここの利用規約も読んでみようよ。

他の利用者又は第三者、若しくはライブドアを差別若しくは誹謗中傷し、又は名誉若しくは信用を傷つける行為

他の利用者又は第三者、若しくはライブドアの財産、プライバシー、肖像権若しくはパブリシティ権を侵害する行為、又は侵害するおそれのある行為

ライブドアは社員が自社サービスの利用規約を守れなくても放置する会社ですか?

カテゴリー: 駄文・雑文

2007年09月20日

エントリー投稿時にファイルも一緒にアップしたいよね、やっぱり。

制作途中のものをこうやってアップして晒すってのはどうなのよって気もしないでもないけど、これもまぁマーケティングの一つの方法だよな。あと、何作ってるよ、いつくらいにリリースできそうだよってのを共有すると別の人が同じもの作らなくて良くなるからユーザーコミュニティにとっても良いことだろうしね。

ExtFieldsの画像添付

例のごとくQuickTimeムービーにしてみた。

ブログ(Movable Type) の投稿インターフェイスの中で、ファイルのアップロードがやっぱり面倒だという声が(主に社内で)出ていたので、汎用的に実装できるように制作中のExtFieldsプラグインに「input type=file」のフィールドも自由に追加できるようにしてみた。

同名ファイルが存在していた時の上書き確認とか同時にAssetテーブルにデータを保存するとか upload_file コールバックをちゃんと呼び出すとか削除はどうすんの、とかこいつはちょっとホネのある作業になりそうな気配だけど何とか今月中には完成させたい。

あと、「フィールドの並べ替えができると便利ですかねぇ」という声もあったので実装してみたよ。エントリー投稿画面をクライアントニーズにあわせて簡単に変更できるから、CMSのカスタマイズがめっちゃ簡単になる(予定!)。

でもって、こっちが並び替えのムービー。

カテゴリー: MovableType

2007年09月15日

MTのエントリープレビュー→Another HTML Lintで文法チェック。

MT4用, プレビュー画面からAnother HTML LintへHTMLソースをポストするボタンを追加するプラグイン。

サイトの品質を確保するための仕組みはワークフローに組み込まなければならないってのは感覚としては理解していても現実的に中々難しいケースもあるでしょう。制作過程ではきちんとできていたものが納品後にだんだんとぐちゃぐちゃに...という経験ないですか? 制作者の皆様。

ということで、Movable Type4の「確認(プレビュー)」画面からAnother HTML Lintへポストして文法チェックを簡単に出来るプラグインを作ってみました。

プレビュー画面に追加されたボタン

プラグインの設定

pluginsフォルダにフォルダごとアップロードするだけで特に設定は必要ありません。Another HTML Lint のcgiのURLを変更する場合のみプラグイン設定画面からアドレスを登録してください (初期設定ではプライマリサイトのゲートウェイのアドレスに設定されています) 。

プラグイン設定画面

尚、Another HTML Lint はチェック項目について細かな設定ができるようになっていますが、このプラグインでは[Lite]バージョンのフォームのデフォルト設定と同じになっています。変更する場合はプラグインのソースを修正してください。

ご利用について

パブリックドメイン。利用に制限は設けません。

ちなみにAnother HTML Lintは非営利目的の利用に限りフリーです。うちの会社では『「Web屋さん」の利用』にあたるので利用料を払って使用しています。

ダウンロード

カテゴリー: MovableTypeプラグイン

続きを読む "MTのエントリープレビュー→Another HTML Lintで文法チェック。" »

2007年09月14日

MT4でログインユーザー限定領域を設定するプラグイン。

MT4用。ログインユーザー限定ページを設定するプラグイン。

例のごとく? ムービーにしました。

設置方法

前回のエントリーを参考にしてください。

  • htaccess又はhttpd.confでmod_alias又はエラードキュメントを設定する(ここは自動化されていません)
  • mt-confg.cgiに「CookiePath /」を追加(テストのためには一度ブラウザのクッキーを削除する必要あり)
  • プラグインの設置/設定→保存(設定項目は以下の通り)

SimpleAuth設定画面

プラグインの設定

  • ドキュメントルートのパス
  • Apacheでアクセスを制限する拡張子
  • 認証付きページにしたいディレクトリ(改行区切り)
  • Directoryへのアクセスの際に返すファイル(カンマ区切り)
  • 404エラーの時に表示させるファイルのパス

パスはいずれもフルパスで記述します。


制限事項/いけてないところ

すごく簡易的なものです。ムービーの通り画像等のアップロードしたファイルにも対応しています。但し、対応しているのはGIF/PNG/JPEGのみで、その他のフォーマットのファイルではContents-Typeヘッダが正しくセットされません。

また、MTのBootstrap.pm を利用したアプリではpragma no-cacheヘッダが付加されるのでクライアントキャッシュがうまくつかえませんし、大きなファイルを扱うことも考慮していません(Perlスクリプトを経由してファイルのデータが処理されるため、アクセスの多いページには不向きです)。あと、設定がちょっと面倒なところでしょうか。

場合によっては潔くダイナミックパブリッシングにしてそのプログラムの中での対応を考えた方が良いかもしれません。ただ「手っ取りばやく、画像等にもアクセス制限をかけたい」場合には使えると思います。

ご利用について

パブリックドメインとします。完全に無保証ですが利用に制限は設けません。

ダウンロード

カテゴリー: MovableTypeプラグイン

続きを読む "MT4でログインユーザー限定領域を設定するプラグイン。" »

2007年09月13日

MTでログインユーザー限定のページを作る方法。

ログインユーザーだけがページを見られるようにしたいってニーズは結構あるようなので。一例を紹介してみる。

追記 : プラグインにしてみた。

考え方

ダイナミック・パブリッシングであればページを生成してリプライするプログラムの中でログインの有無を設定してやれば良い。静的生成の場合はどうするか?

  • MTのクッキーの有効範囲をサイト全体にする
  • 生成されるファイルの名前の後ろに(例えば) .deny を付けるようにする (アーカイブ・マッピングの設定でも良いし、build_file コールバックに対応したプラグインを書いても良い
  • ユーザー限定ページのディレクトリに対するApacheの設定で.denyへのアクセスを拒否する
  • ユーザー限定ページのディレクトリに対するApacheの設定でmod_rewrite又はNotFoundの設定によってリクエストがプログラムに渡るようにしておく
  • プログラムの中でログインの有無をチェックするようにする
  • 例えば example.html ページが存在しない場合、ログインユーザで且つ example.html.deny が存在すれば example.html.deny の中身を返す

以下、MTが /mt以下に、/authディレクトリ以下をログインユーザー限定ページにしたい場合(ファイルのリネームのところは省略します。build_fileコールバックが呼ばれた時に /authディレクトリ以下だったら.denyを付けてリネームするプラグインを書けば良い)。

/mt/mt-config.cgi


CookiePath /

/auth/.htaccess


<Files ~ "¥.(deny)$">
    Order allow,deny
    Deny from all
</Files>
Options -Indexes +SymLinksIfOwnerMatch
  <IfModule mod_rewrite.c>
  <IfModule mod_dir.c>
    DirectoryIndex index.php index.html index.htm default.htm default.html default.asp
  </IfModule>
  RewriteEngine on
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ /mt/plugins/SimpleAuth/SimpleAuth.cgi [L,QSA]
</IfModule>

<IfModule !mod_rewrite.c>
  ErrorDocument 404 /mt/plugins/SimpleAuth/SimpleAuth.cgi
  ErrorDocument 403 /mt/plugins/SimpleAuth/SimpleAuth.cgi
</IfModule>

/mt/plugins/SimpleAuth/SimpleAuth.cgi



#!/usr/bin/perl -w

use strict;
use lib 'lib';
use lib '../../lib';
use lib '../../extlib';
use MT::Bootstrap App => 'SimpleAuth';

/mt/plugins/SimpleAuth/lib/SimpleAuth.pm


package SimpleAuth;

use strict;
use MT::App;

@SimpleAuth::ISA = qw(MT::App);

sub init_request {
	my $app = shift;
	$app->SUPER::init_request(@_);
	$app->add_methods( auth => ¥&_auth );
	$app->{default_mode} = 'unprotected';
	$app->{requires_login} = 1 unless $app->mode eq 'unprotected';
	$app->add_methods( unprotected => ¥&_unprotected );
	$app;
}

############################################################################## 

#Setting

my $base = '/Applications/MAMP/mt4local2';
my $suffix = '.deny';

##############################################################################

sub _unprotected {
	my $app = shift;
	my $login = $app->login;
	if (defined $login) {
	    return &_auth($app);
	} else {
	    $app->set_header('Status','401 Unauthorized');
	    return 'Requires Login.';
	}
}

sub _auth {
    my $app = shift;
    my $path = $app->param('path') || $ENV{"REDIRECT_URL"};
    $path =~ s/¥.¥.//g;
    my $file = $base.$path.$suffix;
    if (-f $file) {
        open(FH, $file) or die;
        my @data = <FH>;
        #$app->set_header('status', 200);
        $app->send_http_header();
        $app->print(@data);
    } else {
        $app->set_header('Status','404 File Not Found');
        return 'File Not Found.';
    }
}

1;

html以外のファイルを処理する場合は拡張子からContent-Typeを識別して付与してやるとか、ディレクトリへのアクセスだったら /index.html を探すようにするとか、そのあたりの処理は必要ですが、基本的にはこんな感じ。

カテゴリー: MovableType

MTのエントリー編集画面をごにょごにょと...

前回1行テキストとテキストエリアの追加のデモを載せてみたのですが、ラジオボタン,セレクトメニュー,チェックボックスにも対応させてみました。CustomFieldsとかRightFieldsとかもそろそろリリースなのかな? ちなみにプロジェクト名称は「LeftFields」!

ExtFieldsによってカスタマイズされたエントリー編集画面

あと、TemplateSelectorとDuplicateプラグインと組み合わせて「エントリーのテンプレート」を複数登録しておいて、そいつをサムネイル画像を見て選択できると便利かな、と思ってやってみた。

あとは...type="file" に対応させるかどうか迷っている。「プレビュー」の時に一時保存させるとか、プレビュー後のreeditの時に値(ファイルの選択状態)を引き継げないので...Flexだったらできるんだろうか...

「エントリーテンプレート」を「変更できる/出来ない」の権限部分(テンプレート編集権限に対応させる予定)、ExtFieldを「扱える/扱えない」の権限部分(エントリーの編集権限に対応させる予定)をやる予定。

カテゴリー: MovableType

2007年09月11日

MT4でカスタムメニュー, モーダルダイアログの追加。

カスタムメニューとカスタムダイアログを登録してみた。Dialogのところでargsが設定できないっぽいのはちょっと...だけど、別のモードを作ってパラメタ設定してから $appと一緒に別の関数に渡してやればいいのであまり気にしていない (でもダイアログでも args設定できて欲しいと思った)。

というか、以下のページに載っていたそのまんまやってみただけだけど、SNAPZ Pro Xが楽しいので何となくのっけてみてます。

こういった標準的に用意されている拡張方法に沿って開発すると一貫したUIっちゅうもんが保てるのだね。

ちなみにメニューは左からcreate(新規作成), manage(一覧), design(デザイン), prefs(設定/ブログ), tools(ツール/システム)という名前になっている。orderのところでどんな数字を指定するかで表示順を設定できるのだが、このあたりは /Lib/MT/App/CMS.pm を見てください、ということで。


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                menus => {
                    'create:example_dialog' => {
                        label => 'Dialog Sample',
                        dialog => 'select_dialog',
                        order => 99,
                        permission => 'publish_post',
                        view   => "blog",
                    },
                    'manage:example_menu' => {
                        label => 'Menu Sample',
                        mode => 'select_menu',
                        order => 999,
                        args => { foo => 'bar',
                                  bar => 'buzz' },
                        permission => 'publish_post',
                    },
                },
                methods => {
                    select_dialog =>
                        'MT::Plugin::Menu::select_dialog',
                    select_menu =>
                        'MT::Plugin::Menu::select_menu',
                },
            },
        },
    });
}

一応サンプルもあげておきますね。

カテゴリー: MovableType

2007年09月10日

SNAPZ Pro Xでムービーキャプチャして遊ぶ!?

SNAPZProX2.1.1面白い!

Snapz Pro X

何か久しぶりにデスクトップアプリを買った。衝動買い。デスクトップ画面をムービーとしてキャプチャすることができるMacOS X用の高機能キャプチャソフト。ダウンロード販売で税込み8,820円。

オンラインマニュアル作成なんかに良いと思うのだけど、例えばウェブアプリ開発の時のテストとか進捗報告なんかに使えるんじゃないか? っていうか、ブログに掲載するのにキャプチャ貼付けて解説文章打ち込んでって面倒じゃない。

ということでまだ作成中なんだけど、何か面白い感じのものが出来た! とか、あぁやっとここまで出来た、っていう途中段階のものを晒してみるのも面白いんじゃないかと。飽きるまでしばらくこんな感じでのせるかもしれない。

今日のは、この↓プラグインをちょっと根本的に書き換えようと思っていて、インターフェイスとか機能とかをちょこちょこと追加した様子のご紹介。

管理画面でテンプレートのバリエーションを作ってエントリー編集画面で別のテンプレートを選択できるんだけど、テンプレートの名前だけじゃなくてテンプレートのサムネイルを登録できるようにしたら面白いというか使いやすいのではないかと。で、どうせならMT4の「カスタムダイアログ」を使ってみようということで、このあたり(How to Create a Modal Dialog) を参考にしながら実装。

ちょっと重たいです(20MB程あります)

カテゴリー: 駄文・雑文

2007年09月08日

MT4のエントリー投稿画面の入力フィールドを簡単に,無制限に増やせるExtFields。

まだ作成中だけど出来ているところまでのデモムービーをアップしたよ!

ExtFieldsで拡張したエントリーの編集画面

これもまた作成中のものだけど、以下のプラグインあたりと組み合わせて使うことでクライアントの要件に沿ったCMSを簡単に構築できる(ものになる筈)。

カスタマイズした編集画面を「ひな形」的に保存・登録できるから、複数のパターンから好きなものを選んで投稿できるし、各パターン毎に出力するテンプレートを切り替えることもできる。

条件タグなんかで出力条件をカスタマイズすることもできるし、このムービーの例では、textだったらdt、textareaだったらdd にしてループさせるようにテンプレートタグを定義している(だから、その場でフィールドはどんどん増やしていける)。

こんな感じね。


<MTIfExtField>
 <dl>
  <MTExtFields>
  <MTIfExtFieldType type="text">
   <dt style="font-size:120%;font-weight:bold"><p>
  <MTElse>
   <dd style="margin-left:20px"><p>
  </MTElse>
  </MTIfExtFieldType>
   <$MTExtFieldText$>
  <MTIfExtFieldType type="text">
   </p></dt>
  <MTElse>
   </p></dd>
  </MTElse>
  </MTIfExtFieldType>
  </MTExtFields>
 </dl>
</MTIfExtField>

もちろん決め打ち? もできる。


<$MTExtFieldText label="label1"$>

リリースの時期とライセンスは未定だけど、最終的にはMTOS用とMT用のデュアルライセンスとか考えてます。

* いや、MT4、いじりがいがありますよ!


追記:

こんな感じにすると、「名前」で指定したタグで囲まれることになる。例えば「名前」を「h1」とか「blockquote」とかするとそのダグで囲まれるわけだ。


<MTExtFields>
 <<$MTExtFieldlabel$>>
  <$MTExtFieldText$>
 </<$MTExtFieldlabel$>>
</MTExtFields>

カテゴリー: MovableType

2007年09月06日

MTObjectBuilder(MT::Objectのサブクラスを作ってDBのテーブルを簡単に拡張するためのcgi)。

ここ1〜2週間程、怒濤のMTプラグインリリースラッシュ? なわけですが、MTを拡張したりMTベースでウェブアプリケーションを開発するにあたっては、データベースを拡張したいケースが当然出てきます。DBの拡張方法は以下のエントリーでもご紹介していますが、簡単に作れたらいいな、ということでMTObjectBuilderというものを作ってみました。

関連するエントリー

MTObjectBuilder

フォームへ必要事項の入力

MT::Objectのサブクラス作成画面

  • プラグイン名を入力
  • 拡張クラス名を入力
  • add clumn をクリックしてカラムを追加
  • カラム名を入力, Typeを選択, 必要であればIndexにチェック
  • 親クラス(指定があれば)を入力(例: Child of MT::Entry)
  • Createをクリック

モジュールとプラグインのソースが生成される

生成結果

ファイル(2つ)を作成して保存

  • 生成されたソースをエディタにペーストしてそれぞれをファイルとして保存

ファイルとして保存

MTへアクセスしてデータベースをアップグレード

  • MTにアクセスするとUpgraderが起動する

アップグレード画面

アップグレード完了

正しく生成されていることを確認

PHPMyAdminで確認

カテゴリー: MovableType

台風から逃げる。

新700系

喫煙室

連結器?

台風やりすごしてから帰るか迷ったのだが、何だかきっかけがあったので今から大阪へ帰るとする。

二度目なので嬉しがって車内で写真とりまくったりしない(してるやん)。

カテゴリー: 駄文・雑文

どんなに技術があろうと出来る人であろうと駄目なものは駄目、って誰かが言わないと。

例えばamebloのフィードが酷かろうがどうだろうがCSS Niteがむかつく存在だろうがどうだろうが言葉を選ばないものは駄目。駄目なものは駄目。違うか!?

少なくともあなたの発言はライ○ドアだったりサイ○○ズ○○の人の発言だったりすることは明らかになっている程度「実名」での発言なわけで。まぁ僕なんかは「お呼びではない」ので多くは語らぬけどね。この手の発言を放置する会社って一体何なんだ?

# 個人的には楽しんでるけどね。

あとさ、タレントの写真を含んだキャプチャがページに貼付けられているってどうなのさ。肖像権的にとか契約的にこれは問題ないとの認識ですかどうですか偉い人。

会社は何も言わないんだ。そうだね、自由って素晴しい!

See also...

まぁ、親父2.0なので、放っておいてくれ。

カテゴリー: 駄文・雑文

2007年09月05日

「ブログ記事」「ウェブページ」の「複製」を行うMT Duplicate プラグイン。

エントリーの「複製」を行うMT4専用プラグイン

Movable Type 4で「ブログ記事」「ウェブページ」の「複製」を可能にします。

プラグインについて

未だに「エントリー」と言った方が通りが良いと思いますが「ブログ記事」「ウェブページ」を複製できるようにするプラグインです。

CMSの設計と運用方針次第ですが、このプラグインが本領を発揮するのはカスタムフィールド等を使って投稿画面をカスタマイズしたり、拙作の「TemplateSelector 」のようなテンプレートを切り替えたりするカスタマイズを施している時かと思います。

このブログでも再三取り上げた通り、MT4をCMSとして拡張するためのプロジェクトを現在進行中で、そのプロセスで作成した一つのプラグインです。

関連エントリー

ライセンス

クリエイティブ・コモンズ・ライセンス (表示-非営利-継承 2.5)

※業務でのご利用はご相談ください。公開しているすべてのプラグインのライセンスについてはMTOSが正式リリースされた折には見直したいと思います。

利用方法

プラグインを利用するだけで特に意識することなく直感的に利用できると思います。

プラグインをインストールすると、下記のように「ブログ記事」「ウェブページ」の一覧に「複製」ボタンが表示されます。

ブログ記事の一覧に追加されたボタン

また、各エントリー(「ブログ記事」「ウェブページ」)の編集画面の下部のボタンにも「複製」ボタンが追加されます。

エントリー編集画面に追加されたボタン

「複製」ボタンをクリックして編集画面に移動された段階で、各フィールドには複製元のエントリーの各値が入っています(但し、タイトル部分を見ていただければ分かる通り、この段階では「ブログ記事(または「ウェブページ」)の作成」扱いとなっています(この段階ではまだエントリーは保存されていません)。

エントリー編集画面のタイトル部分

ダウンロード

カテゴリー: MovableTypeプラグイン

続きを読む "「ブログ記事」「ウェブページ」の「複製」を行うMT Duplicate プラグイン。" »