*[hatefu:labs.yaneu.com/20090329/] blogのclient-side rendering 私は95年ごろに自分のホームページを作っていたころは、htmlを手打ちしていた。そのあと、IBMのホームページビルダーを使うようになった。いま考えてみるに、あれはあまり使い勝手の良いものではなかった。 それに比べるとブログは便利で、思いついたときに思いついたことを気軽に投稿できる。画像のアップロードは簡単だし、RSSだって勝手に配信してくれる。 これだけの仕組みを自分で構築するのはかなり大変で、いまさらホームページビルダーでもないだろうし、htmlタグの直打ちの時代でもないだろう。 大手ブログを利用にせずに、自分のサイトに簡単に記事を投稿できる仕組みはないものかと考えて、今回、やってみようと思ったのが、JavaScriptによる本文の自動整形である。 * JavaScriptによる本文の自動整形の例 このページ自体のソースを見ていただきたい。 本文全体がpreタグで囲まれていて、その中には一切のhtmlタグが出てきていないことがわかるだろう。 お察しの通り、このページは、JavaScriptを使ってすべてを整形している。 この手法を、いま、'client-side rendering'と呼ぶことにする。 従来のブログシステムでは、サーバー側で整形する必要があった。近年、プロセッサのmany core化が進んではいるが、CPU負荷が高く、ネットワークのインフラのほうに余裕があるなら、このようにクライアントサイドで整形させるという選択肢があるのではないかと思う。 また、ブログシステムとしての応用例ばかりではなく、一般ユーザーにしてもhtmlタグを直打ちしなくて済むので、ブログに書く程度の手間で本文が書けるというのも魅力的だ。 * スクリプトの機能説明 ・「id:yaneurao、始まったな!!」などとid記法が使える。 ・「http://d.hatena.ne.jp/yaneurao/」のようにhttpで書かれていたらそのURLは自動的にハイパーリンク ・ ソースコードは >> と << で囲めば表示できる。 例) >> function cssFloat(element , style) { // IEは'styleFloat',Firefox,Safariは'cssFloat',Operaはどちらも大丈夫 var styleFloat = (element.style.styleFloat === undefined ? 'cssFloat' : 'styleFloat') element.style[styleFloat] = style; } << ・'*' とか '**' で開始すると段落見出しになり、それらに対して自動的にアンカーが振られる。 例) * 段落1 ** 小段落1-1 ** 小段落1-2 * 段落2 ** 小段落2-1 ** 小段落2-2 ・画像の貼り付け '[ img:画像ファイル名 ]' と書けばそこに画像を貼り付けることが出来る。 ・はてふ連携 この本文に対して、はてふを貼り付けることが出来る。 関連) はてふ --- はてな付箋リリースしました http://labs.yaneu.com/20090309/ ・その他 整形しているメイン部分のソースコードは60行程度しかない。ソースコードはをこのまま使うのではなく自分の好きなように改造して使うことで、自分だけの整形システムになる。 * 今回のスクリプト 今回のスクリプト http://labs.yaneu.com/blogparts/autoblog.js 自由に変更して使っていただいて構わない。 JavaScriptファイルから、他のJavaScriptファイルをincludeするのが面倒だったので、はてふスクリプトで利用している jkl-dumper.js がソースの末尾につけてあるが、こちらは元のファイルの配布条件/利用条件に準拠するものとする。 * スクリプトの技術的解説 私はJavaScriptの動作検証はまず、IE7とChromeでやることにしている。この2つのブラウザは特に差が大きく、この2つのブラウザで動けば他のブラウザではたいていそのまま動くからである。 以下、IE7とChromeとの動作の違いを書いていく。 ** html中に本文を書く理由 今回のようなシステムの場合、本文自体を外部ファイルにしてしまうことも出来なくはないのだが、そうするとSEO的に損をする。 やはり本文はhtml中に正しく埋め込まれているべきだろう。 ** 本文をpreタグで囲む理由 スクリプト側から本文を拾ってくる必要があり、それをpreタグで囲っている理由だが、preタグで囲まない場合、IE7では元テキストの改行を自動的に潰して(除去して)保持しているため、innerHTMLを取得しても元テキストの改行が拾えないのである。それに対してChromeではpreタグで囲んでいなくとも比較的素直に元テキストをinnerHTMLに格納している。 ** preタグで囲んだ場合のinnerHTML では、preタグで囲んだ場合、そのinnerHTMLはどうなるのか? IE7だとpreタグ内の改行は"\r\n"として保持しているが、Chromeだと'\n'としてしか保持していない。そこで最初に'\r'を除去して、そのあと'\n'でsplitしている。 また、IE7だとpreタグ自体の'pre'という文字を勝手に大文字化してinnerHTMLに保持していたり、preタグ内の '>' を 勝手に'>'と置き換えて保持していたりと、原文をそのままの形で保持しておくという姿勢が見られない。 それに対してChromeは、改行コードの'\r'を除去している以外は、比較的忠実に原文を保持している。DOMの規格上、innerHTMLに格納するときに元テキストをどの程度改竄して良いことになっているのかは私は知らないが、IE7のそれはかなりひどいと思う。 ** html anchorについて 'html://XXX/index.html#123"のようにアンカーが指定された場合、ページが読み込まれた時点でそこにジャンプしようとするブラウザが多いのだが、このアンカーはJavaScriptで生成しているため、ページ読み込み完了時点ではまだそこにジャンプできない。 ブラウザは、JavaScriptのonLoadハンドラの実行が終わってからアンカーにジャンプするように実装されるべきだと思うのだが…。 * まとめ 近年、グラフやTeXのような数式自体もJavaScriptで描画してしまおうという動きがあり、ますますclient-side renderingの重要性は高まるばかりである。 今回のようなスクリプト(今回のものはあくまでコンセプトデモだが)が、ブログシステムなどに利用されることを願う。 * 関連記事 Pure JavaScript Template Engine http://alpha.mixi.co.jp/blog/?p=335 TiddlyWiki http://www.tiddlywiki.com/ * 更新履歴 2010.10.18 コードのキーワードハイライト処理がいろいろおかしかったので修正。 2009.03.29 公開