目的
ブラウザから非CORSなWebサービスを使うために、Bookmarkletで本来のページに寄生する。
(将来の自分に向けたメモ)
環境
OS: Windows
Browser: Chrome 97
基礎
Webブラウザのブックマークのリンクにjavascript:
に続けてjavascriptの実行コードを記載。
アドレスバーに入れてもOK。ただしコピペすると"javascript:"が消えるのでそこだけ手入力。
javascript:alert("Hello");
javascript:var a=document.getElementsByTagName("body")[0];a.setAttribute("contentEditable","true"!=a.getAttribute("contentEditable"));
コード長の制限
alert("12345678901234...長い文字列...")で試行。10000文字までは問題なし。
Bookmarklet特有の話題は以上。
文法チェックと圧縮 - Google Closure Compiler
以下、サンプルコードはこれを使ってコンパイルしてます。
遅延実行 window.Function()を使えとのこと
(()=>{
window.Function('"use strict";return (alert("'+window.location+'"))')();
})();
上はalert表示するコードを生成し、それを評価(実行)する関数を、評価する。
外部リソースを取り込む fetch
どこかのWebサーバ上にjsファイルを用意してそれを取り込む。
fetch('https://kyoya-p.github.io/samples/2022/Bookmarklet/alert-test.js') //要求Promiseを生成
.then(res=>res.text()) //要求Promiseを待ち、応答Promiseを生成
.then(data=>alert(data)) //応答Promiseを待ち、結果表示Promiseを生成
※githubはCORS対応がされていて外部サイトからの参照が楽で助かる
※と思いきやCSPに阻害されるページも...
W3C CSP Level3 Draft
ともかく以降いちいちブラウザのBookmarkを書き換える必要は無くなった
fetch('https://kyoya-p.github.io/samples/2022/Bookmarklet/alert-test.js')
.then(res=>res.text())
.then(jssrc=>window.Function('"use strict";return('+jssrc+')')())
上記をBoolmarkletに変換。これをブラウザのBookmarkのURLに設定。
javascript:(()=>{fetch("https://kyoya-p.github.io/samples/2022/Bookmarklet/alert-test.js").then(function(a){return a.text()}).then(function(a){return window.Function(a)()});})()
目的のページを開いてからBookmarkを選択。
以下おまけ
Kotlin/JSで本体を作成 - IntelliJでプロジェクト作成
ファイル > 新規 > プロジェクト - 新規プロジェクトダイアログが開く
Kotlin > Browser Application を選択し次へ [JS IR compiler]を選択
例えばプロジェクト名を"WebSED"とすると関数はこの名前のオブジェクトのメンバとして実装される。
JavaScriptからKotlinを呼び出すテスト
@ExperimentalJsExport
@JsExport
fun hello() {
document.body?.sayHello()
}
- 関数に
@JsExport
を付与する - JSのモジュールシステムは Plainモード(指定なし)
確認:
-
gradlew browserRun
でブラウザを起動。"Hello from JS"が表示されていることが確認できる(これはプロジェクトのスケルトンコードによるもの) - Bookmarkletとして
javascript:WebSED.hello()
を設定し実行。"Hello from JS"がもう一行表示されればOK(開発者コンソールでやってももちろんOK)
#Kotlinで生成したjs関数をBookmarkletに
Kotlinからトランスパイルされた下記をWebに置く
build/distributions/WebSED.js
build/distributions/WebSED.js.map