Hatena::ブログ(Diary)

caisuiの日記

2013.01.12

vimperator3.6 について

vimperator3.6で e4x を除去 し Template String で 代替するパッチがマージされました。

結果、pluginが影響を受けますので思い付くままに記載したいと思います。


vimperator 3.5で困ってないかたは、 バグの洗い出しや、pluginの 対応が終るまで移行しないほうが良いと思います。

(javascript.options.xml.chrome=true でも軽微ですが、副作用があります)


Template Stringの 正しい仕様は、http://wiki.ecmascript.org/doku.php?id=harmony:quasisを参照下さい。


現段階において、Firefox にTemplate Stringは実装されいません。

vimperator side で 現行javascriptで動くように変換して実行しています。


5行で書かれた Template String は 5行で変換してるので、エラー行番号は似た位置が表示されるはずですが、

記述したそのものが実行されるわけではありませんので plugin 開発においてやっかいな要因になると思います。


以下 私の理解した範囲で実装したものを説明します。


Template String とは

一言で言うと、heredoc っぽい形式で記述できる関数の糖衣構文です。

tag`Literal1${obj1}Literal2${obj2}Literal3`

と記載すると


tag({raw: ["Literal1", "Literal2", "Literal3"],cooked: ["Literal1", "Literal2", "Literal3"]}, [(obj1), (obj2)])

に相当します。

(cooked, raw は、Literal部位のエスケープシーケンスの解釈が変わります。詳しくは、http://wiki.ecmascript.org/doku.php?id=harmony:quasis を参照下さい。)


また、tagは省略することができ、その場合はraw tag 相当が適用されます。

(raw tag は、単純にLiteral と obj を 連結していく tagです)

var name = 'hoge';
var s = `こんにちは${hoge}さん
さようなら${hoge}さん`;

は、

var name = 'hoge';
var s = ("こんにちは" + (hoge) + "さん\n\
さようなら" + (hoge) + "さん");

に相当します。


tag の 自作

関数を作成すれば使えます。

function test(a, b) {
    var raw = a.raw;
    var i, j, s = "";
    for (i = 0, j = b.length; i < j; i++)
        s += raw[i] + "(" + String(b[i]) + ")";
    s += raw[i];
    return s;
}

で 埋め込み変数を括弧で囲うraw tag の 亜種が完成となります。


また、返り値が文字列である必要もありませんので、

function dom(a, b) {
    var raw = a.raw;
    var i, j, s = "";
    // サンプル用の 簡易実装のため文脈依存のエスケープ処理はしてません
    for (i = 0, j = b.length; i < j; i++)
        s += raw[i] + String(b[i]);
    s += raw[i];
    var ps = new DOMParser;
    var doc = ps.parseFromString(s, "text/html");
    var range = document.createRange();
    range.selectNodeContents(doc.body);
    return range.extractContents();
}

var node = dom`<table>
    <tr><td>1</td><td>2</td></tr>
    <tr><td>1</td><td>2</td></tr>
    <tr><td>1</td><td>2</td></tr>
    <tr><td>1</td><td>2</td></tr>
</table>`;

で DOMが生成できます。

plugin について

e4x を 使用しているものは全て動きません。

e4x 固有の文法を使用している場合は、代替案を模索することになります。

以下 変更 例です。

dom の生成
util.xmlToDom(<a href={url}>{text}</a>, document)

util.xmlToDom(xml`<a href=${url}>${text}</a>`, document)
plugin help
var INFO = <plugin name="hoge" version="0.1.0"
    href="xxxx"
    summary="yyy"
    xmlns="http://vimperator.org/namespaces/liberator">
    省略
</plugin>;

var INFO = xml`<plugin name="hoge" version="0.1.0"
    href="xxxx"
    summary="yyy"
    xmlns="http://vimperator.org/namespaces/liberator">
    省略
</plugin>`;
XUL生成
liberator.echo(<datepicker type="grid" xmlns={XUL}/>)

liberator.echo(xml`<datepicker type="grid" xmlns={XUL}/>`)

あるいは、

liberator.echo(xml`<xul:datepicker type="grid"/>`)

用は、xmlns:html と xmlns:xul と xmlns:nsをこっそり定義しちゃってます。

heredoc
node.style.cssText = <![CDATA[
color: red;
border: 1px solid blue;
]]>.toString();

node.style.cssText = `
color: red;
border: 1px solid blue;
`;
e4x の連結

結構差異がでます。(operator + や operator += は できません)

function hoge1(node1, node2) {
    return <pre>{node1 + node2}</pre>
}
function hoge2(array) {
    var x = new XML;
    for (var i = 0, j = array.length; i < j; i++) {
        x += array[i];
    }
    return x;
}

function hoge1(node1, node2) {
    return xml`<pre>${node1}${node2}</pre>;
}
function hoge2(array) {
    var x = xml``;
    for (var i = 0, j = array.length; i < j; i++) {
        x = xml`${x}${array[i]}`;
    }
    return x;
}
その他文法

@xx や .* 等は、DOMParserを使用してdomに変換すれば、似たことができます。


xml という 変数名

使うと xml tag が 使用できません!

変数のxml化

template.maybeXML経由だと エスケープされません。

var html = "<a href='#sample'>xxx</a>";
liberator.echo(template.maybeXML(html))
トラックバック - http://d.hatena.ne.jp/caisui/20130112/1358003289