人力検索と Hatena::Let とアドオンと
まずは、
Hatena::Let のコードがさみしいので、Syntax Highlight しようと思ったの。
よく見るところだから、Bookmarklet じゃなくてユーザスクリプト(アドオン)なの。
スクラッチパッドで確認したよ
(() => {
document.body.appendChild(Object.assign(document.createElement("link"), {
rel: "stylesheet",
href: "https://highlightjs.org/static/demo/styles/zenburn.css",
}));
document.body.appendChild(Object.assign(document.createElement("script"), {
src: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js",
onload: () => {
document.querySelectorAll('pre.code-raw > code').forEach(e => {
hljs.highlightBlock(e);
});
},
}));
})();
そんなに難しいことしてない。
アドオンだと動かないんだ
ブラウザツールボックスのコンソールには、こんなエラーが出てる。
ReferenceError: hljs is not defined
すぐに思い出したよ(うそ。ちょっと「あれ?」ってなった)。
chrome extension について。 ページ内から、contentscripts.js … - 人力検索はてな
Although content scripts don't by default get access to objects created by page scripts,
Content scripts - Mozilla | MDN
コンテンツスクリプトの window と、ページスクリプトの window は、同じじゃない。
だから、ページスクリプトにある window.hljs は、コンテンツスクリプトでは使えない。
window.postMessage と window.addEventListener を使うんだった
(() => {
const d_ = document;
d_.body.appendChild(Object.assign(d_.createElement("link"), {
rel: "stylesheet",
href: "//highlightjs.org/static/demo/styles/zenburn.css",
}));
d_.body.appendChild(Object.assign(d_.createElement("script"), {
src: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js",
onload: () => {
window.postMessage({
command: "do_highlight",
}, "*");
},
}));
d_.body.appendChild(Object.assign(d_.createElement("script"), {
innerHTML: `
window.addEventListener("message", ev => {
if (ev.source == window && ev.data && ev.data.command == "do_highlight") {
document.querySelectorAll('pre.code-raw > code').forEach(e => {
hljs.highlightBlock(e);
});
}
});
`,
}));
})();
きっと普通のやり方は、
- アドオンのリソースに、外部CSS と外部JS を取り込んで、tabs.insertCSS() と tabs.executeScripts() を使う
- CDN に頼るなら、コードを Bookmarklet で書いて、tabs.executeScripts() で実行する
- ヤバい感じのやつ → Sharing objects with page scripts - Mozilla | MDN