GreaseMonkey Driven Development
cho45(さとう) / lowreal.net
- 口癖:めんどい
はなしの内容:
- GDD とか言っちゃってますけど、user.js の入門。
- いつでも user.js かけるように
- ちょっと Opera ?
GM インスコしたけど...
- 保存する -> スクリプト書き換える -> スクリプトリロード -> Install Script クリッコ -> 対象ページリロード -> デバッグ
- そんなの結局書くのがめんどい
とかそんな人向け。
最初は自分も毎回 Install Script してました。なんだこれめんどくせーよとか思ってました。
バリバリ書きまくってる人は知りません。
とりあえずエディタの設定はしよう
- about:config
- greasemonkey.editor
例: C:\apps\xyzzycli.exe
これで設定画面の Edit から開けるように
いや何も設定されてないと選択ダイアログが開くはずだけど...
GM では微妙なタイミングででてくるエディタ選択画面。なんか挙動が謎いので自分で設定しよう。
これで設定の Edit から編集できるようになるで、とりあえず既存スクリプト修正は楽に
いいテキストエディタを使おう
言うまでもない。
ともあれ開発を容易に1
どこでも適用できる user.js を作っとく。
test.user.js(なんでもいい)@include *
あとてきとーに関数の雛形書いて保存しておく
てんぷれ例
// ==UserScript==
// @name Test
// @description Test
// @namespace http://lowreal.net/
// @include *
// ==/UserScript==
(function () {
/*
GM_xmlhttpRequest({
method : "GET",
url : url,
headers : {
"User-Agent":"monkeyagent",
"Accept":"text/monkey,text/xml",
},
onload : function (req) {
var doc = new XML(req.responseText.replace(/^<\?xml.+?\?>/, ''));
},
onerror : function (req) {
alert(req.responseText);
}
});
*/
function $N (name, attr, childs) {
var ret = document.createElement(name);
for (k in attr) {
if (!attr.hasOwnProperty(k)) continue;
v = attr[k];
if (k == "class") {
ret.className = v;
} else {
ret.setAttribute(k, v);
}
}
switch (typeof childs) {
case "string": {
ret.appendChild(document.createTextNode(childs));
break;
}
case "object": {
for (var i = 0, len = childs.length; i < len; i++) {
var child = childs[i];
if (typeof child == "string") {
ret.appendChild(document.createTextNode(child));
} else {
ret.appendChild(child);
}
}
break;
}
}
return ret;
}
// Using XPath Expression Object, snapshot is buggy (crash@Fx1.5.01)
// exp = "string(/)";
// var resolver = document.createNSResolver(document.documentElement);
// var exp = document.createExpression(exp, resolver);
// var result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
function $X (exp, context) {
if (!context) context = document;
var resolver = function (prefix) {
var o = document.createNSResolver(context)(prefix);
return o ? o : (document.contentType == "text/html") ? "" : "http://www.w3.org/1999/xhtml";
}
var exp = document.createExpression(exp, resolver);
var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
var ret = [];
for (var i = 0, len = result.snapshotLength; i < len ; i++) {
ret.push(result.snapshotItem(i));
}
return ret;
}
}
return null;
}
function d(args) {
var out = [];
for (var i = 0; i < arguments.length; i++) out.push(arguments[i]);
if (navigator.userAgent.match(/Firefox/)) {
dump(out.join(" ") + "\n");
} else {
// alert(out.join(" "));
}
}
})();
ともあれ開発を容易に2
そんな感じで test.user.js をインストール
インストール済みのを Edit を押してエディタでひらきっぱ
ともあれ開発を容易に3
他人のスクリプトをパクる
他人のスクリプト読むと「あ~アレね~」とか思って世界が広がるます。
そういうことで
- ブラウズしてて何か思いつく
- 開きっぱなしの test.user.js を編集してゴリゴリ書く。
- よくね? と思ったら分離する。
- 「こりゃだめだ」と思ったら諦めてコメントアウトして、ウェブブラウズ再開
ポイントまとめ
なんというか
- 毎回 Install Script とかやらなくていい
- ページリロードじゃなくて、ただのページ移動でも再実行される。
- というかいっそ、profile の gm_scripts ディレクトリを開きっぱなしでもいい
- 無理して書くことない
リロードだとキャッシュが最新か確かめたりするので、ページ移動のほうがいいときもある。画像が多いページとか
GDD
ヒントだけ。
ページ内の window オブジェクトは GM では unsafeWindow としてアクセスできる。
だからそのサイトのスクリプトを置き換えたりすることもできる。
LDR 拡張系 user.js はコレ
unsafeWindow 使用時の注意
unsafeWindow は unsafeWindow という名の通り、安全ではないオブジェクトです。サイト内スクリプトが触れる window オブジェクトをいぢくるわけですから、unsafeWindow 以下のオブジェクトに GM_xmlhttprequest などを渡してしまうと (単に引数に GM_* を渡すだけでも、コールスタックから見える状態になってしまう場合がある) 、脆弱性の引き金になります。unsafeWindow を使って書いたものを公開する場合は慎重になるべきです。
このため、unsafeWindow オブジェクトは常に「unsafeWindow」としてアクセスするように心がけ、可能な限り他の名前をつけない (代入しない) ようにし、関数の引数に GM_* は絶対に渡さないようにすべきです。
詳しくは GreaseMonkey のドキュメント を読んでください。
おまけ
Opera 向け注意
- 実行タイミングが違う
(onload 時) - E4X が使えない
(innerHTML + XPath に) - GM_* 系関数は使えない
(ラッパを使うべし)
XMLHttpRequest は難しいことしないとドメインを超えられない。
Opera では GreaseMonkey ほぼ互換のファイル形式が使えます。
最近 Opera9 がリリースされ、XPath などがサポートされました。
GreaseMonkey では DOM オブジェクトが構築できた時点でスクリプトが実行されます。