Hatena::ブログ(Diary)

caisuiの日記

2013.12.14

hints-ext 更新しました

更新内容は

  • inline style 禁止 対策
  • 面積のないElementが 欠ける件、実質問題なさげなレベルまで改善
  • ラベル再配置(ラベルが重ならないようにする機能)
    • 高速化(10倍くらいになった)
    • ラベルの移動処理変更
  • 細々と微調整

です。

vimperator/hints-ext.js at master ? caisui/vimperator ? GitHub



inline style 禁止

基本 CSP による inline style禁止 対策です。

また、コンテンツのcssの影響を受けなくなったので、!importが多様されているページでも崩れてしまうことがなくなりました。


CSPによって、ヒントの配置に失敗の図

f:id:caisui:20131214212749p:image


改善後

f:id:caisui:20131214212747p:image


ちなみに、test で使った簡便なCSPを吐く http server はこんなです。

https://gist.github.com/caisui/7959322


面積のないElementが 欠ける

hints-ext について - caisuiの日記の件です。

力技で組込んでみましたが、10ms程度しか差異がでなかったので採用しました。



対策前 [パソコン], [PC周辺機器]等の部位が欠けています。

f:id:caisui:20131214213246p:image


対策後

f:id:caisui:20131214213245p:image


「解決」でなく「実質問題無い」としているのは、子孫ノードすら面積が無い(あるいは子孫が存在しない)ものは検知できてないからです。



本家では、'HR'と'HT' の 部位も表示されています。

f:id:caisui:20131214214335p:image

しかし、見えていない Element なので、実質問題無いかなとしています。


従来の方式を望む場合は、

hints.fixRect0 = false;

とすれば、戻ります。



ラベル再配置

アルゴリズム変更しました。

f:id:caisui:20131214215811p:image

f:id:caisui:20131214215810p:image

と配置するようになりました。

2013.10.19

hints-ext について

現在、特定条件を満たした node が ヒントとして表示できません。

欠落に気付くことは困難なため、使用しないほうが良いと思います。



上記、"Diary"画像のリンクが奇数が表示できていないと思います。

(Windows Xp Windows 8 で確認)


a タグだけ ごまかすなら

style -name=anchor0 * a::after{ display: block; position: absolute; width: 1px; height: 1px; content: "";}

でそれっぽく改善しますが、layoutが壊れるとこがあるかもしれません。


原因

nsIDOMWindowUtils.nodesFromRect の仕様変更により、面積0(height or width 0)の Node が無視されるようになったようです。(多分 24 から 少なくとも 17は 面積0でも 出ている)


hints-ext は、nsIDOMWindowUtils.nodesFromRect を利用することにより、速度を稼いでいます。どうしましょうかね…。

2013.06.09

Smooth Scroll

vimperator/smooth-scroll.js at master ? caisui/vimperator ? GitHub


buffer の Smooth Scroll 化です。

hjkl,gg,G等ほぼ全てが Smooth Scroll になります。

ただし、<Space>は無理です。


デフォルトのスクロース時間は、300ms です。

変更したい場合は、


let smooth_scroll_duration=200

で変更できます。


以下変更にあたって、bufferの挙動変更点です。


  • window決め打ち系(g,GG等) の スクロール対象も hjklと同様 caret 位置から遡る
  • frame,iframeも遡り scrollbarを探します。
  • 画面外スクロールバーは無視

これ mozRequestAnimationFrame を使ってみたのですが、

私の環境では60fpsでています。




最後に、問題点です。


他のscroll と干渉(競合?)します。

アニメーション描画の都合上途中で、

他のスクロールが発生しても影響を受けずにそのまま続きを描写します。


どうしても、途中で操作したいなら、

buffer経由

あるいは

plugins.smoothScroll.scrollBy(node, x, y);

plugins.smoothScroll.scrollTo(node, x, y);

を 経由して干渉する必要があります。

2013.05.27

hints-ext 更新しました。

hints-ext.js を 更新しました。


https://github.com/caisui/vimperator/blob/master/plugin/hints-ext.js


更新内容はざっくり 以下2点です。


  1. Hint Node が document から 破棄されても、そのまま動くように修正
  2. 高さを持つ ノードを子孫に持つ インラインノードの 表示方法の変更

1 は、document を 読み込み中に HaH を表示すると 動作しなくなることがある問題の改修です。


また、style sheet が 遅延して読み込みまれてがっつり位置がズレても、再配置できるように

redraw 関数を追加しました。(末尾 map の サンプルを参照)


2 は、

<a href="#"><img src="..."/></a>

のような Node 対策です。


f:id:caisui:20130527213817p:image


となっていたものが


f:id:caisui:20130527213818p:image


となります。


デフォルトで ON なので、以前のよう(=無効)にしたい場合は、


rc file に

let disable_adj_inline=1

で 無効になります。



最後に、hint の マップ設定例です。hints-ext.js を load後に指定して下さい。



" runtimepath 配下の pluginを全て読み込む
loadplugins

js<<END
(function() {
    // hint の 再描画
    hints.addSimpleMap("<C-l>", function() { this.redraw(); });
    // hint node 重なり除去
    hints.addSimpleMap("<C-S-l>", function() { this.relocation(); } ); 
    // 誤爆防止
    hints.addSimpleMap(["<C-n>", "<C-t>", "<C-f>", "<C-g>"], function() { });
    // インライン ノードの表示方法をトグル
    hints.addSimpleMap("<C-i>", function() { this.toggleInlineAdj(); });
})();
END

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))