これで辞書に書かれているのと同じ順序で、同じテキストブロックに対して複数の正規表現を処理できます。置換式の中に括弧プレースホルダ($1、$2、... $9)を含めると、コンテンツブロックそのものに対して非常に高度な再帰的構文解析を実行できるようになります。
動詞で定義されるローカルプロパティは、他に2つあります。_src:では、最初の変換対象のコンテンツを指定します。defaultURL:では、URLが指定されない場合に使用するデフォルトの辞書ファイルのURLを指定します。
今回のサンプルの動詞の完全な定義をリスト3に示します。
var $ = jQuery;
CmdUtils.CreateCommand({
name:"macro",
author: { name: "Kurt Cagle", email: "kurt@oreilly.com"},
contributors: ["Kurt Cagle"],
license: "Apache License, v.2",
homepage: "http://www.xforms.org/xrx/?q=ubiquity",
description: "Performs regular expression replacements of web page content.",
help: "The macro verb takes the URL of a dictionary file (which can be set up as a default using the defaultURL property) and uses it to replace each regex term with its corresponding replacement value in either a web page (if no content is selected) or within a given selection (if one has been).",
defaultURL:"http://localhost:8080/exist/rest//db/sandbox/dictionary.xml",
takes:{"sourceURL":noun_arb_text},
preview:function(pblock,sourceURL){
this._src = CmdUtils.getHtmlSelection();
var table=<table/>;
try{
this._parseEntries(sourceURL,this._src,function(entries,str){
for each (var entry in entries){
table.tr += <tr><td>{entry.term}</td><td>{entry.expr}</td></tr>;
}
pblock.innerHTML = table.toXMLString();
});
}
catch(e){}
},
execute:function(sourceURL){
this._src = CmdUtils.getHtmlSelection();
if(this._src==null){
var doc = CmdUtils.getDocumentInsecure();
this._src=doc.body.innerHTML;
this._parseEntries(sourceURL,this._src,function(entries,str){doc.body.innerHTML=str});
}
else {
this._parseEntries(sourceURL,this._src,function(entries,str){CmdUtils.setSelection(str,{});});
}
},
_src:'',
_parseEntries:function(sourceURL,src,fn){
if (sourceURL.text == ""){
sourceURL.text = this.defaultURL;
}
jQuery.get(sourceURL.text, function(dictionaryXML){
var dictionary=$(dictionaryXML);
var entries=[];
dictionary.find('entry').each(function(){
var entry = {term:$(this).find('term').text(),
expr:$(this).find('expr').text(),
isGlobal:($(this).attr('global')=='yes')?'g':'',
caseSensitive:($(this).attr('casesensitive')=='yes')?'':'i'};
var entryRE = new RegExp(entry.term,entry.isGlobal+entry.caseSensitive);
entries.push(entry);
/* var arr=src.split(entry.term);
var str =arr.join(entry.expr); */
str = src.replace(entryRE,entry.expr);
src=str;
});
fn(entries,src);
});
this._src=src;
}
});
ここまでの作業の成果については、図1を参照ください。これは、2008年度アメリカ大統領選挙直前のCNNの政治面ページのショットを並べたものです。右側はマクロ適用前のページで、左側は結果を示します。
今回の例では、各候補者の姓の色が変化し、氏名が点線で囲まれ、その境界線で囲まれたボックスの上にポインタを置くと「Candidate for President」と表示されます。この機能は、非常に大きな可能性を秘めています。例えば、外部ソースからコンテンツを受け取り、そのコンテンツの配置をWebページ内で(場合によっては大幅に)変更できます。さらに、このようなマクロをブラウザの起動時またはページの再読み込み時に使用できるようにするメカニズムもインターネット上に出現しています。これらはまだ開発のアルファ段階なのでここでは説明を省きます。同様に、Ubiquityの中には、ブラウザ本体の修正を可能にするメカニズムも数多く存在します。つまり最終的には、Mozillaプラグインの構築に現在使用されている面倒でわずらわしいXPIを、Ubiquityスクリプトによって置き換えることができるかもしれません。
Ubiquityは公開されてからまだ日が浅い技術ですが、新しいタイプのWebオペレーティングシステムの基盤として以前から期待されており、大きな注目を集めています。詳しくは、Ubiquity Wikiをご覧ください。

