-*- Menu -*-
-*- ReasonSet -*-

ReasonSetの作り方(サイト自動構築ツール制作記)@PureBuilder1

このウェブサイトは基本的にはdocument generationとautomation utilityの組み合わせでできています。その中核となるのは PureDoc PureBuilder ですが、実際はPureBuilderが「設定ファイルを記述せよ」というものなので、サイト固有のスクリプトをだいぶ書かなくてはいけないことには変わりありません。

まず、現時点におけるマスターページテンプレートは次のようになっています。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/dtd/xhtml1-transitional.dtd"> <html> <head> <title><%= DOC.meta["title"] %> - <%= ENV["SITETITLE"] ? ENV["SITETITLE"] + " - " : "" %>*ReasonSet*</title> <link rel="stylesheet" type="text/css" href="//reasonset.net/css/layout.css" /> <link rel="stylesheet" type="text/css" href="//reasonset.net/css/base.css" /> <link rel="stylesheet" type="text/css" href="//reasonset.net/css/skin.css" /> <link rel="stylesheet" type="text/css" href="//reasonset.net/css/puredoc.css" /> <link rel="stylesheet" type="text/css" href="//reasonset.net/css/puredoc_skin.css" /> % # Load extra CSS pathes. % # $EXTRA_CSS is separated by :. % if ENV["EXTRA_CSS"] % ENV["EXTRA_CSS"].split(":").each do |i| <link rel="stylesheet" type="text/css" href="//reasonset.net/css/<%= i %>" /> % end % end % % # Load extra link pathes. % # Use $reasonset_link_* % # Leaving paramater name is used as rel name, and use its value as href URI. % ENV.keys.select {|i| i =~ /^reasonset_link_/ }.each do |key| <link rel="<%= key[/^reasonset_link_(.*)/, 1] %>" href="<%= "#{ENV["baseuri"]}/#{ENV[key]}" %>" /> % end % % # Load extra link pathes from DOC.meta["link"] % DOC.meta["link"].each do |linkk, linkv| <link rel="<%= linkk %>" href="<%= ENV["baseuri"] + "/" + linkv %>" /> % end if DOC.meta["link"] <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="content-language" content="ja" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta name="author" content="MASAKI Yuhsuke (Aki Tohmi)" /> <meta name="generator" content="PureBuilder" /> <meta name="robots" content="index,follow" /> % # load extra meta from DOC.meta["meta"] % if DOC.meta["meta"] % DOC.meta["meta"].each do |metak, metav| <meta name="<%= metak %>" content="<%= metav %>" /> % end % end </head> <body> <!-- over all container --> <div id="MainContainer"> <div class="pad_band"></div> <!-- Top Banner --> <div class="full_width_container" id="Header" > <%= ENV["SITE_BANNER"] %> </div> <!-- Center row --> <div id="CenterContainer"> <!-- Sub column --> <div id="SubColumn" class="full_width_container content_box"> <%= ENV["SUBCOLUMN_CONTENT"] || "" %> </div> <!-- / Sub column --> <!-- Main Column --> <div id="MainColumn" class="full_width_container content_box"> <h1><%= DOC.meta["title"] %></h1> <%= DOC.body %> % if DOC.meta["link"] && ( DOC.meta["link"]["next"] || DOC.meta["link"]["content"] || DOC.meta["link"]["prev"] || DOC.meta["link"]["start"] )|| ENV["reasonset_link_content"] || ENV["reasonset_link_start"] <div id="PageNavigation"> % if DOC.meta["link"] && DOC.meta["link"]["prev"] <span class="pagenav"><a href="<%= ENV["baseuri"] + "/" + ( DOC.meta["link"]["prev"].sub(/.pdoc$/, ".html") ) %>">Prev</a></span> % end % if ENV["reasonset_link_start"] || DOC.meta["link"] && DOC.meta["link"]["start"] <span class="pagenav"><a href="<%= ENV["baseuri"] + "/" + ( ENV["reasonset_link_start"] || DOC.meta["link"]["start"] ).sub(/.pdoc$/, ".html") %>">Start page</a></span> % end % if ENV["reasonset_link_content"] || DOC.meta["link"] && DOC.meta["link"]["content"] <span class="pagenav"><a href="<%= ENV["baseuri"] + "/" + ( ENV["reasonset_link_content"] || DOC.meta["link"]["content"] ).sub(/.pdoc$/, ".html") %>">Table of Content</a></span> % end % if DOC.meta["link"] && DOC.meta["link"]["next"] <span class="pagenav"><a href="<%= ENV["baseuri"] + "/" + DOC.meta["link"]["next"].sub(/.pdoc$/, ".html") %>">Next</a></span> % end </div> % end </div> <!-- /Main Column --> </div> <!-- Footer --> <div id="Footer" class="full_width_container content_box"> <%= ENV["FOOTER_CONTENT"] || "" %> <address>e-mail: <a href="mailto:aki@reasonset.net">aki@reasonset.net</a> <div>Copyright &copy; 2014 MASAKI Yuhsuke All rights reserved.</div> </div> <div class="pad_band"></div> </div> <!-- end of over all container --> </body> </html>

eRubyテンプレートファイルなのですが、かなり構造を持っていて複雑になっています。実際、そろそろこの形式は限界だと思っていて、もう少し見やすく直すかもしれません。

DOCというのがPureDocオブジェクトになります。ちなみに、PureDocが呼べないページは、外のスクリプトで内容を作ってしまい、

DOC.is do @body = content end

のようにすることでこのページを活かしています。このページ自体がPureDocに依存しているので、テンプレートからの生成はPureDocを使わなくてはいけない仕様となります。

多くの部分にDOCオブジェクトまたは環境変数を用いています。環境変数のセットは.purebuilder-puredoc.rcファイルで行っていますが、

. ~/doc/reason/sitesettings/chienomi.rc

と単純。

export SITETYPE=CHIENOMI export outsubdir=/chienomi export SITETITLE="ちぇのみ-Chienomi-" export suburi="/chienomi" . ~/doc/reason/sitesettings/global.rc fpath+=$HOME/.yek/lib/purebuild_functions export www_root="${www_root:-$HOME/.vps_www_root/delegate}" export SITE_BANNER="$(erb $HOME/doc/reason/title_banner_build.erb)" export SUBCOLUMN_CONTENT="$(erb $HOME/doc/reason/menu_build.erb )" export puredoc_template=$HOME/doc/reason/template/main.erb export outdir="${outdir:-$www_root$outsubdir$extraoutsubdir}" export baseuri="//reasonset.net"

このようにして設定しています。eRubyを用いている部分は、サイトによって変化する部分で、それ以前にセットした環境変数を元に何を生成するかが変化するようになっています。

一方、このエッセイのような生成はもう少し複雑で、

export extraoutsubdir="/essay" . ~/doc/reason/sitesettings/chienomi.rc export suburi="$suburi/essay" export reasonset_link_contents="chienomi/essay/" export reasonset_link_start="chienomi/essay/${$(print articles/*.pdoc([1])):r}.html" if (( ${#files} < 1 )) then files=(articles/*.pdoc) fi

という.purebuilder-puredoc.rcファイルが書かれています。

PureBuilder:PureDocはタイパラメータ(Zshの、配列と:セパレートのスカラーがリンクする変数)の$FILES(スカラー)/$files(配列)と、$index(one originなので要注意)をexportするものです。そのため、前の処理ファイル、次の処理ファイルはわかるようになっています。

そしてリビルド時に、連載は連載でビルドしています。

#!/usr/bin/zsh build-puredoc *.pdoc build-puredoc

次、前はPureDocドキュメント内で動的に構築しています。

##----- # title : Something ##----- DOC.is do p "Something..." end DOC.instance_eval File.read("#{ENV["HOME"]}/doc/reason/rbutil/chienomi_column.rb")

取り込まれているファイルは次のようになっています。

files = ENV["FILES"].split(":") index = ENV["index"].to_i - 1 @meta["link"] = {} if index > 0 @meta["link"]["prev"] = "chienomi/essay/#{files[index - 1]}" end if index < files.length - 1 @meta["link"]["next"] = "chienomi/essay/#{files[index + 1]}" end

そしてこれが先ほどのテンプレートで動的なリンクとして扱われ、またメインカラム下部の追加的な内容としても使われるということです。

ちなみに、URIが//から始まるようになっているのは、そうしないとCSSが読まれなかったりする(httpスキームで書いていて、httpsでアクセスされた場合など)ことがあるから。意味と見栄えの分離にかなり気を遣っていて、ページのソースは音声リーダーなどでも読めるはずですが、視覚的に理解できる意味はCSSが持っていたりするので、CSSを取り扱わないブラウザではかなりよみづらいかも知れません。HTML5流行りの昨今ですが、あえて動的な要素をなるべく排除し、静的な状態で読みやすいページを心がけているのは、もちろん旧式ブラウザやIEでも読みやすいページを提供するためであり、アクセシビリティのためです。

このように動的に生成されるコンテンツですが、「変更タイミングは予期できる」ため、別に毎回生成する必要はないはずだと考えます。現在の環境でキャッシュ機構がなく、eRubyテンプレートからRuby1.8.7を用いて生成する場合と比べると、応答速度は推定600%以上の向上となっています(転送時間を除く)。体感としては、ちょっとしたひっかかりがなくなり一瞬です。ネットワークトラフィックをみると非常に少ないのが分かると思います。通信速度の制限されたスマホや、格安SIMなど低速な環境でも読みやすい。その意味も含めて「アクセシビリティ」というのは、ウェブサイトにおける最大の価値であると思っています。

高いエクスペリエンスとを持ちながらレスポンシブルにするにはどうしたらいいか、ということをテーマにしたのがオライリーから発行されているハイパフォーマンスWebサイトがありますが、このサイトではそうしたテクニックも取り込んでいます。それにしても、プリミティヴな構造的にまず見やすくする、という意識が、最近は欠如しているのではないか?と感じます。動的に変化するから読みやすいのではなく、書籍や雑誌のレイアウトのように、目に留まりやすい、頭に入りやすい、そして読みやすい「構造的なデザイン」というものがまずあり、動的要素というのはvisiterにとって「読みやすい状態を維持する」ためのものであるべきだと私は思うのです。

読みやすいというのは、accessibleであるということ(例えIE6であっても読める、curlなどでも読める、w3mでも読める)もそうだし、プアな通信回線でも快適に読めることもそうでしょう。現在はモバイルデバイスのような「小さい画面」での読みやすさが考慮されていませんが、いずれ対応するつもりでいます。

Since: 2014-11-10 18:20:38 +0900
Last update: 2014-11-19 13:32:03 +0900
About