<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>3.14</title>
	<link href="http://white.s151.xrea.com/blog/"/>
	<link href="http://white.s151.xrea.com/blog/index.atom"/>
	<updated>2008-06-15T15:45:58+09:00</updated>
	<author>
		<name>snj14</name>
	</author>
	<id>http://white.s151.xrea.com/blog/</id>

	<entry>
		<title>About</title>
		<link href="http://white.s151.xrea.com/blog/2000-01-01-00-00.html"/>
		<id>http://white.s151.xrea.com/blog/2000-01-01-00-00.html</id>
		<published>2008-06-15T15:45:58+09:00</published>
		<updated>2008-06-15T15:45:58+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<dl><dt>書いてる人</dt><dd>snj14</dd><dd><a href="http://tako3.com/http://white.s151.xrea.com/wiki/">tako3</a></dd><dd><a href="http://geourl.org/near?p=http://white.s151.xrea.com/blog/">geourl</a></dd></dl><dl><dt>コメント/トラックバック</dt><dd>意図的に設置していません．<a href="http://twitter.com/">twitter</a> (<a href="http://twitter.1x1.jp/search/?source=&amp;keyword=snj14&amp;lang=&amp;text=1">snj14の検索結果</a>)や<a href="http://b.hatena.ne.jp/">はてブ</a>はチェックしています．</dd></dl><dl><dt>過去ログ</dt><dd><a href="http://white.s151.xrea.com/wiki/index.php?diary">http://white.s151.xrea.com/wiki/index.php?diary</a> (pukiwikiのweblogプラグイン)</dd></dl><dl><dt>フィード</dt><dd><a href="http://white.s151.xrea.com/blog/index.atom">ATOM</a> (全文配信しています)</dd></dl><dl><dt>Validator</dt><dd><a href="http://validator.w3.org/check/referer">XHTML Validator</a></dd><dd><a href="http://jigsaw.w3.org/css-validator">CSS Validator</a></dd></dl>			</div>
		</content>
	</entry>
	<entry>
		<title>LocationbarNewTab2.uc.js</title>
		<link href="http://white.s151.xrea.com/blog/2007-10-19-05-36.html"/>
		<id>http://white.s151.xrea.com/blog/2007-10-19-05-36.html</id>
		<published>2008-06-11T21:11:43+09:00</published>
		<updated>2008-06-11T21:11:43+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<p><ins datetime="2008-06-10T22-49-51+09:00"> <a href="http://coderepos.org/share/browser/lang/javascript/userchrome">CodeRepos</a>に入れた</ins><ins datetime="2008-06-07T12-34-37+09:00"> 新しいタブを開く前にフォーカスをロケーションバーから外すようにしました</ins></p><p>元は firefox userChrome.js greasemonkey スクリプトスレ (part1)の178さんのロケーションバーからURL入力してEnterを押すと新規タブで開くuserChrome.js用スクリプトですブックマークレットを開く時とabout:blankな時はその場で開くようにしました(名前は適当)</p><pre class="code_javascript">// open in New Tab from location bar
BrowserLoadURL = function(event,post){
    gBrowser.userTypedValue = content.window.document.URL;
    if((event &amp;&amp; event.altKey) ||
       gURLBar.value.match(/^javascript:/) ||
       gBrowser.userTypedValue == 'about:blank'){
      loadURI(gURLBar.value,null,post,true);
    }else{
        _content.focus();
        gBrowser.loadOneTab(gURLBar.value,null,null,post,false,true);
    }
}

</pre>			</div>
		</content>
	</entry>
	<entry>
		<title>GRDDLでメタデータを取得するLDRize</title>
		<link href="http://white.s151.xrea.com/blog/2008-03-09-15-53.html"/>
		<id>http://white.s151.xrea.com/blog/2008-03-09-15-53.html</id>
		<published>2008-06-10T23:32:23+09:00</published>
		<updated>2008-06-10T23:32:23+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<h2>概要</h2><p>AutoPagerizeやLDRize，LDR Full FeedなどのGreasemonkeyスクリプトはページごとの構造の違いを吸収するため，XPathなどのデータをSITEINFOとしてwikiから取得しています．ですが，SITEINFOには<a href="http://white.s151.xrea.com/blog/2008-01-31-20-02.html">LDRize専用のmicroformatsについて</a>という記事に書いた問題点があります．同じ記事中で疲れて途中でやめてしまった解決方法の提示の続きを書きます．</p><p>また，実装したものを<a href="http://coderepos.org/share/browser/lang/javascript/userscripts/ldrize/ldrize.user.js?">CodeRepos</a>にあげてます．インストールした後，このブログで動作の確認ができます．まだ<a href="http://purl.org/net/ldrize/ns">語彙</a>とXSLT(語彙のページと同じ場所にリンクがある)がこれで良いのか判断付かないのでフィードバックが欲しいです．よろしくお願いします．</p><h2>解決方法</h2><p>で，結論から先に書くと，これらの問題の解決策は <strong>GRDDLで抽出したRDFをSITEINFOとして使う</strong> というものです．理由は以下のような点があります．(前回挙げたmicroformatsの問題点とSITEINFOの問題点が全て解決される上にプラスアルファ)</p><ul class="ul1"><li>ページを開くたびにmicroformatsの数だけ探索しなくて済む</li><li>ページの構造を保証できる</li><li>値の意味を明示できる</li><li>バリデーションができる</li><li>wikiへの依存を少なくできる</li></ul><p>逆に，デメリットはユーザの手間がちょっと増えることです．ページの構造に合ったXSLTがなければ作ってHTMLに1行追加する必要があります．XSLTが存在すればHTMLに1行追加だけですが．</p><p>現実的に，全てのページがGRDDLに対応してくれるとは思えないので，wikiにURLの正規表現+XPathを書く今の方法も残す予定ではあります．(wikiにURLの正規表現+XSLTのURLを書く方法もやりたい．ページを作った人がページの構造を保証するGRDDLに対して，第三者が簡単に保証する方法として．)</p><h2>ページを開くたびにmicroformatsの数だけ探索しなくて済む</h2><p>LDRizeはhAtomとxFolkというmicroformatsに対応していますが，これらに対応できているのは，<strong>全てのページ</strong> (非対応のページを含む)で「このページはhAtomに対応しているか」「このページはxFolkに対応しているか」を探索(XPathにマッチするかチェック)しているためです．</p><p>今は2つのmicroformatsに対応していないため2回の探索だけで済む…わけではなく，tDiaryやWordPress，blogger，PukiWiki，RandomNoteなど，他にもいろいろな構造に対して全てのページで探索しているので，とても無駄が多いのが現状です．</p><p>これが，GRDDLに対応したページならば操作は1回で済みます(link要素の探索)し，それ以上増えることもなくなります．正確には，無駄にXSLTを処理しなくてもいいように簡単な探索(こっちで見つかれば終了)と全ての探索の2回ですが．</p><h2>値の意味を明示できる</h2><pre>link:      'h2//a[contains(@class,&quot;l&quot;)]',
</pre><p>これはLDRize用SITEINFOの一部です．現在，SITEINFOの値(右側の部分)にはどのようなXPathを書くべきか，また，それはどこに書かれているか，についての決まりはありません．SITEINFOのwikiにちょろっと書いてあったり，動作を知った上で，それっぽく書いているのが現状です．なぜこれが問題かというと，前回の記事でも書いた通り，「この値も入れて！」と言う人がでてきても，<strong>実際入れてしまうと「どういう値か分からないのに誰がメンテするのか」という問題があって入れられない</strong> という勿体ないことになってしまうからです．そのためには， <strong>linkはこういう構造に対するXPathを書く</strong> とあらかじめ明示する必要があるのです．GRDDLでRDFを抽出して，それをSITEINFOとして用いると，linkにはURIの接頭辞が付いて， <a href="http://purl.org/net/ldrize/ns#link">http://purl.org/net/ldrize/ns#link</a> のようになります．これはURIで色々なものを表すというRDFの特性上こうなるのです．</p><h2>ページの構造を保証できる</h2><h3>microformatsの問題点</h3><p>※ クライアントを 「microformatsで構造化されたページを処理するプログラム」の意味で用います．</p><p>前回もチラっと書いたmicroformatsの問題点について，もう一度．</p><ul class="ul1"><li>rel=&quot;home&quot;と同じ形で別の意味を定義する組織が現れた場合，どのように解釈するのか？<ul class="ul2"><li>クライアントは<a href="http://microformats.org/wiki/rel-home">rel-home</a>と解釈する．でもページを作った人が別の意味で構造化していると，意図しない動作(バグ)になる．少なくともそう見える．</li><li>同音異義語 みたいな感じ．</li></ul></li><li>rel=&quot;home&quot;と同じ意味で，別の組織がrel=&quot;sitetop&quot;を定義し，更に別の組織がrel=&quot;toppage&quot;(以下略)のようになった場合，クライアントはいくつかの定義しか利用できなくなる．<ul class="ul2"><li>クライアントが解釈できないのならば構造化する意味はない．</li><li>最近MSがwebsliceとかいうhatomの亜種を作ると言いだしたし．</li><li>同義語 みたいな感じ．</li></ul></li></ul><h3>原因</h3><p>原因はこんな感じです多分．</p><ul class="ul1"><li>class属性やrel属性などの値は自由に記述することが許されている</li><li>共通の構造を決めても，それを知らない人がいる(知らないから勝手に定義するし勝手に利用する)</li><li><strong>「どのページにどの構造が使われているか」の保証が出来ない</strong></li><li>microformatsに厳密性がない</li></ul><p>保証がないから厳密性がないわけですが．</p><h3>解決方法</h3><p>「どのページにどの構造が使われているか」を保証されていて，それをクライアントが解釈できれば，上記問題点は解決できます．人間が「このページのrel=&quot;home&quot;は<a href="http://microformats.org/wiki/rel-home">rel-home</a>だよ．別のrel=&quot;home&quot;じゃないよ．」と教えてくれればいいわけです．で，前回も書いたように，保証された構造のための方法に，RDFaとGRDDLというのがあってどちらかによって保証されれば良いのです．両方とも最終的にはRDFというものを抽出できるようになっていて，RDFではURIで名前を決めるので重複しないから厳密ってことなのです．</p><ul class="ul1"><li>RDFaはmicroformatsと取って代わるもので，XHTMLの中で保証します．</li><li>GRDDLはmicroformatsと一緒に使うもので，XSLTの中で保証します．</li></ul><p>どっちでも良いのですが，エンドユーザの手間が少ないの方がみんなが(自分も)楽なので，楽な方を取ります．</p><ul class="ul1"><li>microformats+GRDDLは，一度XSLTを作成すれば後のエンドユーザはmicroformatsに対応した後に1行追加するだけです．</li><li>RDFaはそれぞれのタグごとに名前空間を指定したりしないといけないので，GRDDLのような資源の再利用が難しいです．</li></ul><p>というわけで，GRDDLによる解決方法を取ります．</p><h2>バリデーションができる</h2><p>XSLT内で条件分岐を行って以下のようにする．</p><ul class="ul1"><li>正しい構造なら正しくRDFを抽出する</li><li>正しくない構造なら何も抽出しない</li></ul><p>RDFが抽出できた時だけクライアント(LDRizeなど)を実行させるようにすると，HTML構造を変更して，かつ，XSLTも正しいものに変更した時のみ動作し，それ以外の場合(HTML構造だけを変更したときなど)はクライアントが動作しないので，誤動作も起きない．</p><h2>wikiへの依存を少なくできる</h2><p>それぞれのページ側にメタデータ(SITEINFO)抽出のためのルール(XSLT)の指定を行うので，wikiが落ちたり消されたりいたずらされても，被害を受けずに済む可能性が高くなります．</p><p>関連して，ページから直接SITEINFOを生成できるので，wikiからデータを削除しても良くなって，LDRizeがローカルに保存するデータが少なくなります．現状は，1度も見ないようなページ用のSITEINFOのデータも全てのユーザが全部GM_setValueでprefs.jsに保存しています．wikiのデータを減らして，ページ側でメタデータを生成できるようになれば，自分が見たページ用のSITEINFOをその場で生成してキャッシュしておくことができるようになるため，1度も見たことがないページ用のSITEINFOをキャッシュしなくて良くなります．</p><h2>GreasemonkeyでGRDDL変換を行いRDFを扱う方法について</h2><p>RDFとは，URIかデータ(文字列とか)を使って表現した三つ組みのことです．だいたい．具体例をあげると，このブログから抽出できるRDF/XML(XML形式で3つ組みを表したRDF)の一部は下記のような感じです．</p><pre class="code_RDF/XML">&lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot; xmlns:ldrize=&quot;http://purl.org/net/ldrize/ns#&quot;&gt;
  &lt;rdf:Description rdf:about=&quot;http://white.s151.xrea.com/blog/&quot;&gt;
    &lt;ldrize:article&gt;.//*[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;), &quot; hentry &quot;)]&lt;/ldrize:article&gt;
  &lt;/rdf:Description&gt;
&lt;/rdf:RDF&gt;
</pre><p>一応<a href="http://www.w3.org/2007/08/grddl/?docAddr=http%3A%2F%2Fwhite.s151.xrea.com%2Fblog%2F&amp;output=turtleplain">GRDDLで抽出できるこのブログの全てのRDF</a>も見られます．これはウェブサービスとして提供されているものですが，XSLTの処理系があればRDF/XMLを出力することができます．とりあえず，GreasemonkeyからはXSLTを使ってRDF/XMLを出力できるので，そのXMLをXPathで処理しています(本当はちゃんとRDFパーサとか使うべき．Greasemonkeyからは扱えませんが拡張やuserChrome.jsからはRDFも扱えるらしい．<a href="http://developer.mozilla.org/ja/docs/RDF">http://developer.mozilla.org/ja/docs/RDF</a> )．</p><p>ここで，上記のRDF例のインデントの一番深い部分を見ると，SITEINFOに良く似ています．wiki上の表現に倣って変換してみると下記のようになります．データが取得できれば，あとは今までのスクリプトと変わりはありません．</p><pre>article: './/*[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;), &quot; hentry &quot;)]'
</pre><p>prefs.jsに保存されるキャッシュデータは↓のようになります．structuredUriRegExの正規表現にマッチするかどうかを確認して，マッチしなければGRDDL変換を行います．</p><pre>[{section:\&quot;.//*[contains(concat(\\\&quot; \\\&quot;,normalize-space(@class),\\\&quot; \\\&quot;), \\\&quot; section \\\&quot;)]\&quot;,
  article:\&quot;.//*[contains(concat(\\\&quot; \\\&quot;,normalize-space(@class),\\\&quot; \\\&quot;), \\\&quot; hentry \\\&quot;)]\&quot;,
  view:\&quot;.//*[contains(concat(\\\&quot; \\\&quot;,normalize-space(@class),\\\&quot; \\\&quot;), \\\&quot; entry-title \\\&quot;)]//text()\&quot;,
  link:\&quot;.//*[contains(concat(\\\&quot; \\\&quot;,normalize-space(@rel),\\\&quot; \\\&quot;),\\\&quot; bookmark \\\&quot;)]\&quot;,
  structuredUriRegEx:\&quot;^http://white.s151.xrea.com/blog/\&quot;,
  expire:(new Date(1204137557921))
 },
 {...}]
</pre><ol class="ol1"><li>生成されるデータはGRDDL変換を行ったページ ＝ 自分が見たページ</li><li>一定期間が過ぎたキャッシュは破棄される</li><li>1+2 ＝ 余計なデータは持たない</li></ol><h2>今後について</h2><p>まだコードや語彙やXSLTに問題や不安が残ってるので，それらが解決したらuserscripts.orgにあげて，テスト版でなくなると思います．</p><p>…あとから気づいたけれど，同じ構造(例えばhAtom)でもサイトが違えばその数だけXPathをキャッシュしようとするから，同じXPathが沢山prefs.jsに保存されることになってしまう．要検討．</p>			</div>
		</content>
	</entry>
	<entry>
		<title>ShareTwitterOnTumblr</title>
		<link href="http://white.s151.xrea.com/blog/2008-03-02-09-30.html"/>
		<id>http://white.s151.xrea.com/blog/2008-03-02-09-30.html</id>
		<published>2008-06-10T22:33:41+09:00</published>
		<updated>2008-06-10T22:33:41+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<h2>概要</h2><p><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>，<a href="http://userscripts.org/scripts/show/11562">LDRize</a>と連携してTwitterの発言をTumblrにChatとして投稿出来るGreasemonkeyスクリプトです．デモは<a href="http://userscripts.org/scripts/show/23459">userscripts.org</a>にあります．</p><h2>コレを使うと何がうれしいのか</h2><ul class="ul1"><li>Twitter上のちょっとした議論(最近結構見かける)とか，この流れスゲーと思ったのをTumblrに投稿しておける．</li><li>誰かにその議論やスゲー流れがあったことを教えたい時に，URLをいくつも教えるのは教える側も教えられる側も大変．</li><li>とは言え，発言自体の羅列を送るのも長ったらしい．</li><li>TumblrにChatとして投稿しておけば，1つのURLを教えるだけで良くなる．</li><li>他の誰かに教えるためだけでなく，備忘録として使っても良い．</li><li>こんな感じ→ <a href="http://snj.tumblr.com/post/27707495">http://snj.tumblr.com/post/27707495</a> <a href="http://snj.tumblr.com/post/27720910">http://snj.tumblr.com/post/27720910</a> (こんなの人力でやる気しない)</li></ul><h2>インストール</h2><p><a href="http://userscripts.org/scripts/show/23459">ShareTwitterOnTumblr</a> (403って言われる人は <a href="http://coderepos.org/share/browser/lang/javascript/userscripts/sharetwitterontumblr.user.js?">CodeRepos</a>からどうぞ)</p><ul class="ul1"><li><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>が必要です</li><li><a href="http://userscripts.org/scripts/show/11562">LDRize</a>が必要です(なくても良いけどまともに使えない)</li><li><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>や<a href="http://userscripts.org/scripts/show/11562">LDRize</a>より下に配置してください</li></ul><h2>使い方</h2><ul class="ul1"><li><a href="http://twitter.com/home">Twitter</a>や<a href="http://twitter.1x1.jp/search/">Twitter検索</a>, <a href="http://terraminds.com/twitter/">terraminds</a>を開いてください．</li><li>LDRizeを使って，投稿したい発言にpinを立ててください(j/kで移動してp)</li><li>一通りpinを立て終えたら M-x (Alt+x) を押してMinibufferを表示させてください</li><li>Minibufferに以下の例のように入力してください</li><li>右下の Share ... が Share ... done に変わったら投稿完了です．</li><li>ちょっと長いので履歴を辿る(C-r)かエイリアスを設定(C-c)したほうが良いです．</li></ul><pre>// 現在開いているページを投稿(1つの発言しかないChatになります)
location | share-twitter-on-tumblr

// ピンを立てたもの(なければ現在の)を全て投稿
pinned-or-current-link | share-twitter-on-tumblr | clear-pin
</pre><h2>仕様とか</h2><ul class="ul1"><li><a href="http://coderepos.org/share/browser/lang/javascript/userscripts/sharetwitterontumblr.user.js?">CodeRepos</a>にあげているので，気に入らない動作があれば弄ってください．</li><li>LDRize用SITEINFOのlink先(LDRizeのoで開くページ)が ^<a href="http://twitter.com/id/statuses/">http://twitter.com/id/statuses/</a>\d+$ であれば他のページでも動きます．<ul class="ul2"><li>@includeにURLを入れる必要はあります．( <a href="http://coderepos.org/share/browser/lang/javascript/userscripts/sharetwitterontumblr.user.js?">CodeRepos</a>のソースを編集してください．)</li><li>ピンを立てたlinkに1つでもtwitter以外のページが混じっていると動作しません．</li></ul></li><li>ピンを立てた順番は関係ありません．twitter.com/statuses/の直後の番号でソートしているので，時系列に並びます．</li><li>ふぁぼったーは一覧のページにtwitterへのパーマリンクがなかったので保留にしました．</li><li>twitter，Twitter検索，terraminds でフォーマットが異なるので，twitterのパーマリンクを取得して，GM_XHRで本文を取得しています．</li></ul><h2>愚痴</h2><p>microformatsとか使って構造を合わせてくれないと，こういうスクリプトを作りづらい．というか今のままでは素のHTMLから本文を取得するのは不可能．無理矢理やろうと思えばできるけど，スケーラブルでないしサステナブルでないのでやるべきでないと思う．仕方なくGM_XHRでtwitterにリクエスト発行して本文を取得してるから，10個の発言にpin立てて実行すると10回アクセスが発生する．それプラスTumblrのパラメータ取得に1回と投稿に1回．構造が統一されていれば，こんなことしなくても済む．twitterも一覧ページはhAtomのくせに個別のページは独自構造だし，かといって一覧ページの本文は末尾に...が入ってたりして良く分からない．今までみたいにSITEINFOを作ればとりあえずは解決するけど，あれは拡大しないし持続しない．拡大・持続しないと分かっているものに依存したスクリプトを何個も書きたくない．</p><p>話しが飛ぶけど2chコピペブログのHTMLは本当にひどい．構造も糞もあったもんじゃない．誰かhAtomとかで出力するコピペブログ作成専用のソフトウェアかブログサービスを作ってくれればいいのに．もし仮に構造化された2chコピペブログがあったら，ShareTwitterOnTumblrをTwitter専用じゃなくて，2chの書き込みにも適用できたりするんだわ．機械可読になるから，ShareTwitterOnTumblrだけでなくこれから誰かが作るであろう便利なスクリプトにも使えるようになるんだ．</p><p>で，2chに適用できるということは，はてブのコメントとかブログのコメントとかにも適用できたりするハズなんだけど，はてブははてブで独自のキーバインドをつけてるからLDRizeが動かないっていう問題がある．「非LDRizeユーザ」や「重くなるからGreasemonkeyを入れたくない」という人のことを考えたら，サイト独自のキーバインドをJavaScriptで設定するのは間違ってないかもしれない．作ってる人もユーザのためを思ってやってるんだと思う．でも，それサステナブル？そしてスケールラブル？</p><p>はてブだけじゃなくて，自分のブログにj/kスクロールを入れてる人もいるけど，Shift,Ctrl,Alt,Metaキーの判定もちゃんとやってる？j/kじゃなくてn/p使いたい人はどうすればいい？AutoPagerizeが継ぎ足したページに対応できてる？AutoPagerizeみたいなUIをどうにかするスクリプトがこれから出てきたときに，対応できる？仮に全部できたとしても，1つ1つのサイトが別々に実装してたら，これらの対応状況は全部違うんだよ？使い勝手は本当に良い？本当にユーザのためになる？</p>			</div>
		</content>
	</entry>
	<entry>
		<title>ReblogCommand</title>
		<link href="http://white.s151.xrea.com/blog/2008-02-29-11-50.html"/>
		<id>http://white.s151.xrea.com/blog/2008-02-29-11-50.html</id>
		<published>2008-06-10T22:33:40+09:00</published>
		<updated>2008-06-10T22:33:40+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<h2>概要</h2><p><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>と連携してキー1発でreblog出来るGreasemonkeyスクリプトに関する説明です．<a href="http://userscripts.org/scripts/show/14490">MinibufferBookmarkCommand</a>のreblog版のような感じです．デモは <a href="http://userscripts.org/scripts/show/23365">userscripts.org</a> にあります．</p><h2>コレを使うと何がうれしいのか</h2><ul class="ul1"><li>reblog画面が開く時間，待たずに済みます</li><li>キー1発なので，<a href="http://userscripts.org/scripts/show/12305">LDRize Minibuffer reblog command</a>に比べ，ピンを立てなくても良くなります<ul class="ul2"><li>手間は微々たるものですが，心理的に楽になれます．多分．</li></ul></li><li>殆ど<a href="http://userscripts.org/scripts/show/14797">TumblrReblogInLDR</a>と同じですが，LivedoorReadr/FastLadderだけでなく<a href="http://www.tumblr.com/dashboard/">Dashboard</a>でも利用できます</li><li>誰かのTumblrのページでも多分動きます<ul class="ul2"><li>ただし，SITEINFOのlinkで指定したXPathがパーマリンクでなく画像のURLやリンク先のURLになっていたりすると動作しません</li></ul></li><li>reblog専用なので，FFFFOUNDやFlickrのページやフィードからpostすることは出来ません</li></ul><h2>インストール</h2><p><a href="http://userscripts.org/scripts/show/23365">ReblogCommand</a></p><ul class="ul1"><li><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>が必要です</li><li>また，<a href="http://www.tumblr.com/dashboard/">Dashboard</a>で実行する際は<a href="http://userscripts.org/scripts/show/11562">LDRize</a>もあったほうが便利です</li><li><a href="http://userscripts.org/scripts/show/11759">Minibuffer</a>や<a href="http://userscripts.org/scripts/show/11562">LDRize</a>より下に配置してください</li></ul><h2>使い方</h2><ul class="ul1"><li>tやT(shift + t)を押してください<ul class="ul2"><li>t : そのままreblogします</li><li>T : 新しくreblogのページを開きます</li></ul></li><li>または，Minibufferに以下の例のように入力してください<ul class="ul2"><li>オプションは -m のみで，指定するとTを押した時のように新しく開きます</li></ul></li></ul><pre>// 現在開いているページをreblog
location | reblog

// 現在開いているページを編集してreblog (http://www.tumblr.com/reblog/id のページを開く)
location | reblog -m

// ピンを立てたもの(なければ現在の)を全てreblog
pinned-or-current-link | reblog | clear-pin
</pre><h2>設定</h2><ul class="ul1"><li>ALLOW_OWN_DOMAIN</li><li>独自ドメインでTumblrを使っている人を適当に予測するかどうか，の真偽値です．誤爆したら嫌な人はfalseにしてください．</li></ul><h2>既知の問題</h2><p>FastLadder(LivedoorReaderも?)でピンを立ててtを押してもunsafeWindowがどうこうと怒られてしまいます．原因が分かりません．分かったら直します．一応<a href="http://coderepos.org/share/browser/lang/javascript/userscripts/reblogcommand.user.js?">CodeRepos</a>にあげてるので誰か直してくれるとうれしいです．</p>			</div>
		</content>
	</entry>
	<entry>
		<title>特定のclass属性を持った任意の要素にマッチするXPath</title>
		<link href="http://white.s151.xrea.com/blog/2008-02-11-10-36.html"/>
		<id>http://white.s151.xrea.com/blog/2008-02-11-10-36.html</id>
		<published>2008-06-10T22:20:59+09:00</published>
		<updated>2008-06-10T22:20:59+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<h2>結論</h2><p>特定のclass属性を持った任意の要素にマッチするXPath(hogeは指定したいclass属性名)</p><pre class="code_xpath">//*[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;), &quot; hoge &quot;)]
</pre><p>特定の要素にしたい場合は適当に</p><pre class="code_xpath">div[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;), &quot; hoge &quot;)]
</pre><p>などとする．</p><h2>概要</h2><p><strong>特定のclass属性を持った任意の要素にマッチするXPath</strong>というのはアドオンやUserJavaScript，スクレイピングの際にDOMノードを特定するために良く使いますが，XPathの書き方がマズイ人がたまにいます．普通に考えたらXPathはこうなります．</p><p>XPath1::</p><pre class="code_xpath">//*[@class=&quot;hoge&quot;]
</pre><p>class属性は以下の引用部分に書かれているとおり，スタイルシート以外の目的で使っても良く，後述しますが複数の値を持つことも許されています．</p><blockquote cite="http://www.w3.org/TR/html4/struct/global.html#adef-class">
The class attribute has several roles in HTML:
    * As a style sheet selector (when an author wishes to assign style information to a set of elements).
    * For general purpose processing by user agents.
</blockquote><p>しかし，XPath1では他のUserJavaScriptがclass属性を追加した時などに問題が起きます．(例えばcustomize googleというアドオンのWayBack Machineという機能も，今はどうかわかりませんが，2007-09-05時点ではLDRizeと一緒に使えないという問題がありました)</p><p>こうした問題が起きる原因は以下の2つです．</p><ol class="ol1"><li>class属性が複数の値を持てることを考慮していない</li><li>white spaceがタブや改行を含むことを考慮していない</li></ol><p>最終的には結論で示したXPathになるので大したことはありませんが，一応W3Cの原文の引用と一緒に説明します．</p><h2>class属性は複数の値を持てる</h2><blockquote cite="http://www.w3.org/TR/html4/struct/global.html#h-7.5.2">
Multiple class names must be separated by white space characters.
</blockquote><p>なので，XPathは以下のようになるかと思います．</p><p>XPath2</p><pre class="code_xpath">//*[contains(concat(&quot; &quot;,@class,&quot; &quot;), &quot; hoge &quot;)]
</pre><p>XPath2の動きを説明すると，</p><ol class="ol1"><li>//で強制的にルート要素から，全ての子孫要素に対して探索を行います(XHRした結果に対して似たようなことをしたいときは.//にする必要がある)</li><li>\*で全ての要素にマッチします</li><li>[]で1でマッチした要素(この場合は全ての要素)を更に絞り込みます</li><li>@classは，例えばマッチした要素が&lt;div class=&quot;foo hoge bar&quot;&gt;なら &quot;foo hoge bar&quot; に置換されます</li><li>concat(&quot; &quot;,@class,&quot; &quot;)で文字列の結合を行います =&gt; &quot; foo hoge bar &quot;</li><li>contains(&quot; foo hoge bar &quot;, &quot; hoge &quot;)で，1つ目の文字列の中に2つめの文字列が含まれるかのチェックを行います．<ol class="ol2"><li>concatで前後に半角スペースを結合したので，hogeが真ん中になくてもマッチします．</li></ol></li></ol><h2>white spaceはタブや改行を含む</h2><blockquote cite="http://www.w3.org/TR/html4/struct/global.html">
White space (spaces, newlines, tabs, and comments)
</blockquote><blockquote cite="http://www.w3.org/TR/html4/types.html#type-cdata">
User agents should interpret attribute values as follows:

   * Replace character entities with characters,
   * Ignore line feeds,
   * Replace each carriage return or tab with a single space.
</blockquote><p>なので，XPathは以下のようになります．</p><p>XPath3</p><pre class="code_xpath">//*[contains(concat(&quot; &quot;,normalize-space(@class),&quot; &quot;), &quot; hoge &quot;)]
</pre><h2>normalize-space</h2><p>XPathの動きを説明する前にnormalize-spaceの調査．</p><blockquote cite="http://www.w3.org/TR/xpath#function-normalize-space">
The normalize-space function returns the argument string with whitespace normalized by stripping leading and trailing whitespace and replacing sequences of whitespace characters by a single space. 
Whitespace characters are the same as those allowed by the S production in XML. 
</blockquote><p>日本語訳</p><blockquote cite="http://www.infoteria.com/jp/contents/xml-data/REC-xpath-19991116-jpn.htm#function-normalize-space">
normalize-space 関数は、引数に指定した文字列の空白文字を正規化して返す。つまり前後の空白文字を取り除き、連続する空白文字を１つの空白文字に置き換える。
空白文字は、XMLの S プロダクションで使用できるものと同じである。
</blockquote><p>S production in XMLってなんぞやってことでこれも調べる．</p><blockquote cite="http://www.w3.org/TR/REC-xml/#NT-S">
White Space
[3]   	S	   ::=   	(#x20 | #x9 | #xD | #xA)+
</blockquote><p>確認(firebugで以下を実行)</p><pre class="code_javascript">// spaceとtabは普通に表示したら分からなかったのでキモい感じになってしまった
var chars = [&quot;#x20&quot;,&quot;#x9&quot;,&quot;#xD&quot;,&quot;#xA&quot;];
for(var i=0; chars.length&gt;i; i++){
 chars[i].match(/#x([0-9A-F]+)/);
 var str = String.fromCharCode(parseInt(RegExp.$1,16));
 switch(str){
  case &quot; &quot;:
  console.log(&quot;space&quot;)
  break;
  case &quot;\t&quot;:
  console.log(&quot;tab&quot;)
  break;
  default:
  console.log([str])
 }
}

// 実行結果
// space
// tab
// [&quot;\r&quot;]
// [&quot;\n&quot;]
</pre><p>なので，XPath3の動きは</p><ol class="ol1"><li>途中まではXPath2と一緒</li><li>normalize-space()で連続する空白文字()を半角スペースに置換，先頭と末尾の空白文字を削除</li><li>途中からもXPath2と一緒</li></ol><h2>case sensitive</h2><blockquote cite="http://www.w3.org/TR/html4/struct/global.html#h-7.5.2">
class = cdata-list [CS]
</blockquote><blockquote cite="http://www.w3.org/TR/html4/types.html#case-sensitive">
CS::
    The value is case-sensitive (i.e., user agents interpret &quot;a&quot; and &quot;A&quot; differently).
</blockquote><p>class属性の値はcase sensitive，つまり，大文字と小文字は別物なので，これの変換はいらない．</p><p>ちなみに，rel属性の値はcase insensitiveなので変換が必要(でもやり方が美しくない)で，しかも複数の値を持てる．(e.g. rel=&quot;friend met&quot;)</p>			</div>
		</content>
	</entry>
	<entry>
		<title>LDRize専用のmicroformatsについて</title>
		<link href="http://white.s151.xrea.com/blog/2008-01-31-20-02.html"/>
		<id>http://white.s151.xrea.com/blog/2008-01-31-20-02.html</id>
		<published>2008-06-09T01:01:58+09:00</published>
		<updated>2008-06-09T01:01:58+09:00</updated>
		<content type="xhtml" xml:base="white.s151.xrea.com">
			<div xmlns="http://www.w3.org/1999/xhtml">
<h2>先に結論</h2><p>LDRize専用のオレオレフォーマット案には反対です．その理由を書きます．ついでに今後の展望について書くつもりでしたが，疲れたので途中まで．</p><h2>今までの話の流れ</h2><blockquote title="LDRizeとmicroformats" cite="http://june29.jp/2008/01/12/ldrize-microformats/">

- 内部向けのサイトなので，公にSITEINFOを書きたくない
- 「v」「o」で開くようなリンクはなく，「j」「k」のスクロール操作だけを利用したい

ちょっと特殊なケースですね．
</blockquote><p>実は，これは今まで見えにくかっただけで，LDRizeの一番の利点を生かしたケースじゃないかと思っています．<a href="http://snj.tumblr.com/post/23125267">ちょっとだけTumblrに書いたやつ</a>や<a href="http://twitter.com/snj14/statuses/589110972">ちょっとだけTwitterに書いたやつ1</a><a href="http://twitter.com/snj14/statuses/589130552">ちょっとだけTwitterに書いたやつ2</a>以外はまだオンラインにあげてないので，詳しくはまた今度書きますが(多分)，LDRizeの利点は以下の３つだと考えています．</p><ul class="ul1"><li>読み飛ばせる</li><li>位置を調整できる</li><li>記事単位でなんらかの操作ができる</li></ul><blockquote title="LDRizeとmicroformats" cite="http://june29.jp/2008/01/12/ldrize-microformats/">

 じゃあ，今回のケースのようなサイトでLDRizeの「j」「k」スクロールだけを利用したいときにはどうすればいいでしょうか．
 オレオレフォーマットにはなりますが，SITEINFOに
 
 domain:    'microformats',
 paragraph: '//*[contains(concat(&quot; &quot;,@class,&quot; &quot;), &quot; ldrize-paragraph &quot;)]'
 
 のような記述を追加し，サイト側のマークアップで対応するってのは現時点ではアリかなと思っています．
 皆さん，どう思われますか．
</blockquote><p>と言われて，あとで書く！と思いながら随分時間が経ってしまいました．すいません．</p><h3>まとめ</h3><ul class="ul1"><li>LDRizeがサポートしているmicroformatsはhAtom(ブログ用)とxfolk(SBM用)だけです</li><li>LDRizeの利点1(読み飛ばせる)の効果を利用できるシーンはブログやSBM以外にもあります(例: amazon, wikipedia)</li><li>「専用のmicroformatsほしい！」</li><li>こんなんどうでしょう → class=&quot;ldrize-paragraph&quot;というオレオレフォーマット</li></ul><h2>用途を定義したmicroformatsが駄目な理由</h2><blockquote title="LDRizeとmicroformats" cite="http://june29.jp/2008/01/12/ldrize-microformats/">

 AutoPagerizeのmicroformatsは，完全にAutoPagerize用です．
 一方でLDRizeのカバーしている microformatsは，LDRizeのためのものではないので，
 LDRizeを動作させるためにマークアップすることが意味的に正しいとは限らないのですね．

</blockquote><p>引用部にもありますが，LDRizeが利用するmicroformatsはLDRize専用のものではありません．そもそもmicroformatsは，HTMLの構造をある程度統一することで，意味を持ったデータをプログラムから取得するものです．用途に対してmicroformatsを定義すると「１つの用途」にしか用いることができませんが，構造に対してmicroformatsを定義すると「複数の用途」に用いることができます．前者で複数の用途に用いてもいいのですが，もともと「１つの用途」のためのマークアップなので，変更があるかもしれません．変更された時に，そのmicroformatsを利用している別のプログラムもそのまま利用し続けていいと保証できるのでしょうか．</p><p>具体例を挙げます．</p><p><a href="http://d.hatena.ne.jp/swdyh/20070701/1183239979">autopagerize_page_element</a> は，AutoPagerize用のmicroformats(?)です．class=&quot;autopagerize_page_element&quot;で指定された部分をclass=&quot;autopagerize_insert_before&quot;で指定された部分の直前に挿入します．なので，autopagerize_page_elementは <strong>だいたいページのコンテンツの部分</strong> となります．ですがautopagerize_page_elementという名称は <strong>用途</strong> を表しており，<strong>構造</strong> を表しているわけではないので，ページのコンテンツの部分でない可能性もあります．</p><p>ここで，ページのコンテンツをスクレイピングしてページの要約を作るようなスクリプトが <strong>ページのコンテンツの部分</strong> を欲しいとします．このスクリプトはautopagerize_page_elementを利用しても大丈夫でしょうか．もしHTMLが変更されてautopagerize_page_elementに広告が入り，メタデータ(時間,タグ,コメント etc)が入り，AutoPagerizeに利用するには問題ないがページのコンテンツの部分でない という状況になったら精度に問題が生じるのではないでしょうか．そう考えると，autopagerize_page_elementをAutoPagerize以外の用途に用いるのは避けたほうが良いでしょう．</p><p>では，このスクリプトはまた別に専用のmicroformatsを作るべきでしょうか？もし，autopagerize_page_elementのような<strong>用途</strong>に対するmicroforamtsではなく，ページのコンテンツの部分という<strong>構造</strong>に対するmicroformatsが定義されていればどうでしょうか？</p><p>話しは反れますが，CSSのお勉強系のサイトに，HTMLのクラス属性の設計で <strong>構造</strong> でなく <strong>用途</strong> を限定してしまい，とても恥ずかしいことになってる例の代表がよく載っていますよね． <strong>class=&quot;red&quot;</strong> とか．</p><p>＃ <a href="http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88">wikipedia</a>にも <strong>マイクロフォーマットには用途ごとに様々なものがある</strong> とか書いてあるのはどうにかしたほうが良いと思う．</p><h3>まとめ</h3><ul class="ul1"><li><strong>用途</strong> に対してmicroformatsを定義すると「１つの用途」にしか用いることができません</li><li><strong>構造</strong> に対してmicroformatsを定義すると「複数の用途」に用いることができます</li></ul><h2>Microformatsの問題点</h2><p>ついでにmicroformatsの問題点について．</p><p>microformatsはお手軽な分，全然正確ではありません．もしautopagerize_page_elementがcontentsくらい短くなったら誤爆する可能性があります．その場しのぎの解決策としてはAutoPagerizeみたいに接頭辞をつけるか，hAtomみたいに親要素にhfeedをつける といった方法があります．<a href="http://d.hatena.ne.jp/ku0522/20071108/1194514883">kuさんの記事</a>にもありますが，これはmicroformatsの限界なのでしょう．</p><p>microformats以外の方法がないかと探してみたところ，RDFaというものがありました．これはmicroformatsみたいに決まったクラスを指定したりしますが，XML名前空間を指定したりする必要があります．名前空間の指定があるので正確ですが，どこからどこまでがこの名前空間なのかという適用範囲を理解する必要があります．また，microformatsに比べてだいぶXHTMLが複雑になるので，美しくありません．microformatsでさえ面倒がってやってくれないのに，さらに数段階面倒なことはさせるのは非現実的です．</p><h3>まとめ</h3><ul class="ul1"><li>microformatsは簡単ですが正確ではありません</li><li>RDFaは正確ですが簡単ではありません</li></ul><h2>SITEINFOの問題点</h2><p>ついでにSITEINFOの問題点について．</p><p>少し前にAutoPagerizeのSITEINFOに「exampleUrlをつけるように」というお達しがでました．一度作成したSITEINFOがHTMLの変更によって無効化されることがあるため， 現在は有効なのか無効なのかの判断を機械的にできるようにするためです．それでも，その判断は別のスクリプトで行う必要があり，無効になっていた場合にwikiから外すのも人力で行う必要があります．</p><p>また，AutoPagerizeのデータを再利用する話しも出ています。</p><blockquote cite="http://piro.sakura.ne.jp/latest/blosxom/mozilla/extension/rewindforward/2007-11-05_autopagerize.htm">

 他のユーザースクリプトなりアドオンなりで前のページへのリンクの情報を使うような物もあるかもしれないし、
 ということでSiteInfoには前のページへのリンクの検出ルール（prevLink）も含めてもらえると主に僕が嬉しいです。

</blockquote><p>仮に，prevLinkを追加したとしましょう.そうなると「この値も入れて！」って言う人がきっと他にも出てきます．となると， <strong>どんな名前がどんな意味を持っているのか</strong> をプログラム間で共通のものにする必要があるでしょう．ある人がmainContentという名前を追加して，他の人がsiteContentという名前を追加したけど意味は同じ，という状態になると，とてももったいないことになります．さらに前述したようなHTMLの変更が加わると，誰が変更するのか，全部変更しなければならないのか，何を表しているかも分からない値の変更はどうするのか，分かる範囲で修正した場合はどれが未変更の値なのかをどうやって区別するのか，といった問題も発生します．</p><h3>まとめ</h3><ul class="ul1"><li>SITEINFOの正しさの保証が全自動でできない</li><li>SITEINFOの語彙が明示的に共通化されていない</li><li>HTML構造が変更されると，この２つが組み合わさる<ul class="ul2"><li>誰が，どれを 変更するのか etc</li></ul></li></ul><h2>Microformatsの先へ</h2><p>ところで，GRDDLというものが少し前に勧告されています．これはmicroformatsを利用してRDFを抽出するために，head内にlink要素としてXSLT(XSLTじゃなくても良いけど普通はXSLTみたい)を指定するものです．RDFを抽出するXSLT側に，名前空間の指定などの面倒なことを隠蔽できるので，HTML側は普通にmicroformats的なマークアップをすれば良いのです．そして，headタグのprofile属性にちょろっと書き足してlink要素を書き足すだけです．microformats的な，と書いたのは，microformats.orgで決められたmicroformatsでなくても，XSLTさえ書けばRDFを抽出できるためです．</p><p>なのでGRDDLでRDFを抽出することは，microformatsの手軽さを保ったまま正確さを獲得できます．正確さといっても，HTMLを書いた人によって保証されるだけですが．</p><h3>まとめ</h3><ul class="ul1"><li>GRDDL = microformatsの簡単さ + 正確さ</li></ul><br /><p>つかれたのでここまで．続きはまた今度．</p>			</div>
		</content>
	</entry>
</feed>

