*
タグを日本語の字形を教科書体の中から順に変更、他*
タグを絵文字に使われるフォントの中から順に変更*
タグの行の高さを固定*
タグを日本語の字形を変更*
タグを字形を分数や他に変更ここではMozilla系ブラウザ(Firefox/SeaMonkey/Camino)に関するちょっとしたコツを扱います。
Mozilla 系の拡張機能は XUL/XPCOM 技術基盤による実装でしたが、Firefox は Google Chrome とともに WebExtension (ブラウザ拡張機能) へと移行しました。よって、かつての拡張機能は Firefox では使えなくなっています。
また、拡張機能のセキュリティアップデートについては XUL/XPCOM においては特に注意を払う必要があります。よって、更新が滞っている拡張機能などの使用は控えた方が懸命です。
ここでは Firefox/SeaMonkey について筆者がお勧めの拡張機能をまとめておきます。
Firefox.app/Contents/Resources/omni.ja
」のなかにあるようで、仕方がないので各ユーザプロファイル向けとして「~/Library/Application Support/Firefox/Profiles/*.*/searchplugins/
」に置いておくしかないようです(Firefox 34.0 からすべてのユーザ向けの検索プラグインを置いておく場所が変わってしまいました。今は「Firefox.app/Contents/Resources/browser/searchplugins/
」に置いておけば良いようです(Firefix 21.0 からすべてのユーザ向けの検索プラグインを置いておく場所が変わってしまいました。以前は「Firefox.app/Contents/MacOS/searchplugins/
」でしたが、今は「Firefox.app/Contents/MacOS/browser/searchplugins/
」に置いておけば良いようです))。ちなみに、私は以下の追加の検索プラグインを使っています。但し、(*)が付いたものは最近のデフォルトにて重なるものです。
以下、ブックマークレットのリンクの先頭に添えてあるのは、バージョン確認のための CRC32 値です。ブックマークレットの文字列は読み辛いので、ブックマーク管理にそのままドラッグ&ドロップしてタイトルとともに CRC32 値と保持し、手元の版との違いを気付きやすくしています。
Bookmarklet でブラウザをさらに便利に扱うことが出来ます。下記のような Javascript コードを思いついたら、bookmarkletify and unbookmarkletify でエンコードしてブックマークに登録しましょう。そのようにしたものを下記に紹介します。さらにウェブ等でそれを紹介したければ、ソースを preify and unpreify にて pre
タグに記述可能にするといいと思います。
ブラウザの「タブの複製」は履歴等も新たなタブに複製されますが、これは閲覧している URL を別タブにて再表示するためのブックマークレットです。そのページはそのままに新たに URL を打ち直してみたい時に重宝します。
javascript: window.open(location.href, '_blank', null); void(0);bookmarklet: (
e0945da3
) duplicate URL
閲覧している URL を Google キャッシュに切り替えるブックマークレットです。但し、URL が file:
などのローカルファイルの場合は何もしません。
javascript: if (document.URL.match(/^file:\/\//) || document.URL.match(/^https?:\/\/localhost[\/:]/) || document.URL.match(/^https?:\/\/.*\/local\//)) { console.log("location error:\n" + document.URL); } else if (!document.URL.match(/^https?:\/\/webcache\.googleusercontent\.com\/search\?q=cache:/) && document.URL.match(/^https?:\/\//)) { location.href = 'https://webcache.googleusercontent.com/search?q=cache:' + location.href; } else { console.log("location error:\n" + document.URL); }bookmarklet: (
a47a9c36
) cacheify URL
閲覧している URL を WayBackMachine(archive.org) に切り替えるブックマークレットです。但し、URL が file:
などのローカルファイルの場合は何もしません。
javascript: if (document.URL.match(/^file:\/\//) || document.URL.match(/^https?:\/\/localhost[\/:]/) || document.URL.match(/^https?:\/\/.*\/local\//)) { console.log("location error:\n" + document.URL); } else if (!document.URL.match(/^http:\/\/liveweb\.archive\.org\//) && document.URL.match(/^https?:\/\//)) { location.href = 'http://liveweb.archive.org/' + location.href; } else { console.log("location error:\n" + document.URL); }bookmarklet: (
aa1628cd
) archive URL
ローカルホストのウェブサーバでウェブ開発を行い、完成したらグローバルアドレスの公開ホストへ上げるなどはよくされていることと思われます。これは閲覧している URL のローカルホストと公開ホストを切り替えるブックマークレットです。host
変数を書き換えて利用してください。
javascript: (function () { const host = 'www.aihara.co.jp'; const localhost = 'localhost'; const res = [ [ new RegExp('^(https?://)' + host.replace(/\./, '\.') + '(/.*)$'), `http://${localhost}$2` ], [ new RegExp('^(https?://)' + localhost.replace(/\./, '\.') + '(/.*)$'), `$1${host}$2` ], ]; if (document.URL.match(res[0][0])) { location.href = location.href.replace(res[0][0], res[0][1]); console.log("global:\n" + document.URL + '\n' + location.href); } else if (document.URL.match(res[1][0])) { location.href = location.href.replace(res[1][0], res[1][1]); console.log("local:\n" + document.URL + '\n' + location.href); } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
0b18e980
) localhost/unlocalhost URL
主旨は同じですが、別タブで切り替え先のホストを開くプックマークレットも作成しました。正直こちらの方が便利です。
javascript: (function () { const host = 'www.aihara.co.jp'; const localhost = 'localhost'; const res = [ [ new RegExp('^(https?://)' + host.replace(/\./, '\.') + '(/.*)$'), `http://${localhost}$2` ], [ new RegExp('^(https?://)' + localhost.replace(/\./, '\.') + '(/.*)$'), `$1${host}$2` ], ]; if (document.URL.match(res[0][0])) { const location_href = location.href.replace(res[0][0], res[0][1]); window.open(location_href, '_blank', null); console.log("global:\n" + document.URL + '\n' + location_href); } else if (document.URL.match(res[1][0])) { const location_href = location.href.replace(res[1][0], res[1][1]); window.open(location_href, '_blank', null); console.log("local:\n" + document.URL + '\n' + location_href); } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
29f63b58
) duplicate localhost/unlocalhost URL
ところで、似たような用途で以下のような URL をブックマークレット一つで置き換えたいとも思いましたが、URL が file://
でも Javascript が発動するので機能するのですが、https?://
からは file://
への参照は許可されていないので機能しません。ちょっと不便ですが一応、紹介しておきます。
file:///home/taiji/public_html/mozilla/index.html
↔︎ http://localhost/~taiji/mozilla/index.html
3a80526c
) duplicate file → localhost URL
ドラフトサイト (~webmaster 等) と公開サイトを切り替えます。
javascript: (function () { const tildeuser = '~webmaster'; const res = [ [ new RegExp('^(https?://[^/]+/)(?:' + tildeuser.replace(/\./g, '\.') + `/)(.*)$`), `$1$2` ], [ new RegExp('^(https?://[^/]+/)(?!' + tildeuser.replace(/\./g, '\.') + `/)(.*)$`), `$1${tildeuser}/$2` ], ]; if (document.URL.match(res[0][0])) { location.href = location.href.replace(res[0][0], res[0][1]); console.log("draft:\n" + document.URL + '\n' + location.href); } else if (document.URL.match(res[1][0])) { location.href = location.href.replace(res[1][0], res[1][1]); console.log("public:\n" + document.URL + '\n' + location.href); } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
7336ac9a
) webmaster/unwebmaster URL
主旨は同じですが、別タブで切り替え先のサイトを開くブックマークレットも作成しました。どちらでもお好きな方で。
javascript: (function () { const tildeuser = '~webmaster'; const res = [ [ new RegExp('^(https?://[^/]+/)(?:' + tildeuser.replace(/\./g, '\.') + `/)(.*)$`), `$1$2` ], [ new RegExp('^(https?://[^/]+/)(?!' + tildeuser.replace(/\./g, '\.') + `/)(.*)$`), `$1${tildeuser}/$2` ], ]; if (document.URL.match(res[0][0])) { const location_href = location.href.replace(res[0][0], res[0][1]); window.open(location_href, '_blank', null); console.log("draft:\n" + document.URL + '\n' + location_href); } else if (document.URL.match(res[1][0])) { const location_href = location.href.replace(res[1][0], res[1][1]); window.open(location_href, '_blank', null); console.log("public:\n" + document.URL + '\n' + location_href); } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
386356d1
) duplicate webmaster/unwebmaster URL
Google 翻訳で現在のページ全体もしくは選択された部分のテキストを日本語に翻訳します。URL が file:
などのローカルファイルでも善処してくれるので便利です。
javascript: { const sl = 'auto', tl = 'ja'; let selection, text, url; if ((selection = (text = document.getSelection().toString()).length > 0) || ((text = document.body.innerText) && (location.protocol.match(/^file:$/) || location.host.match(/^localhost$/)))) { url = 'https://translate.google.co.jp/?sl=' + sl + '&tl=' + tl + '&text=' + encodeURIComponent(text) + '&op=translate'; } else { url = 'http://translate.google.com/translate?hl=ja&sl=' + sl + '&tl=' + tl + '&u=' + encodeURIComponent(location.href); } void window.open(url, selection ? '_blank' : '_tab', selection ? 'width=1280, height=800, scrollbars=yes, noopener=yes, noreferrer=yes' : 'noopener=yes, noreferrer=yes'); }bookmarklet: (
40e2ba64
) translate into ja URL6d5198e9
) multi translate into ja URL … マルチ翻訳ウェブサービスに対応(サービス提供側による制限が生じること多々あり)
Google 翻訳で現在のページ全体もしくは選択された部分のテキストを英語に翻訳します。URL が file:
などのローカルファイルでも善処してくれるので便利です。
javascript: { const sl = 'auto', tl = 'en'; let selection, text, url; if ((selection = (text = document.getSelection().toString()).length > 0) || ((text = document.body.innerText) && (location.protocol.match(/^file:$/) || location.host.match(/^localhost$/)))) { url = 'https://translate.google.co.jp/?sl=' + sl + '&tl=' + tl + '&text=' + encodeURIComponent(text) + '&op=translate'; } else { url = 'http://translate.google.com/translate?hl=ja&sl=' + sl + '&tl=' + tl + '&u=' + encodeURIComponent(location.href); } void window.open(url, selection ? '_blank' : '_tab', selection ? 'width=1280, height=800, scrollbars=yes, noopener=yes, noreferrer=yes' : 'noopener=yes, noreferrer=yes'); }bookmarklet: (
267631fa
) translate into en URLd51aa733
) multi translate into en URL … マルチ翻訳ウェブサービスに対応(サービス提供側による制限が生じること多々あり)
閲覧中の文書の HTML を検証 (Validate) します。URL が file:
などのローカルファイルでも善処してくれるので便利です。
javascript: (function () { function ya_preify(value) { return (new Option(value)).innerHTML; } function ya_unpreify(value) { let e = new Option(); e.innerHTML = value; return e.innerText; } if (document.URL.match(/^file:\/\//) || document.URL.match(/^https?:\/\/localhost[\/:]/) || document.URL.match(/^https?:\/\/.*\/~webmaster\//) || document.URL.match(/^https?:\/\/.*\/local\//)) { { const url = 'https://validator.w3.org/check'; const serialized_document = (new XMLSerializer()).serializeToString(document); let w = window.open('about:blank', '_blank'); w.document.open(); w.document.write(`<!doctype html> <html lang="ja"> <head> <title>validate HTML</title> <meta charset="utf-8"/> </head> <body> <form method="post" enctype="multipart/form-data" action="${url}"> <textarea name="fragment">${ya_preify(serialized_document)}</textarea> <select name="doctype"><option value="Inline" selected="selected">(detect automatically)</option></select> <input type="submit"/> </form> </body> </html>`); w.document.close(); let form = w.document.getElementsByTagName('form')[0]; form.submit(); } } else if (document.URL.match(/^https?:\/\//)) { { const url = "http://validator.w3.org/check?charset=(detect+automatically)&doctype=Inline&group=0&uri=" + escape(document.URL); console.log(url); window.open(url, '_blank'); } } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
cb67378b
) validate HTML [2022/01/28] function preify() をブラウザの特性を利用したものに置き換えました。
閲覧中の文書の CSS を検証 (Validate) します。URL が file:
などのローカルファイルでも善処してくれるので便利です。
javascript: (function () { function ya_preify(value) { return (new Option(value)).innerHTML; } function ya_unpreify(value) { let e = new Option(); e.innerHTML = value; return e.innerText; } if (document.URL.match(/^file:\/\//) || document.URL.match(/^https?:\/\/localhost[\/:]/) || document.URL.match(/^https?:\/\/.*\/~webmaster\//) || document.URL.match(/^https?:\/\/.*\/local\//)) { { const url = "http://jigsaw.w3.org/css-validator/validator"; const serialized_document = (new XMLSerializer()).serializeToString(document); let w = window.open('about:blank', '_blank'); w.document.open(); w.document.write(`<!doctype html> <html lang="ja"> <head> <title>validate CSS</title> <meta charset="utf-8"/> </head> <body> <form method="post" enctype="multipart/form-data" action="${url}"> <textarea name="text">${ya_preify(serialized_document)}</textarea> <select name="profile"><option selected="selected" value="css3svg"></option></select> <select name="usermedium"><option selected="selected" value="all"></option></select> <select name="type"><option selected="selected" value="none"></option></select> <select name="warning"><option value="2" selected="selected"></option></select> <input type="hidden" name="lang" value="ja"/> <input type="submit"/> </form> </body> </html>`); w.document.close(); let form = w.document.getElementsByTagName('form')[0]; form.submit(); } } else if (document.URL.match(/^https?:\/\//)) { { const url = "http://jigsaw.w3.org/css-validator/validator?profile=css3svg&usermedium=all&warning=2&vextwarning=&uri=" + escape(document.URL); console.log(url); window.open(url, '_blank'); } } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
479381dd
) validate CSS [2022/01/28] function preify() をブラウザの特性を利用したものに置き換えました。
閲覧中の文書の HTML の国際化を検証 (Validate) します。これは URL が file:
などのローカルファイルでは検証できませんので、公開済みの URL 専用となります。URL が file:
などのローカルファイルでも善処してくれるように出来ました、ので便利です。
javascript: (function () { if (document.URL.match(/^file:\/\//) || document.URL.match(/^https?:\/\/localhost[\/:]/) || document.URL.match(/^https?:\/\/.*\/~webmaster\//) || document.URL.match(/^https?:\/\/.*\/local\//)) { { const url = "https://validator.w3.org/i18n-checker/check"; const serialized_document = (new XMLSerializer()).serializeToString(document); const w = window.open('about:blank', '_blank'); w.document.open(); w.document.write(`<!doctype html> <html lang="ja"> <head> <title>validate I18N</title> <meta charset="utf-8"/> </head> <body> <form method="post" enctype="multipart/form-data" action="${url}"> <select name="mimetype"><option value="html" selected="selected">text/html</option></select> <input type="submit"/> </form> </body> </html>`) w.document.close(); const form = w.document.getElementsByTagName('form')[0]; form.addEventListener('formdata', function (ev) { const file = new File([ serialized_document, ], null, { type: 'text/html', }); ev.formData.append('file', file); }); form.submit(); } } else if (document.URL.match(/^https?:\/\//)) { { const url = "https://validator.w3.org/i18n-checker/check?uri=" + escape(document.URL) + "#validate-by-uri+"; window.open(url, '_blank'); } } else { console.log("location error:\n" + document.URL); } })();bookmarklet: (
0b42e474
) validate I18N
たまにブラウザの「戻る」ボタンやショートカットで、戻れないサイトがあります。マイクロソフトのページに多いのですが、ブラウザの「戻る」ボタンを長押ししてみると、1ページのつもりが2ページ閲覧していることになっているのですよね。なので、1つ戻ると自動転送で進んでしまうので、普通には戻れないのです。履歴から2つ前を選んで戻ることはできます。素早く「戻る!戻る!」とすれば(上手くすれば2つ前に)戻れます。
このブックマークレットはブラウザの履歴において「2つ戻る」ボタン代わりです。問題提起として、このようなページを作成するサイトが無くなることを祈って。
javascript:window.history.go(-2);bookmarklet: (
fdd1f837
) history back2 URL
狭い画面解像度でページを閲覧したらどのように見えるか、別ウィンドウで確認します。Firefox のかつての拡張機能 prefbar にはウィンドウをリサイズするプルダウンメニューがありましたが、その代替となります。
javascript: void window.open(location.href, "_blank", "width=640, height=480, menubar=false, toolbar=false, location=false, status=false, resizable=true, scrollbars=true, noopener=true, noreferrer=true");bookmarklet: duplicate VGA window URL ﹘ 640x480 のウィンドウで閲覧中のページを開く
ブログ記事などページ番号が指定されている URL の数字を増分します。
javascript: { location.href = location.href.replace(/(\?.*?p(?:age)?=)(\d+)/, (m,p1,p2)=>p1+(parseInt(p2)+1)); }bookmarklet: (
f99af9a4
) ++page URL
ブログ記事などページ番号が指定されている URL の数字を減分します。
javascript: { location.href = location.href.replace(/(\?.*?p(?:age)?=)(\d+)/, (m,p1,p2)=>p1+(parseInt(p2)-1)); }bookmarklet: (
112f33e7
) --page URL
Amazon の商品のページの URL には長々と商品名などが含まれています。人に紹介するときには必要最小限の短い URL で伝えたいものです。
javascript: (function() { const reps = [ [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:dp\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:gp\/reader\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:gp\/product(?:\/[^\/]*)?\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:exec\/obidos(?:\/[^\/]*)*\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], ]; for (const [ re, p ] of reps) { if (location.href.match(re)) { location.href = location.href.replace(re, p); return; } } console.log(`location error: ${location.href}`); })();bookmarklet: (
e5164bef
) shorten amazon URL
Amazon だけでなく Youtube の URL にも余分な情報が付加されていることがあり、それを短くします。
javascript: (function() { const reps = [ [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:dp\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:gp\/reader\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:gp\/product(?:\/[^\/]*)?\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.amazon(?:\.co\.jp|\.com))\/?.*?(?:exec\/obidos(?:\/[^\/]*)*\/)([0-9A-Z]{10})(?:[\/?].*)?$/, '$1/dp/$2' ], [ /^(https?:\/\/www\.youtube\.com\/watch\?v=)([^&]*)(&.*)?$/, '$1$2' ], ]; for (const [ re, p ] of reps) { if (location.href.match(re)) { location.href = location.href.replace(re, p); return; } } console.log(`location error: ${location.href}`); })();bookmarklet: (
25ced1df
) shorten amazon URL
このような <a href="http://google.com/" target="_blank">リンク</a> は生成元のサイトのストレージアクセスが生成先に許可されてしまうなどのセキュリティ驚異があります。本来なら、<a href="http://google.com/" target="_blank" rel="noopener">リンク</a> のように rel 属性に noopener
が無ければなりません。閲覧中のページのそのようなリンクにその属性を指定するブックマークレットとなります。文書に変更があった場合にはアラートがでますので、セキュリティチェックに使えます。
javascript: function noopener_urls(node) { let r = false; for (const target of [ "_blank", "_tab", ]) { const es = Array.from(node.querySelectorAll(`a[href][target=${target}][rel=noopener]`)); for (const e of node.querySelectorAll(`a[href][target=${target}]`)) { if (es.includes(e)) continue; console.log(e); e.rel = 'noopener'; r = true; } } if (r) alert('a[href][target=_blank|_tab][rel!=noopener] found'); } noopener_urls(document.body);bookmarklet: (
443aad03
) noopener URLsa0d1965c
) noreferer URLs … 同様に noreferer
を指定するブックマークレット、アラート無し
次節で紹介している prefbar は、Firefox 57 から XUL(XML User Interface Language)/XPCOM(Cross Platform Component Object Model) が廃止され、WebExtensions に移行したことにより、多くのボタンが使えなくなっています。よって、ブックマークレットとして代替の機能をここで紹介します。
閲覧中の文書で、なぜかリンクが貼られていない URL にリンクを貼ります(リンクを貼ったら「管理人」とやらからクレームの時代がかつてありました。しかし、その名残が未だあるらしく、リンクを張らずに URL だけを記載するサイトが企業サイトにさえ、あります。引用する権利は法律で認められているので、これは不便が無いように手元でリンクを貼ります)。
javascript: function link_urls(node) { const parentNode = node.parentNode; if (node.nodeType == 3) { if (node.nodeValue.match(/\b(h?ttp(s?):\/\/(\S+))/)) { const url = 'http' + RegExp.$2 + '://' + RegExp.$3; const tag_a = document.createElement('a'); tag_a.href = url; tag_a.appendChild(document.createTextNode(RegExp.$1)); parentNode.insertBefore(document.createTextNode(RegExp.leftContext), node); parentNode.insertBefore(tag_a, node); parentNode.insertBefore(document.createTextNode(RegExp.rightContext), node); parentNode.removeChild(node); console.log(tag_a); } } else if (node.nodeType == 1 && !/^(style|script|iframe|pre|a)$/i.test(node.tagName)) { for (const child of node.childNodes) { link_urls(child); } } } link_urls(document.body);bookmarklet: (
77c37609
) link URLs
閲覧中の文書で、なぜか一拍するジャンパーが咬まされているリンクを通常のリンクに直します(これは広告を咬ましたいサイトに多いです。消費者の権利として広告をみない権利を行使するのはブラウザの「広告ブロック」機能と同様、その都度行使できます)。
javascript: function normalize_urls(node) { let tag_a_list = node.getElementsByTagName('a'); for (const tag_a of tag_a_list) { if (tag_a.href.match(/^http(s?):\/\/(ime\.nu\/|2ch\.io\/|jump\.[25]ch\.net\/\?)/)) { tag_a.href = tag_a.href.replace(/^http(s?):\/\/(ime\.nu\/|2ch\.io\/|jump\.[25]ch\.net\/\?)/, 'http$1://'); if (tag_a.href.match(/^http:\/\/http(s?):?\/\//)) { tag_a.href = tag_a.href.replace(/^http:\/\/http(s?):?\/\//, 'http$1://'); } console.log(tag_a); } } } normalize_urls(document.body);bookmarklet: (
34721884
) normalize URLs
閲覧中の文書内の画像や動画のリンクをインライン埋め込みコンテンツに仕立てます。
javascript: function embed_hrefs(node) { const tag_a_list = node.getElementsByTagName('a'); for (const tag_a of tag_a_list) { let flag = false; if (tag_a.href.match(/\.(jpe?g|gif|png)$/i)) { tag_a.innerHTML += '<img src="' + tag_a.href + '" border=0 style="max-width: 640px;" referrerpolicy="no-referrer"/>'; flag = true; } else if (tag_a.href.match(/^(https?:\/\/www\.nicovideo\.jp\/)watch\/(.*)$/i)) { const src = RegExp.$1.replace(/www\./, 'ext.') + 'thumb_watch/' + RegExp.$2 + '?w=640&h=480'; tag_a.innerHTML += '<script type="text/javascript" src="' + src + '"></script>'; flag = true; } else if (tag_a.href.match(/^(https?:\/\/www\.dailymotion\.com\/)video\/(.*)$/i)) { const src = RegExp.$1 + 'embed/video/' + RegExp.$2; tag_a.innerHTML += '<iframe width="640" height="480" src="' + src + '" frameborder="0" allowfullscreen></iframe>'; flag = true; } else if (tag_a.href.match(/^(https?:\/\/www\.youtube\.com\/)watch\?v=(.*)$/i)) { const src = RegExp.$1 + 'embed/' + RegExp.$2 + '?feature=player_detailpage'; tag_a.innerHTML += '<iframe width="640" height="480" src="' + src + '" frameborder="0" allowfullscreen></iframe>'; flag = true; } else if (tag_a.href.match(/^(https?:\/\/youtu\.be\/)(.*)$/i)) { const src = 'https://www.youtube.com/' + 'embed/' + RegExp.$2 + '?feature=player_detailpage'; tag_a.innerHTML += '<iframe width="640" height="480" src="' + src + '" frameborder="0" allowfullscreen></iframe>'; flag = true; } if (flag) console.log(tag_a); } } embed_hrefs(document.body);bookmarklet: (
633cc3c0
) emded URLs [2022/02/04] 画像の埋め込み大き過ぎ、他、改良しました。bd2e3094
) link, normalize & embed URLs [2022/02/04] 同上、改良しました。
閲覧中の文書のリンクを全て Google キャッシュへのリンクに貼り直します。リンク切れが多々ある、文書の閲覧のときにとても便利です。
javascript: function cacheify_urls(node) { const re = /^https:\/\/webcache\.googleusercontent\.com\/search\?q=cache:/; for (const tag_a of node.getElementsByTagName('a')) if (!tag_a.href.match(re)) tag_a.href = tag_a.href.replace(/^/, 'https://webcache.googleusercontent.com/search?q=cache:'); } cacheify_urls(document.body);bookmarklet: (
289af6fc
) cacheify URLsf7081c8d
) toggle cacheify URLs … そのトグル版で、もう一度適用すると Google キャッシュへのリンクを外します。
閲覧中の文書のリンクを全て WayBackMachine(archive.org) へのリンクに貼り直します。リンク切れが多々ある、レガシーな文書の閲覧のときにとても便利です。
javascript: function archive_urls(node) { const re = /^http:\/\/liveweb\.archive\.org\//; for (const tag_a of node.getElementsByTagName('a')) if (!tag_a.href.match(re)) tag_a.href = tag_a.href.replace(/^/, 'http://liveweb.archive.org/'); } archive_urls(document.body);bookmarklet: (
5cad7dce
) archive URLs73474935
) toggle archive URLs … そのトグル版で、もう一度適用すると archive.org へのリンクを外します。
閲覧中の文書にスタイルを挿入してモノクロにします。配色が派手すぎて内容が頭に入ってこないページに便利です。
javascript: (function() { const id = 'monochromize'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `* { color: black !important; background-color: white !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: monochromize URL
閲覧中の文書にスタイルを挿入して img
, embed
, object
, applet
, bgsound
, video
, audio
, canvas
タグを visibility: hidden
にします。画像の多用で文書が埋もれて読みづらいときに便利です。
javascript: (function() { const id = 'hide_media'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `img, embed, object, applet, bgsound, video, audio, canvas, iframe { visibility: hidden !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: (
e8391997
) hide media URL
閲覧中の文書にスタイルを挿入して img
, embed
, object
, applet
, bgsound
, video
, audio
, canvas
タグを display: none
にします。画像の多用でブラウザに負荷がかかり過ぎているときに重宝します。
javascript: (function() { const id = 'remove_media'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `img, embed, object, applet, bgsound, video, audio, canvas, iframe { display: none !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: (
b61c17c2
) remove media URL
なぜこんなブックマークレットを作ったか覚えてないのですが、視聴中の動画を左右反転します。もう一度適用すると戻します。
javascript: (function () { function insert_tag_to_target(tag, attr, html = null, target = document.body, next = null) { const e = document.createElement(tag); if (attr.onload) { e.addEventListener('load', attr.onload); delete attr.onload; } for (const a in attr) e.setAttribute(a, attr[a]); if (html) e.innerHTML = html; target.insertBefore(e, next); } const id = 'video_flip_y'; const text = `\ video { transform: scaleX(-1) !important; } `; const style = document.getElementById(id); if (style) style.parentNode.removeChild(style); else insert_tag_to_target('style', { id: id, }, text, document.head); })();bookmarklet: (
3b4700b9
) flipY video tags ﹘ Y 軸 video 反転18933ef4
) flipX video tags ﹘ X 軸 video 反転fd27470f
) flipXY video tags ﹘ X, Y 軸 video 反転9f4406f0
) rotate clockwise video tags ﹘ 時計回り回転4516776d
) rotate anti clockwise video tags ﹘ 反時計回り回転
通常の一段組だと間伸びしてビューの情報量が少ないページがあります(例えば本ページとか)。強引に body に columns: 2 スタイルを挿入するブックマークレットです。スクロールする手間が省けて便利です。
javascript: { const s = document.body.getAttribute('style'); document.body.setAttribute('style', `${s ? s + (/;$/.test(s) ? '' : ';') + ' ' : ''}columns: 2;`); }bookmarklet: (
8c74bf41
) body columns two URL
同様なことを、はじめは以下の方法でやってみてましたが、スタイルがあまり維持されないのでボツにしようかと思いましたが、何かの役に立つかと敢えて載せておきます。
javascript: document.body.innerHTML = `<div style="columns: 2;">${document.body.innerHTML}</div>`;bookmarklet: (
afc44e58
) body falls div columns two URL
前者は body 全体でしたが、折り返しまで読んでページ先頭まで戻る、という形になります。もしかすると、文書によってはセクション毎に2段組の方が読みやすいのかもしれません。このブックマークレットに関しては h2 タグから推定した section を2段組にします。但し、段組み間を分かりやすくするために hr タグも挿入します。
javascript:(()=>{ document.body.innerHTML = document.body.innerHTML.replace(/<h2[^>]*>[\s\S]*?<\/h2>[\s\S]*?(?=<(?:h2|section|address|\/body)[^>]*>)/g, v=>`<section style="columns: 2;">${v}</section>\n<hr class="ornament" style="--ornament: '🙓🙒🙑🙐🙗🙖🙕🙔'"/>`); })();bookmarklet: (
f757f56a
) sectioning h2 columns two URL
2段組にはせず、h2 タグから section を推定して囲むブックマークレットも置いておきます。
javascript:(()=>{ document.body.innerHTML = document.body.innerHTML.replace(/<h2[^>]*>[\s\S]*?<\/h2>[\s\S]*?(?=<(?:h2|section|address|\/body)[^>]*>)/g, v=>`<section>${v}</section>`); })();bookmarklet: (
71560c2a
) sectioning h2 URL
ウェブページのテキストをコピーしようとして、そこがリンクでテキストのコピーに難儀したことはありませんか?このブックマークレットで一時的にコピーしやすいようにリンクを隠します。もう一度呼べばリンクを戻します。
javascript:for (const e of [ ...document.body.querySelectorAll('a[href]'), ...document.body.querySelectorAll('a[data-hyper_reference]'), ]) { let v = null; if ((v = e.getAttribute('href'))) { e.removeAttribute('href'); e.setAttribute('data-hyper_reference', v); } else if ((v = e.getAttribute('data-hyper_reference'))) { e.removeAttribute('data-hyper_reference'); e.setAttribute('href', v); } if (v) console.log(v); }bookmarklet: (
b9a0e1c2
) hide/reveal HREFs
閲覧中のページでどれかキーを押すまで、クリックした要素を削除し続けます。
javascript: (function () { let click_listener = null; document.body.style.cursor = "help"; document.body.addEventListener('click', (click_listener=function (ev) { const e = document.elementFromPoint(ev.pageX, ev.pageY); if (e) e.parentNode.removeChild(e); ev.preventDefault(); })); document.body.addEventListener('keyup', function (ev) { document.body.removeEventListener('click', click_listener); document.body.style.cursor = "default"; ev.preventDefault(); }, { once: true, }); })();bookmarklet: (
31939c47
) clicked elements remover
一度だけ、クリックした要素を削除します。
javascript: (function () { document.body.style.cursor = "help"; document.body.addEventListener('click', (click_listener=function (ev) { const e = document.elementFromPoint(ev.pageX, ev.pageY); if (e) e.parentNode.removeChild(e); ev.preventDefault(); document.body.style.cursor = "default"; }), { once: true, }); })();bookmarklet: (
94e42851
) clicked element remover
閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語のゴシック体に切り替えます。再度適用すれば、それを元に戻します。
javascript: (function() { const id = 'sans_serif_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-family: '小塚ゴシック Pr6N', 'Kozuka Gothic Pr6N', 'IPAexゴシック', 'IPAexGothic', 'TakaoExゴシック', 'TakaoExGothic', 'BIZ UDPゴシック', 'BIZ UDPGothic', '凸版文久ゴシック', 'Toppan Bunkyu Gothic', '游ゴシック', 'Yu Gothic', '游ゴシック体', 'YuGothic', 'ヒラギノ角ゴシック', 'Hiragino Sans', 'ヒラギノ角ゴ ProN', 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ Pro', 'Hiragino Kaku Gothic Pro', 'ヒラギノ角ゴ StdN', 'Hiragino Kaku Gothic StdN', 'Noto Sans CJK JP', '源ノ角ゴシック', 'Source Han Sans', /*'Noto Sans Japanese', */ 'Noto Sans JP', 'メイリオ', 'Meiryo', 'MS Pゴシック', 'MS PGothic', 'Takao Pゴシック', 'TakaoPGothic', 'IPA Pゴシック', 'IPAPGothic', 'IPA X0208 Pゴシック', 'IPAX0208PGothic', 'モトヤLシータ゛3等幅', 'MotoyaLCedar', 'Droid Sans Japanese', 'Droid Sans Fallback', 'M PLUS 1p', sans-serif !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: sans-serif fontify (ja) URL
閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語の明朝体に切り替えます。再度適用すれば、それを元に戻します。Microsoft IE のゴシック体の所為で昨今は明朝体を読みづらいと感じる人々が増えてきている気がします。紙媒体の書籍や新聞などの本文は明朝体が一般的なので、本を読む習慣がそれで削がれているとしたら、些か罪深いことです。このブックマークレットを活用して明朝体にも慣れるようにしましょう。
javascript: (function() { const id = 'serif_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-family: '小塚明朝 Pr6N', 'Kozuka Mincho Pr6N', 'IPAex明朝', 'IPAexMincho', 'TakaoEx明朝', 'TakaoExMincho', '凸版文久明朝', 'Toppan Bunkyu Mincho', '游明朝', 'Yu Mincho', '游明朝体', 'YuMincho', 'ヒラギノ明朝 ProN', 'Hiragino Mincho ProN', 'ヒラギノ明朝 Pro', 'Hiragino Mincho Pro', 'Noto Serif CJK JP', '源ノ明朝 JP', 'Source Han Serif JP', 'MS P明朝', 'MS PMincho', 'Takao P明朝', 'TakaoPMincho', 'IPA P明朝', 'IPAMincho', 'IPA X0208 P明朝', 'IPAX0208Mincho', serif !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: serif fontify (ja) URL
閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語のMS P互換ゴシック体に切り替えます。再度適用すれば、それを元に戻します。これは、某掲示板由来の日本独特のプロポーショナルフォントによるアスキーアートを再現するために利用できます。
javascript: (function() { const id = 'MS_P_sans_serif_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-family: /*'M+ 1p', 'M+ 2p', 'Mgen+ 1p', 'Mgen+ 2p', 'Rounded M+ 1p', 'Rounded M+ 2p', 'Rounded Mgen+ 1p', 'Rounded Mgen+ 2p', 'Rounded-L M+ 1p', 'Rounded-L M+ 2p', 'Rounded-L Mgen+ 1p', 'Rounded-L Mgen+ 2p', 'Rounded-X M+ 1p', 'Rounded-X M+ 2p', 'Rounded-X Mgen+ 1p', 'Rounded-X Mgen+ 2p', 'ほのかアンティーク角', 'Honoka Antique-Kaku', 'Takao Pゴシック', 'TakaoPGothic',*/ 'MS Pゴシック', 'MS PGothic', '梅Pゴシック', 'Ume P Gothic', 'RobotoJAA', 'IPA モナー Pゴシック', 'IPAMonaPGothic', 'Mona', 'Monapo', sans-serif !important; } * { font-size: 12pt; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: MS P sans-serif fontify (ja) URL
閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグを日本語の等幅フォントに切り替えます。再度適用すれば、それを元に戻します。プログラミングを教えるにあたって、零「0
」とオー「O
」、一「1
」とエル「l
」と縦線「|
」、チルダ「~
」と波線「〜
」とマクロン「¯
」などなど、基本的な区別がし難いフォントがあるようです。等幅フォントのなかにはコーディングにて区別しやすいグリフのデザインなものが多くありますので、それをこのブックマークレットで積極的に使っていきたいものです。
javascript: (function() { const id = 'monospace_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `pre, tt, code, kbd, samp { font-family: '源柔ゴシックX等幅', 'Gen Jyuu Gothic X Monospace', '源ノ等幅', 'SourceHanMono-Regular', '源ノ角ゴシック Code JP', 'Source Han Code JP', '源ノ角ゴシック HW', 'Source Han Sans HW', 'Noto Sans Mono CJK JP', 'M+ 1mn', 'M+ 1m', 'M+ 1mn', 'M+ 2m', 'Mgen+ 1m', 'Mgen+ 1mn', 'Mgen+ 2m', 'Rounded M+ 1m', 'Rounded M+ 1mn', 'Rounded M+ 2m', 'Rounded Mgen+ 1m', 'Rounded Mgen+ 1mn', 'Rounded Mgen+ 2m', 'Rounded-L M+ 1m', 'Rounded-L M+ 1mn', 'Rounded-L M+ 2m', 'Rounded-L Mgen+ 1m', 'Rounded-L Mgen+ 1mn', 'Rounded-L Mgen+ 2m', 'Rounded-X M+ 1m', 'Rounded-X M+ 1mn', 'Rounded-X M+ 2m', 'Rounded-X Mgen+ 1m', 'Rounded-X Mgen+ 1mn', 'Rounded-X Mgen+ 2m', 'モトヤLシータ゛3等幅', 'MotoyaLCedar', 'RobotoJ Mono', 'Osaka-Mono', monospace !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: monospace fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語の教科書体や筆記体に切り替えます。再度適用すれば、それを元に戻します。文書がとても読みやすくなることを感じることができると思います。
javascript: (function() { const id = 'cursive_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { font-family: 'クレー', 'クレー ミディアム', 'Klee', 'UD デジタル 教科書体 NP-R', 'UD Digi Kyokasho NP-R', '游教科書体 横用', 'YuKyokasho Yoko', '游教科書体', 'YuKyokasho', 'DFP中楷書体', 'DFPKaiSho-Md', 'DFP教科書体W3', 'DFPKyoKaSho-W3', 'HG正楷書体-PRO', 'HGSeikaishotaiPRO', cursive !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: cursive fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語の丸ゴシック体やポップ体に切り替えます。再度適用すれば、それを元に戻します。文書がくだけた雰囲気になることを感じることができると思います。
javascript: (function() { const id = 'fantasy_fontify_ja'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) { font-family: 'ほのかアンティーク丸', 'Honoka Antique-Maru', 'ほのか丸ゴシック', 'Honoka Maru-Gothic', '筑紫B丸ゴシック', 'Tsukushi B Round Gothic', '筑紫A丸ゴシック', 'Tsukushi A Round Gothic', 'ヒラギノ丸ゴ ProN', 'Hiragino Maru Gothic ProN', 'Rounded M+ 2p', 'Rounded M+ 1p', 'Rounded M+ 2c', 'Rounded Mplus 1c', 'DFP太丸ゴシック体', 'DFPMaruGothic-SB', 'モトヤLマルベリ3等幅', 'MotoyaLMaru', 'HG丸ゴシックM-Pro', 'HGMaruGothicMPRO', fantasy !important; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: fantasy fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグについて、以下の日本語のカーニングの種類を逆順に切り替えます。一周したら元に戻ります。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の日本語フォントなら、以上のように一つのフォントでプロポーショナルや固定幅に対応され、大変便利です。
javascript: (function() { const id = 'kern_glyphs_fontify'; const style = document.getElementById(id); const kern_glyphs = [ "/* なし */ 'tnum' 0, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス */ 'tnum' 0, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 1, 'pkna' 1, 'palt' 1, 'halt' 0", //"/* プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス&字幅半角メトリクス */ 'tnum' 0, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 1, 'pkna' 1, 'palt' 1, 'halt' 1", "/* 等幅数字&等幅全角字形 */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 1, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* 等幅数字&等幅全角字形&字幅半角メトリクス */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 1, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 1", "/* 等幅数字 */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* 等幅数字&字幅半角メトリクス */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 1", "/* 等幅数字&等幅三分字形 */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 1, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* 等幅数字&等幅三分字形&字幅半角メトリクス */ 'tnum' 1, 'hwid' 0, 'qwid' 0, 'twid' 1, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 1", "/* 等幅数字&等幅四分字形 */ 'tnum' 1, 'hwid' 0, 'qwid' 1, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* 等幅数字&等幅四分字形&字幅半角メトリクス */ 'tnum' 1, 'hwid' 0, 'qwid' 1, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 1", "/* 等幅数字&等幅半角字形 */ 'tnum' 1, 'hwid' 1, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 0", "/* 等幅数字&等幅半角字形&字幅半角メトリクス */ 'tnum' 1, 'hwid' 1, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0, 'halt' 1", ].reverse(); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${kern_glyphs[0]} !important; } `; document.head.appendChild(style); } else { let i = 0; for (; i<kern_glyphs.length; ++i) { const innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${kern_glyphs[i]} !important; } `; if (style.innerHTML == innerHTML) break; } if (i != kern_glyphs.length - 1) style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${kern_glyphs[i + 1]} !important; } `; else style.parentNode.removeChild(style); } } )();bookmarklet: kern glyphs fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語をプロポーショナルに切り替えます。再度適用すれば逆に固定幅へ、再々度適用すれば、それを元に戻します。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の日本語フォントなら、以上のように一つのフォントでプロポーショナルも固定幅も使え、大変便利です。
javascript: (function() { const id = 'prop_glyphs_fontify'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { /* プロポーショナル数字&プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス */ font-feature-settings: 'tnum' 0, 'hwid' 0, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 1, 'pwid' 1, 'pkna' 1, 'palt' 1 !important; } `; document.head.appendChild(style); } else { const innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { /* 等幅数字&等幅半角字形 */ font-feature-settings: 'tnum' 1, 'hwid' 1, 'qwid' 0, 'twid' 0, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0 !important; } `; if (style.innerHTML != innerHTML) style.innerHTML = innerHTML; else style.parentNode.removeChild(style); } } )();bookmarklet: prop glyphs fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグを日本語を固定幅に切り替えます。再度適用すれば逆にプロポーショナルへ、再々度適用すれば、それを元に戻します。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の日本語フォントなら、以上のように一つのフォントで固定幅もプロポーショナルも使え、大変便利です。
javascript: (function() { const id = 'fixw_glyphs_fontify'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `pre, tt, code, kbd, samp { /* 等幅数字&等幅半角字形 */ font-feature-settings: 'tnum' 1, 'hwid' 1, 'fwid' 0, 'pnum' 0, 'pwid' 0, 'pkna' 0, 'palt' 0 !important; } `; document.head.appendChild(style); } else { const innerHTML = `pre, tt, code, kbd, samp { /* プロポーショナル数字&プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス */ font-feature-settings: 'tnum' 0, 'hwid' 0, 'fwid' 0, 'pnum' 1, 'pwid' 1, 'pkna' 1, 'palt' 1 !important; } `; if (style.innerHTML != innerHTML) style.innerHTML = innerHTML; else style.parentNode.removeChild(style); } } )();bookmarklet: fixw glyphs fontify (ja) URL
閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグについて、以下の縦書きの日本語のカーニングの種類を逆順に切り替えます。一周したら元に戻ります。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の日本語フォントなら、以上のように一つのフォントで縦書きのプロポーショナルや固定幅に対応され、大変便利です。
javascript: (function() { const id = 'vkrn_glyphs_fontify'; const style = document.getElementById(id); const vkrn_glyphs = [ "/* 縦組み用字形 */ 'vert' 1, 'vkrn' 1, 'vkna' 1, 'vpal' 0, 'vhal' 0", "/* 縦組み用字形&縦組み字幅半角メトリクス */ 'vert' 1, 'vkrn' 1, 'vkna' 1, 'vpal' 0, 'vhal' 1", "/* 縦組み用字形&縦組みプロポーショナルメトリクス */ 'vert' 1, 'vkrn' 1, 'vkna' 1, 'vpal' 1, 'vhal' 0", ].reverse(); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${vkrn_glyphs[0]} !important; } `; document.head.appendChild(style); } else { let i = 0; for (; i<vkrn_glyphs.length; ++i) { const innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${vkrn_glyphs[i]} !important; } `; if (style.innerHTML == innerHTML) break; } if (i != vkrn_glyphs.length - 1) style.innerHTML = `*:not(pre):not(tt):not(code):not(kbd):not(samp) { font-feature-settings: ${vkrn_glyphs[i + 1]} !important; } `; else style.parentNode.removeChild(style); } } )();bookmarklet: vkrn glyphs fontify (ja) URL
*
タグを日本語の字形を変更閲覧中の文書にスタイルを挿入してすべてのタグについて、以下の日本語の字形の種類を順に切り替えます。一周したら元に戻ります。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の日本語フォントなら、以上のように一つのフォントで例えば国語審議会による印刷標準字体にされ、大変便利です。
javascript: (function() { const id = 'variant_glyphs_fontify'; const style = document.getElementById(id); const variant_glyphs = [ "/* JIS78 字形 */ 'jp78'", "/* JIS83 字形 */ 'jp83'", "/* JIS90 字形 */ 'jp90'", "/* JIS2004 字形 */ 'jp04'", "/* 旧字体 */ 'trad'", //"/* ルビ用字形 */ 'ruby'", //"/* 横組み用かな */ 'hkna'", "/* 印刷標準字体 */ 'nlck'", //"/* 修飾字形 */ 'nalt'", //"/* イタリック */ 'ital'", ]; if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `* { font-feature-settings: ${variant_glyphs[0]} !important; } `; document.head.appendChild(style); } else { let i = 0; for (; i<variant_glyphs.length; ++i) { const innerHTML = `* { font-feature-settings: ${variant_glyphs[i]} !important; } `; if (style.innerHTML == innerHTML) break; } if (i != variant_glyphs.length - 1) style.innerHTML = `* { font-feature-settings: ${variant_glyphs[i + 1]} !important; } `; else style.parentNode.removeChild(style); console.log(`${document.getElementById(id) ? document.getElementById(id).innerHTML : 'null'}`); } } )();bookmarklet: variant glyphs fontify (ja) URL
*
タグを字形を分数や他に変更閲覧中の文書にスタイルを挿入してすべてのタグについて、以下の字形の種類を順に切り替えます。一周したら元に戻ります。
指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。OpenType 以降の新し目の非東アジアフォントなら、以上のように一つのフォントで様々な字体の種類が確認できて、大変便利です。
javascript: (function() { const id = 'frac_other_glyphs_fontify'; const style = document.getElementById(id); const frac_other_glyphs = [ "/* 分数 */ 'frac'", "/* 上付き文字 */ 'sups'", "/* 下付き文字 */ 'subs'", "/* 上付き序数表記 */ 'ordn'", "/* ライニング数字 */ 'lnum'", "/* オールドスタイル数字 */ 'onum'", "/* プロポーショナル数字 */ 'pnum'", "/* 等幅数字 */ 'tnum'", "/* 一般的な合字/標準合字 */ 'liga' 0, 'clig' 0", "/* 前後関係に依存する字形 */ 'calt' 0", "/* 任意の合字 */ 'dlig'", "/* スモールキャップス */ 'smcp'", "/* 大文字のスモールキャップス */ 'c2sc'", "/* スワッシュ字形 */ 'swsh'", "/* カーニング */ 'kern'", "/* 字体組版/分解 */ 'ccmp' 0", "/* ローカライズの字形 */ 'locl' 0", "/* デザインのバリエーション */ 'salt'", "/* デザインのバリエーション 2 */ 'salt' 2", "/* デザインのセット 1 */ 'ss01'", //"/* デザインのセット 2 */ 'ss02'", //"/* デザインのセット 3 */ 'ss03'", //"/* デザインのセット 4 */ 'ss04'", //"/* デザインのセット 5 */ 'ss05'", //"/* デザインのセット 6 */ 'ss06'", //"/* デザインのセット 7 */ 'ss07'", //"/* デザインのセット 8 */ 'ss08'", //"/* デザインのセット 9 */ 'ss09'", //"/* デザインのセット 10 */ 'ss10'", //"/* デザインのセット 11 */ 'ss11'", //"/* デザインのセット 12 */ 'ss12'", //"/* デザインのセット 13 */ 'ss13'", //"/* デザインのセット 14 */ 'ss14'", //"/* デザインのセット 15 */ 'ss15'", //"/* デザインのセット 16 */ 'ss16'", //"/* デザインのセット 17 */ 'ss17'", //"/* デザインのセット 18 */ 'ss18'", //"/* デザインのセット 19 */ 'ss19'", //"/* デザインのセット 20 */ 'ss20'", ]; if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `* { font-feature-settings: ${frac_other_glyphs[0]} !important; } `; document.head.appendChild(style); } else { let i = 0; for (; i<frac_other_glyphs.length; ++i) { const innerHTML = `* { font-feature-settings: ${frac_other_glyphs[i]} !important; } `; if (style.innerHTML == innerHTML) break; } if (i != frac_other_glyphs.length - 1) style.innerHTML = `* { font-feature-settings: ${frac_other_glyphs[i + 1]} !important; } `; else style.parentNode.removeChild(style); console.log(`${document.getElementById(id) ? document.getElementById(id).innerHTML : 'null'}`); } } )();bookmarklet: frac other glyphs fontify URL
*
タグを日本語の字形を教科書体の中から順に変更、他「Javascript(+CSS) でフォントが有効か検査する」にて、AdobeBlank フォントの代わりに、サイズの小さな、拙作 GetaBlank が製作できたので、ブックマークレットとしてこれを実現できるようになりました。
上記の日本語のゴシック体(サンスセリフ)、明朝体(セリフ)、筆記体(カーシブ)、丸ゴシック等のポップ体(ファンタジー)などをスタイルで指定したものは、システムにそれらのフォントのどれかがインストールされていることを期待して、優先するものを先にいくつものフォントを指定してしていました。つまり、列挙したフォントを切り替えるという役割はありませんでした。
なぜなら、列挙したフォントが実際にブラウザで有効かどうかは俄かには分からないので、通常は難しい機能となってしまいます。しかし、AdobeBlank や拙作の GetaBlank を利用すれば、指定したフォントが有効か否かを判定することが可能となりました。さらに、GetaBlank であればサイズが小さいので、ブックマークレットとして厭わず利用できるでしょう。
筆記体を例としてそのブックマークレットのコードを示します。以下は、既知の日本語フォント名の配列にて、ブラウザで有効なフォントのみから、適用した順ですべてのタグのフォントを切り替えます。一周したら元に戻ります。
javascript: (function() { const fallback_font_name = 'cursive'; const font_feature_settings = "'tnum' 0, 'hwid' 0, 'fwid' 0, 'pnum' 1, 'pwid' 1, 'pkna' 1, 'palt' 1 /* プロポーショナル数字&プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス */"; const id = 'cursive_font_rotate_ja'; const font_names = [ 'クレー', //'クレー ミディアム', 'Klee', 'UD デジタル 教科書体 NP-R', 'UD Digi Kyokasho NP-R', '游教科書体 横用', //'YuKyokasho Yoko', '游教科書体', //'YuKyokasho', 'DFP中楷書体', 'DFPKaiSho-Md', 'DFP教科書体W3', 'DFPKyoKaSho-W3', 'HG正楷書体-PRO', 'HGSeikaishotaiPRO', '機械彫刻用標準書体', //'Kikai Chokoku JIS', 'Adobe NotDef', 'Adobe Blank', ]; let installed_font_names = []; let installed_font_names_index = 0; function is_installed_ja_font(font_name) { //const string = '〓'; const string = '='; const span_tag = document.createElement('span'); span_tag.style.fontFamily = `'${font_name}', GetaBlank`; span_tag.innerHTML = `${string}`; document.body.appendChild(span_tag); //console.log(font_name, span_tag.offsetWidth); const is_not_geta_blank = span_tag.offsetWidth > .0; document.body.removeChild(span_tag); return is_not_geta_blank; } const id_font_face = 'font_face_GetaBlank'; if (!document.getElementById(id_font_face)) { let style = document.createElement('style'); style.id = id_font_face; style.setAttribute('type', 'text/css'); style.innerHTML = `@font-face { font-family: 'GetaBlank'; src: url("data:font/woff; base64,d09GRk9UVE8AAAPsAA0AAAAABcwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAABMAAAAIcAAACd9iQb30ZGVE0AAAG4AAAAGgAAAByK+r5UR0RFRgAAAdQAAAAdAAAAHgAoAApPUy8yAAAB9AAAADsAAABgSrqELGNtYXAAAAIwAAAAPwAAAVIAUTLiaGVhZAAAAnAAAAApAAAANhPrmPtoaGVhAAACnAAAABcAAAAkARgAA2htdHgAAAK0AAAACwAAAAwAAAAAbWF4cAAAAsAAAAAGAAAABgAEUABuYW1lAAACyAAAAOgAAAGeC4KKO3Bvc3QAAAOwAAAAEwAAACD//gAKdmhlYQAAA8QAAAAZAAAAJP+aD4J2bXR4AAAD4AAAAAsAAAAMAAAAAHicY2RgYWFgZGTkck8tSXTKSczLZmBkYmBksPkhy/RDjvmHBEs3D/NUHhY5LgZLNtX/3d1wBg97NxCwyjA088swMAjIMHQJyjCwyzBME2JgAZnAwcDPIMGgWJqXaWBgnAKkjA0MjeG2IKwDAcZ2xg4GFkZGJmYWVj4g6BbpFu3m4QIATFAg/QB4nGNgYGBkAIJrvsmhIPpW2Np6GA0AQqUGlQAAeJxjYGRgYOABYjEgZmJgBGJmIMkC5jEAAAPMADMAAAB4nGNgZvzCOIGBlYGDYRnDZgYGBmUoXcXAw+DEgAoYgRAOAtJcUxgcGGwNhMGC4nA1MKAAhIwA+EMHrwB4nGNgYGBmgGAZBkYGEPAB8hjBfBYGAyDNAYRMYBlbA+H//5FZ/4+e/wDVBQaMbAzIXNIBEyWaBwcAAGOZCWAAeJxjYGRgYADiyb0KC+L5bb4yaIMEGBhuha2tR6ahgIOBCUQBAA/hCHAAAAB4nGNgZGAAIgYGcQYYYGRABUwAAucAHQB4nGNgQAAAAAwAAQAAAFAAAAQAAHichY8xasMwFIY/J05CSOlQSsegJaONraGQjBkc6NghuwdhQowNinOBHqJn6CEy5xg9QA9R+tsVXQqt4Ol9+t+vpyfghlci+hUx5z7wiBlp4DErXgLH8lwCT1jwHngq/VPOKJ5LuRtu9TzilmXgMU88Bo7leQs84YFr4Kn0D3Y4Okq21NobjrBzXbmty0b4rGrFeah5HV11rktBQStvN2Qvh8Ng9YtMeaP43fVbt6xJyBVW3j4o2qYrWl85Y9PMbMzP62K7TvLEZla2v+fcq+o5cRjmMnqhn4W986dD25g8/a/DF6YNPh14nGNgZgCD/78ZuBiwAAAvxAIIAHicY2AUYPjf8L+BQZwBARgZkAETAGCnAyoAAAB4nGNgQAAAAAwAAQA=") format('woff'); } `; document.head.appendChild(style); } let style = document.getElementById(id); if (!style) { for (const font_name of font_names) { const is_installed = is_installed_ja_font(font_name); if (is_installed) { //console.log(font_name); installed_font_names.push(font_name); } } style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `* { font-family: '${installed_font_names[installed_font_names_index]}', ${fallback_font_name} !important; ${typeof font_feature_settings === 'undefined' ? '' : ' font-feature-settings: ' + font_feature_settings + ' !important;'} /* installed_font_names: ${installed_font_names.map(v => `'${v}'`).join(',')}; */ /* installed_font_names_index: ${installed_font_names_index}; */ } `; console.log(installed_font_names[installed_font_names_index]); document.head.appendChild(style); } else { let installed_font_names = style.innerHTML.replace(/^[\s\S]*\/\* installed_font_names: ([^;]*); \*\/[\s\S]*$/, '$1').split(',').map(v => v.replace(/^'(.*)'$/, '$1')); let installed_font_names_index = Number(style.innerHTML.replace(/^[\s\S]*\/\* installed_font_names_index: (\d+); \*\/[\s\S]*$/, '$1')); //console.log(installed_font_names_index, installed_font_names.length); if (++installed_font_names_index < installed_font_names.length) { style.innerHTML = `* { font-family: '${installed_font_names[installed_font_names_index]}', ${fallback_font_name} !important; ${typeof font_feature_settings === 'undefined' ? '' : ' font-feature-settings: ' + font_feature_settings + ' !important;'} /* installed_font_names: ${installed_font_names.map(v => `'${v}'`).join(',')}; */ /* installed_font_names_index: ${installed_font_names_index}; */ } `; console.log(installed_font_names[installed_font_names_index]); } else { style.parentNode.removeChild(document.getElementById(id_font_face)); style.parentNode.removeChild(style); } } } )();
筆記体を含む、他のフォント集合についてもブックマークレットを以下に用意しました。各種フォントの外観を確かめるために、大変便利です。
bookmarklet: sans-serif font rotate (ja) URLしかし、それでも相当長いブックマークレットでもブックマークに登録できることが分かります。
*
タグを絵文字に使われるフォントの中から順に変更Unicode.org の絵文字のページの HTML ソースを覗いてみると、絵文字が備わっているフォントとして 'Noto Color Emoji'
, 'Apple Color Emoji'
, 'Segoe UI Emoji'
, Symbola
, Code2002, Code2001, Code2000
他が想定されていることが分かりました。'Noto Color Emoji'
は Google 仕様の競合で Apple 製品では使えないようです。「絵文字がなんか変だな、意味がわからないな」などというときに別の絵文字に一時的に切り替えてみてみると何かわかることがあるかもしれません。これらのフォントに 'Unifont Upper', Unifont-JP, Unifont
を加えて全てのタグで順に絵文字フォントを優先的に設定し、最後は元に戻します。ページ全体は絵文字優先の設定の廉で崩れますので、絵文字に懸念があるときの用途として割り切ってお使いください。
一つ目は前節と同様、拙作 GetaBlank を応用したものです。
javascript: (function() { const fallback_font_name = 'sans-serif'; const id = 'emoji_font_rotate'; const font_names = [ "'Twitter Color Emoji'", "'Noto Color Emoji'", "'Apple Color Emoji'", "'Segoe UI Emoji'", "'Symbola'", "'Unifont Upper', 'Unifont-JP', 'Unifont'", "'Code2002', 'Code2001', 'Code2000'", ]; let installed_font_names = []; let installed_font_names_index = 0; function is_installed_ja_font(font_name) { //const string = '〓'; const string = '='; const span_tag = document.createElement('span'); span_tag.style.fontFamily = `'${font_name}', GetaBlank`; span_tag.innerHTML = `${string}`; document.body.appendChild(span_tag); //console.log(font_name, span_tag.offsetWidth); const is_not_geta_blank = span_tag.offsetWidth > .0; document.body.removeChild(span_tag); return is_not_geta_blank; } const id_font_face = 'font_face_GetaBlank'; if (!document.getElementById(id_font_face)) { let style = document.createElement('style'); style.id = id_font_face; style.setAttribute('type', 'text/css'); style.innerHTML = `@font-face { font-family: 'GetaBlank'; src: url("data:font/woff; base64,d09GRk9UVE8AAAPsAA0AAAAABcwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAABMAAAAIcAAACd9iQb30ZGVE0AAAG4AAAAGgAAAByK+r5UR0RFRgAAAdQAAAAdAAAAHgAoAApPUy8yAAAB9AAAADsAAABgSrqELGNtYXAAAAIwAAAAPwAAAVIAUTLiaGVhZAAAAnAAAAApAAAANhPrmPtoaGVhAAACnAAAABcAAAAkARgAA2htdHgAAAK0AAAACwAAAAwAAAAAbWF4cAAAAsAAAAAGAAAABgAEUABuYW1lAAACyAAAAOgAAAGeC4KKO3Bvc3QAAAOwAAAAEwAAACD//gAKdmhlYQAAA8QAAAAZAAAAJP+aD4J2bXR4AAAD4AAAAAsAAAAMAAAAAHicY2RgYWFgZGTkck8tSXTKSczLZmBkYmBksPkhy/RDjvmHBEs3D/NUHhY5LgZLNtX/3d1wBg97NxCwyjA088swMAjIMHQJyjCwyzBME2JgAZnAwcDPIMGgWJqXaWBgnAKkjA0MjeG2IKwDAcZ2xg4GFkZGJmYWVj4g6BbpFu3m4QIATFAg/QB4nGNgYGBkAIJrvsmhIPpW2Np6GA0AQqUGlQAAeJxjYGRgYOABYjEgZmJgBGJmIMkC5jEAAAPMADMAAAB4nGNgZvzCOIGBlYGDYRnDZgYGBmUoXcXAw+DEgAoYgRAOAtJcUxgcGGwNhMGC4nA1MKAAhIwA+EMHrwB4nGNgYGBmgGAZBkYGEPAB8hjBfBYGAyDNAYRMYBlbA+H//5FZ/4+e/wDVBQaMbAzIXNIBEyWaBwcAAGOZCWAAeJxjYGRgYADiyb0KC+L5bb4yaIMEGBhuha2tR6ahgIOBCUQBAA/hCHAAAAB4nGNgZGAAIgYGcQYYYGRABUwAAucAHQB4nGNgQAAAAAwAAQAAAFAAAAQAAHichY8xasMwFIY/J05CSOlQSsegJaONraGQjBkc6NghuwdhQowNinOBHqJn6CEy5xg9QA9R+tsVXQqt4Ol9+t+vpyfghlci+hUx5z7wiBlp4DErXgLH8lwCT1jwHngq/VPOKJ5LuRtu9TzilmXgMU88Bo7leQs84YFr4Kn0D3Y4Okq21NobjrBzXbmty0b4rGrFeah5HV11rktBQStvN2Qvh8Ng9YtMeaP43fVbt6xJyBVW3j4o2qYrWl85Y9PMbMzP62K7TvLEZla2v+fcq+o5cRjmMnqhn4W986dD25g8/a/DF6YNPh14nGNgZgCD/78ZuBiwAAAvxAIIAHicY2AUYPjf8L+BQZwBARgZkAETAGCnAyoAAAB4nGNgQAAAAAwAAQA=") format('woff'); } `; document.head.appendChild(style); } let style = document.getElementById(id); if (!style) { for (const font_name of font_names) { const is_installed = is_installed_ja_font(font_name); if (is_installed) { //console.log(font_name); installed_font_names.push(font_name); } } style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `* { font-family: ${installed_font_names[installed_font_names_index]}, ${fallback_font_name} !important; ${typeof font_feature_settings == 'undefined' ? '' : ' font-feature-settings: ' + font_feature_settings + ' !important;'} /* installed_font_names: ${installed_font_names.map(v => `"${v}"`).join('、')}; */ /* installed_font_names_index: ${installed_font_names_index}; */ } `; console.log(installed_font_names[installed_font_names_index]); document.head.appendChild(style); } else { let installed_font_names = style.innerHTML.replace(/^[\s\S]*\/\* installed_font_names: ([^;]*); \*\/[\s\S]*$/, '$1').split('、').map(v => v.replace(/^"(.*)"$/, '$1')); let installed_font_names_index = Number(style.innerHTML.replace(/^[\s\S]*\/\* installed_font_names_index: (\d+); \*\/[\s\S]*$/, '$1')); //console.log(installed_font_names_index, installed_font_names.length); if (++installed_font_names_index < installed_font_names.length) { style.innerHTML = `* { font-family: ${installed_font_names[installed_font_names_index]}, ${fallback_font_name} !important; ${typeof font_feature_settings == 'undefined' ? '' : ' font-feature-settings: ' + font_feature_settings + ' !important;'} /* installed_font_names: ${installed_font_names.map(v => `"${v}"`).join('、')}; */ /* installed_font_names_index: ${installed_font_names_index}; */ } `; console.log(installed_font_names[installed_font_names_index]); } else { style.parentNode.removeChild(document.getElementById(id_font_face)); style.parentNode.removeChild(style); } } } )();bookmarklet: (
7a5e744e
) emoji font rotate URL [2022/02/03] 'Twitter Color Emoji'
を追加したついでに、「'Unifont Upper', Unifont-JP, Unifont
」などをひとかたまりにして使い勝手を改善しました。
二つ目は、拙作 GetaBlank を使用せずに単純にフォントセットを適用する度に切り替え元に戻します。
javascript: (function () { const id = 'emoji-font-simply-rotate'; const fonts = [ "'Twitter Color Emoji'", "'Noto Color Emoji'", "'Apple Color Emoji'", "'Segoe UI Emoji'", "Symbola", "'Unifont Upper', Unifont-JP, Unifont", "Code2002, Code2001, Code2000", ]; const style = document.getElementById(id); if (style) { let innerHTML = style.innerHTML; for (let i=0; i<fonts.length-1; ++i) { innerHTML = innerHTML.replace(new RegExp(`^(.* font-family: )(${fonts[i]})(, sans-serif !important;.*)$`, 's'), `$1${fonts[i+1]}$3`); if (innerHTML != style.innerHTML) break; } if (innerHTML != style.innerHTML) { style.innerHTML = innerHTML; console.log(style.outerHTML); } else { style.parentNode.removeChild(style); console.log(`removed style#${id}`) } } else { const e = document.createElement('style'); e.id = id; e.innerHTML = ` * { font-family: ${fonts[0]}, sans-serif !important; font-variant-emoji: emoji; } `; document.head.insertBefore(e, document.head.firstNode) console.log(e.outerHTML); } })();bookmarklet: (
b15a0f74
) emoji font simply rotate URL [2022/02/03] 'Twitter Color Emoji'
を追加しました。
*
タグの行の高さを固定指定したフォントに依っては、いやに行送りが狭かったり、逆に広かったりします。調べてみると、ブラウザ既定の line-height
が normal
とやらが、どうもフォントから決定しているようです。Firefox で日本語フォントで試してみると、実測値としては calc(16.5/16)
、calc(24.5/16)
、calc(32.5/16)
などのように、旧めのフォントでは狭い値、新しめのフォントでは広い値になっています。この決定に依存せず、これらの値に固定して表示してみたいときに、このブックマークレットを使います。最後は元に戻します。(2021/07/12 追記) calc(16.5/16)
などの値に先立ち、normal
を強めに設定するので、ブラウザ依存の行の高さの様子から閲覧するように更新しました。そのあとは前の版と同じです。
javascript: (function() { const id = 'line_height'; const line_heights = [ "normal /* depend on browsers */", "calc(16.5/16) /* 'MS Mincho', 'MS Gothic', etc. */", "calc(24.5/16) /* Meiryo, 'Hiragino Mincho ProN', 'Hiragino Kaku Gothic ProN', etc. */", "calc(32.5/16) /* 'Kozuka Mincho Pr6N', 'Kozuka Gothic Pr6N', YuMincho, YuGothic, 'Toppan Bunkyu Mincho', 'Toppan Bunkyu Gothic', etc. */", ]; const style = document.getElementById(id); if (!style) { let line_heights_index = 0; let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `*:not(sup):not(sub) { line-height: ${line_heights[line_heights_index]} !important; } sup, sub { line-height: 0 !important; } `; style.setAttribute('data-line_heights_index', line_heights_index); document.head.appendChild(style); console.log(style.innerHTML); } else { let line_heights_index = style.getAttribute('data-line_heights_index'); if (++line_heights_index < line_heights.length) { style.innerHTML = `*:not(sup):not(sub) { line-height: ${line_heights[line_heights_index]} !important; } sup, sub { line-height: 0 !important; } `; style.setAttribute('data-line_heights_index', line_heights_index); console.log(style.innerHTML); } else { style.parentNode.removeChild(style); } } } )();bookmarklet: (
8aa77022
) line-height specify URL
ちなみに、Firefox では開発ツールの3ペインインスペクターのフォントで行の高さが自由に変更できます。
閲覧中の文書のノードをパースしてしてテキスト及びコメントの約物(、。「」『』)を(,. ‘’ “” )に変換します。再度適用すれば、逆変換します。技術文書のようになることを感じることができると思います。ちなみに、jascientify and unjascientify にも同様のものがあります。
javascript: if (jascientified === undefined) { var jascientified = true; } else { jascientified = !jascientified; } (function () { const jascientify_char_map = [ [ '、', ',' ], [ '。', '.' ], [ '「', ' ‘' ], [ '」', '’ ' ], [ '『', ' “' ], [ '』', '” ' ], ]; let jascientify_char_inverse_map = []; jascientify_char_map.forEach(a => { jascientify_char_inverse_map.push([ a[1], a[0] ]); }); function jascientify(value) { jascientify_char_map.forEach(a => { value = value.replace(new RegExp(a[0], 'g'), a[1]); }); return value; } function unjascientify(value) { jascientify_char_inverse_map.forEach(a => { value = value.replace(new RegExp(a[0], 'g'), a[1]); }); return value; } function parse_nodes(parent_node, callback) { if (parent_node.hasChildNodes()) { for (let node = parent_node.firstChild; node; node = node.nextSibling) { parse_nodes(node, callback); } } callback.call(parent_node); } parse_nodes(document.body, jascientified ? function () { if (this.nodeType == 3 || this.nodeType == 8) this.nodeValue = jascientify(this.nodeValue); } : function () { if (this.nodeType == 3 || this.nodeType == 8) this.nodeValue = unjascientify(this.nodeValue); }); })();bookmarklet: jascientify/unjascientify URL
閲覧中の文書のノードをパースしてしてテキスト及びコメントの JIS X 0213 で非推奨の全角のラテン文字や半角のカタカナを JIS X 0213 で推奨の半角のラテン文字や全角のカタカナに変換します。再度適用すれば、逆変換します。Unix 使いの文書のようになることを感じることができると思います。ちなみに、janormalize and unjanormalize にも同様のものがあります。
javascript: if (janormalized === undefined) { var janormalized = true; } else { janormalized = !janormalized; } (function () { const janormalize_char_map = [ [ "!", "!" ], [ "”", "\"" ], [ "#", "#" ], [ "$", "$" ], [ "%", "%" ], [ "&", "&" ], [ "(", "(" ], [ ")", ")" ], [ "*", "*" ], [ "+", "+" ], [ ",", "," ], [ "−", "-" ], [ ".", "." ], [ "/", "/" ], [ "0", "0" ], [ "1", "1" ], [ "2", "2" ], [ "3", "3" ], [ "4", "4" ], [ "5", "5" ], [ "6", "6" ], [ "7", "7" ], [ "8", "8" ], [ "9", "9" ], [ ":", ":" ], [ ";", ";" ], [ "<", "<" ], [ "=", "=" ], [ ">", ">" ], [ "?", "?" ], [ "@", "@" ], [ "A", "A" ], [ "B", "B" ], [ "C", "C" ], [ "D", "D" ], [ "E", "E" ], [ "F", "F" ], [ "G", "G" ], [ "H", "H" ], [ "I", "I" ], [ "J", "J" ], [ "K", "K" ], [ "L", "L" ], [ "M", "M" ], [ "N", "N" ], [ "O", "O" ], [ "P", "P" ], [ "Q", "Q" ], [ "R", "R" ], [ "S", "S" ], [ "T", "T" ], [ "U", "U" ], [ "V", "V" ], [ "W", "W" ], [ "X", "X" ], [ "Z", "Z" ], [ "[", "[" ], [ "\", "\\" ], [ "]", "]" ], [ "^", "^" ], [ "_", "_" ], [ "`", "`" ], [ "a", "a" ], [ "b", "b" ], [ "c", "c" ], [ "d", "d" ], [ "e", "e" ], [ "f", "f" ], [ "g", "g" ], [ "h", "h" ], [ "i", "i" ], [ "j", "j" ], [ "k", "k" ], [ "l", "l" ], [ "m", "m" ], [ "n", "n" ], [ "o", "o" ], [ "p", "p" ], [ "q", "q" ], [ "r", "r" ], [ "s", "s" ], [ "t", "t" ], [ "u", "u" ], [ "v", "v" ], [ "w", "w" ], [ "x", "x" ], [ "y", "y" ], [ "z", "z" ], [ "{", "{" ], [ "|", "|" ], [ "¦", "¦" ], [ "}", "}" ], [ "〜", "~" ], [ "¬", "¬" ], [ " ̄", "¯" ], [ "¥", "¥" ], [ "。", "。" ], [ "「", "「" ], [ "」", "」" ], [ "、", "、" ], [ "・", "・" ], [ "ガ", "ガ" ], [ "ギ", "ギ" ], [ "グ", "グ" ], [ "ゲ", "ゲ" ], [ "ゴ", "ゴ" ], [ "ザ", "ザ" ], [ "ジ", "ジ" ], [ "ズ", "ズ" ], [ "ゼ", "ゼ" ], [ "ゾ", "ゾ" ], [ "ダ", "ダ" ], [ "ヂ", "ヂ" ], [ "ヅ", "ヅ" ], [ "デ", "デ" ], [ "ド", "ド" ], [ "バ", "バ" ], [ "ビ", "ビ" ], [ "ブ", "ブ" ], [ "ベ", "ベ" ], [ "ボ", "ボ" ], [ "パ", "パ" ], [ "ピ", "ピ" ], [ "プ", "プ" ], [ "ペ", "ペ" ], [ "ポ", "ポ" ], [ "ヴ", "ヴ" ], [ "ヲ", "ヲ" ], [ "ァ", "ァ" ], [ "ィ", "ィ" ], [ "ゥ", "ゥ" ], [ "ェ", "ェ" ], [ "ォ", "ォ" ], [ "ャ", "ャ" ], [ "ュ", "ュ" ], [ "ョ", "ョ" ], [ "ッ", "ッ" ], [ "ー", "ー" ], [ "ア", "ア" ], [ "イ", "イ" ], [ "ウ", "ウ" ], [ "エ", "エ" ], [ "オ", "オ" ], [ "カ", "カ" ], [ "キ", "キ" ], [ "ク", "ク" ], [ "ケ", "ケ" ], [ "コ", "コ" ], [ "サ", "サ" ], [ "シ", "シ" ], [ "ス", "ス" ], [ "セ", "セ" ], [ "ソ", "ソ" ], [ "タ", "タ" ], [ "チ", "チ" ], [ "ツ", "ツ" ], [ "テ", "テ" ], [ "ト", "ト" ], [ "ナ", "ナ" ], [ "ニ", "ニ" ], [ "ヌ", "ヌ" ], [ "ネ", "ネ" ], [ "ノ", "ノ" ], [ "ハ", "ハ" ], [ "ヒ", "ヒ" ], [ "フ", "フ" ], [ "ヘ", "ヘ" ], [ "ホ", "ホ" ], [ "マ", "マ" ], [ "ミ", "ミ" ], [ "ム", "ム" ], [ "メ", "メ" ], [ "モ", "モ" ], [ "ヤ", "ヤ" ], [ "ユ", "ユ" ], [ "ヨ", "ヨ" ], [ "ラ", "ラ" ], [ "リ", "リ" ], [ "ル", "ル" ], [ "レ", "レ" ], [ "ロ", "ロ" ], [ "ワ", "ワ" ], [ "ン", "ン" ], [ "゙", "゛" ], [ "゚", "゜" ], ]; let janormalize_char_inverse_map = []; janormalize_char_map.forEach(a => { janormalize_char_inverse_map.push([ a[1], a[0] ]); }); function janormalize(value) { janormalize_char_map.forEach(a => { value = value.replace(new RegExp(a[0], 'g'), a[1]); }); return value; } function unjanormalize(value) { janormalize_char_inverse_map.forEach(a => { value = value.replace(new RegExp(a[0].replace(/([!$()*+.?\[\\\]^|])/g, '\\$1'), 'g'), a[1]); }); return value; } function parse_nodes(parent_node, callback) { if (parent_node.hasChildNodes()) { for (let node = parent_node.firstChild; node; node = node.nextSibling) { parse_nodes(node, callback); } } callback.call(parent_node); } parse_nodes(document.body, janormalized ? function () { if (this.nodeType == 3 || this.nodeType == 8) this.nodeValue = janormalize(this.nodeValue); } : function () { if (this.nodeType == 3 || this.nodeType == 8) this.nodeValue = unjanormalize(this.nodeValue); }); } )();bookmarklet: janormalize/unjanormalize URL
縦書き仕様のスタイルに変更します。青空文庫などが縦書きで読めて、便利です。
javascript: (function() { const id = 'root_vertical_rl_wm'; const style = document.getElementById(id); if (!style) { let style = document.createElement('style'); style.id = id; style.setAttribute('type', 'text/css'); style.innerHTML = `:root { -webkit-writing-mode: vertical-rl; writing-mode: vertical-rl; /*-webkit-text-orientation: upright; text-orientation: upright;*/ font-family: 'Toppan Bunkyu Mincho', SourceHanMono-Regular, 'Source Han Sans HW', 'Noto Sans Mono CJK JP', 'Tsukushi B Round Gothic', 'Tsukushi A Round Gothic', 'Hiragino Maru Gothic ProN', Klee, 'YuKyokasho Yoko', YuKyokasho, 'Kozuka Mincho Pr6N', TakaoExMincho, IPAexMincho, /*'Toppan Bunkyu Mincho',*/ 'Yu Mincho', YuMincho, 'Hiragino Mincho ProN', 'Hiragino Mincho Pro', 'Noto Serif CJK JP', 'Source Han Serif JP', 'Kozuka Gothic Pr6N', TakaoExGothic, IPAexGothic, 'Toppan Bunkyu Gothic', 'Yu Gothic', YuGothic, 'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Hiragino Kaku Gothic Pro', 'Hiragino Kaku Gothic StdN', 'Noto Sans CJK JP', 'Source Han Sans', 'Noto Sans JP', 'Noto Sans Japanese', Meiryo, 'Droid Sans Fallback', serif; } `; document.head.appendChild(style); } else { style.parentNode.removeChild(style); } } )();bookmarklet: root vertical-rl writing-mode URL
ユーザーエージェントの種類に依らず見た目を統一したいという目的で、リセットCSSなるものを利用する場合があるようです。
これらのスタイルシートを閲覧中のページのスタイルに順に挿入します。一周すれば元に戻します。2020/01/16 頃に作成したブックマークレットでは document.head.appendChild
していたのですが、それだと目的にそぐわないので、document.head.insertBefore(, document.head.firstChild)
するようにしました(2021/05/14)。
javascript: (function() { const id = 'css_reset'; const css_resetters = [ [ 'reset.css', 'data:text/css;base64,…' ], [ 'normalize.css', 'data:text/css;base64,…' ], [ 'res.css', 'data:text/css;base64,…' ], [ 'sanitize.css', 'data:text/css;base64,…' ], [ 'remedy.css', 'data:text/css;base64,…' ], [ 'destyle.css', 'data:text/css;base64,…' ], ]; const link = document.getElementById(id); if (!link) { let css_resetters_index = 0; let link = document.createElement('link'); link.id = id; link.setAttribute('href', css_resetters[css_resetters_index][1]); link.setAttribute('data-css_resetters_index', css_resetters_index); link.setAttribute('rel', 'stylesheet'); document.head.firstChild && document.head.insertBefore(link, document.head.firstChild) || document.head.appendChild(link); console.log(css_resetters[css_resetters_index][0]); } else { let css_resetters_index = link.getAttribute('data-css_resetters_index'); if (++css_resetters_index < css_resetters.length) { link.setAttribute('href', css_resetters[css_resetters_index][1]); link.setAttribute('data-css_resetters_index', css_resetters_index); console.log(css_resetters[css_resetters_index][0]); } else { link.parentNode.removeChild(link); console.log('none'); } } } )();bookmarklet: (
70f0ac85
) CSS reset URL92bd1d9d
) CDN CSS reset URL CSS は CDN で最新を使いたい、という方のために base64 でスタイルシートを埋め込まない版も用意しました。
これは特に執筆途中に節など、HTML ソースを見ようという人々には別にみられても構わないけど、一般には目に触れられないように hidden 属性をとりあえずつけて隠しておくことがあります。それを忘れないようにブックマーク一押しで顕にします。もう一度適用すると元に戻します。そういったタグが存在するかどうかは、ブラウザコンソールのログを見るようにします。
javascript: (()=>{ const identifier = '𐇪'; let style = document.getElementById(identifier); if (style) { for (const e of document.body.querySelectorAll(`.${identifier}`)) { e.setAttribute('hidden', true); e.classList.remove(`${identifier}`); console.log('rehide', e); } style.parentNode.removeChild(style); } else { style = document.createElement('style'); style.id = `${identifier}`; style.innerHTML = `\ .${identifier} { position: absolute; background-color: #ffffff77; border-radius: .25em; }\n`; document.head.appendChild(style); for (const e of document.body.querySelectorAll('[hidden]')) { e.classList.add(`${identifier}`); e.removeAttribute('hidden'); console.log('unhide', e); } } })();bookmarklet: (
5b95133e
) unhide/rehide URL09c18191
) +unhide/rehide URL 前者はレイアウトをオリジナルの壊さないように position: absolute で顕にさせてましたが、そうすると重なって見えない画像などがあるので、レイアウトが崩れても (position: relative というか) スタイルなしで顕にする版です。
先の hidden 属性をもつタグ以外にも、似たような用途で使われるときもあるスタイルとして display: none があります。こちらも同様に、ブックマーク一押しで顕にします。もう一度適用すると元に戻します。そういったタグが存在するかどうかは、ブラウザコンソールのログを見るようにします。
あくまで、タグに直接そうしたスタイルを適用している場合のみで、クラスなどで display: none が適用されていて window.getComputedStyle()
メソッドじゃないと判断できない場合などは対象外です。
javascript: (()=>{ const identifier = '\u{2064}'; let style = document.getElementById(identifier); if (style) { for (const e of document.body.querySelectorAll(`.${identifier}`)) { e.style.display = 'none'; e.classList.remove(`display_${identifier}`); console.log('undisplay', e); } style.parentNode.removeChild(style); } else { style = document.createElement('style'); style.id = `${identifier}`; style.innerHTML = `\ .${identifier} { position: absolute; background-color: #ffffff77; border-radius: .25em; }\n`; document.head.appendChild(style); for (const e of document.body.querySelectorAll('[style*="display:"]')) { if (e.style.display != 'none') continue; e.classList.add(`${identifier}`); e.style.display = null; console.log('display', e); } } })();bookmarklet: (
119e041a
) display/undisplay URL
これも主に HTML 執筆途中などの用途ですが、内容を確認するときに閉じてあるすべての details タグをすべて開いていくのが面倒なときに、全部一気に開いてしまいます。もう一度適用すると元に戻します。そういったタグが存在するかどうかは、ブラウザコンソールのログを見るようにします。前の2例とテーマは似ているのに、アルゴリズムが随分と異なりますが、バランス的にこれで十分かと。
javascript: (()=>{ let c = 0; for (const e of document.body.querySelectorAll('details:not([open])')) { e.setAttribute('open', true); console.log(e); ++c; } if (0 < c) return; c = 0; for (const e of document.body.querySelectorAll('details[open]')) { e.removeAttribute('open'); console.log(e); ++c; } })();bookmarklet: (
d7beb6f4
) open/close details URL
閲覧環境が違いすぎるのか意図しているのか不明ですが、body その他に background 属性で背景画像を載せて、本文が非常に読みづらいページが存在します。それを一時的に除去します。もう一度適用すれば元に戻します。
javascript: (()=>{ let c = 0; for (const e of document.querySelectorAll('[background]')) { const b = e.getAttribute('background'); e.removeAttribute('background'); e.setAttribute('data-background', b); ++c; } if (0 < c) return; for (const e of document.querySelectorAll('[data-background]')) { const b = e.getAttribute('data-background'); e.removeAttribute('data-background'); e.setAttribute('background', b); } })();bookmarklet: (
a7062d41
) sink/unsink background URL
主に自作の HTML+CSS において不具合が発生したときに、問題を切り分けるためのブックマークレットなのですが、link[rel='stylesheet']
タグをすべて除去します。何か原因不明の問題が発生したときにこれを実行してみて問題が露呈しなければ、原因が除去したスタイルシートにあるのでしょう。結局大体ブラウザのバグだったりすることが多いのですけど、そこに辿り着くためにも有用です。並べて style
タグをすべて除去するブックマークレット、タグの style
属性を除去するブックマークレットを添えておきます。おんなじノリで script
タグを除去するのも作ったのですがブラウザが Javascript の実行が出来なくなるわけではないみたいなのでボツにしました。
javascript:(() => { for (const link of document.querySelectorAll("link[rel='stylesheet']")) { console.log(link); link.parentNode.removeChild(link); } })();"
javascript:(() => { for (const style of document.querySelectorAll("style")) { console.log(style); style.parentNode.removeChild(style); } })();
javascript:(() => { for (const node of document.querySelectorAll("*[style]")) { console.log(node); node.style = null; } })();
80747c9c
) remove stylesheets URL … link[rel='stylesheet']
タグをすべて除去15f98bb0
) remove styles URL … style
タグをすべて除去f8ea0072
) remove tagstyles URL … style
属性をすべて除去
HTML 文書の音声読み上げに重宝すると思うのですが、ふりがなをする仕組みである ruby タグ内において「読みがな」だけを残して他を除去します。もう一度適用すると元に戻します。たまたま戻せないときはリロードしてください。
javascript: (function () { const class_name = 'rt_only'; const res = [ /(.*)/s, new RegExp(`.*<!--${class_name}: (.*)-->`, 's') ]; for (const ruby of document.querySelectorAll('ruby')) { if (!ruby.classList || !ruby.classList.contains(class_name)) { ruby.classList.add(class_name); ruby.setAttribute('style', `display: inline-block; width: ${ruby.offsetWidth}px; text-align: center;`); ruby.innerHTML = ruby.innerHTML.replace(res[0], `${Array.from(ruby.querySelectorAll('rt')).map(v=>v.outerHTML).join('')}<!--${class_name}: $1-->`); } else { ruby.classList.remove(class_name); ruby.removeAttribute('style'); ruby.innerHTML = ruby.innerHTML.replace(res[1], '$1'); } } })();bookmarklet: leave rt only in ruby URL
私が古くに書いた HTML 文書もそうなのですが、ドメイン内リンクと文書ローカルリンクと外部リンクのスタイルを違えてなくて、多少気軽にリンクを辿れないページがあります。これを適用すると多少読みやすくなると思います。もう一度適用すると元に戻ります。
bookmarklet: (789cb9c8
) insert location style hrefs URL1d71365c
) insert rich location style hrefs URL … こちらはリッチなスタイルを挿入します。
javascript: (function () { function insert_tag_to_target(tag, attr, html = null, target = document.body, next = null) { const e = document.createElement(tag); if (attr.onload) { e.addEventListener('load', attr.onload); delete attr.onload; } for (const a in attr) e.setAttribute(a, attr[a]); if (html) e.innerHTML = html; target.insertBefore(e, next); } const id = 'a_href_location'; const text = `\ /* 1) links outside domain: external link ^https:// etc. 2) links to the same domain: local link ^/ 3) links to the same document tree: relative link ^. etc. 4) links to the same page: self link ^#, ^? */ a[href] { text-underline-offset: 25%; } a[href]:link, a[href]:visited { text-decoration: none; } a[href]:hover, a[href]:active { text-decoration: underline solid; } a[href^='#']:hover, a[href^='#']:active, a[href^='?']:hover, a[href^='?']:active, a[href^='.']:hover, a[href^='.']:active, a[href^='/']:hover, a[href^='/']:active { text-decoration: underline dotted CanvasText; } a:not([href*='://']):hover, a:not([href*='://']):active { text-decoration: underline dotted CanvasText; } a::before, a::after { display: inline-block; text-decoration: none; vertical-align: top; font-size: smaller; } a[href^='#']::before { content: '⥯ '; } a[href^='?']::before { content: '⤺ '; } a[href^='.']::before { content: '⥪ '; } a[href^='/']::before { content: '⇱ '; } a[href^='mailto:']::before { content: '🡔 '; } a[href^='http:']::before, a[href^='ftp:']::before { content: '⌁ '; } a[href^='http:']::after, a[href^='https:']::after, a[href^='ftp:']::after { content: ' 🡒'; } a[href][target='_blank']::after { content: ' 🡕'; } a[href^='#']::before, a[href^='?']::before { color: mediumblue; } a[href^='mailto:']::before, a[href][target='_blank']::after { color: dodgerblue; } a[href^='http:']::before, a[href^='ftp:']::before, a[href][rel*='nofollow']::after, a[href][rel*='sponsored']::after { color: orange; } a[href][rel*='noreferrer']::after, a[href][rel*='noopener']::after { color: LinkText; } `; const style = document.getElementById(id); if (style) style.parentNode.removeChild(style); else insert_tag_to_target('style', { id: id, }, text, document.head); })();bookmarklet: (
74e14563
) insert more rich location style hrefs URL … セキュリティ的見地による着色を加えて、さらにリッチなスタイルを挿入します。
これは自分が必要だったのですが、ページに動画をある時間間隔に切り取って貼り付けている場合、それらの「開始時刻,終了時刻=閲覧時間」を人間が見てわかりやすい表示で確認したいときがありました。
,00:11:21 <video controls="" src="無題の動画.mp4#t=,00000681"> 00:11:21,00:18:11=00:06:50 <video controls="" src="無題の動画.mp4#t=00000681,00001091"> 00:18:11,00:38:24=00:20:13 <video controls="" src="無題の動画.mp4#t=00001091,00002304"> 00:38:24,00:57:10=00:18:46 <video controls="" src="無題の動画.mp4#t=00002304,00003430"> 00:57:10,01:07:39=00:10:29 <video controls="" src="無題の動画.mp4#t=00003430,00004059"> 01:07:39,01:20:16=00:12:37 <video controls="" src="無題の動画.mp4#t=00004059,00004816"> 01:20:16,01:32:24=00:12:08 <video controls="" src="無題の動画.mp4#t=00004816,00005544"> 01:32:24, <video controls="" src="無題の動画.mp4#t=00005544,">
こんな感じに「ログ」に印字されます。自分専用としか思えないのですが、もしかしたら需要があるかもしれませんので。
javascript: (function () { const res = [ /.*[#\+]t=(),(\d+).*/, /.*[#\+]t=(\d+),(\d+).*/, /.*[#\+]t=(\d+)().*/ ]; const re = / .*/; for (const e of document.body.querySelectorAll("video[src*='t=']")) { let tmstrs = [ "", "", "" ], times = [ new Date(0, 0), new Date(0, 0), new Date(0, 0) ], m; let i = 0; for (; i<res.length; ++i) if ((m=e.src.match(res[i]))) { tmstrs[0] = m[1]; tmstrs[1] = m[2]; break; } switch (i) { case 0: // from the beginning times[1].setSeconds(parseInt(tmstrs[1])); tmstrs[1] = times[1].toTimeString().replace(re, ''); console.log(`,${tmstrs[1]}`, e); break; case 1: times[0].setSeconds(parseInt(tmstrs[0])); times[1].setSeconds(parseInt(tmstrs[1])); times[2].setSeconds((times[1].getTime() - times[0].getTime())/1000); tmstrs[0] = times[0].toTimeString().replace(re, ''); tmstrs[1] = times[1].toTimeString().replace(re, ''); tmstrs[2] = times[2].toTimeString().replace(re, ''); console.log(`${tmstrs[0]},${tmstrs[1]}=${tmstrs[2]}`, e); break; case 2: // to the ending times[0].setSeconds(parseInt(tmstrs[0])); tmstrs[0] = times[0].toTimeString().replace(re, ''); console.log(`${tmstrs[0]},`, e); break; default: break; } } })();bookmarklet: (
80f7cbb1
) log video time duration URL
次節で紹介している prefbar は、Firefox 57 から多くのボタンが使えなくなっていますので、以上、ブックマークレットとして代替の機能を紹介しました。
私が重宝しているのはprefbarアドオンで、それに関連したabout:configの設定などをまとめておきたいと思います。
稀に色を多用していて非常に読みづらいページがあります。私には、やり過ぎな配色が邪魔して努力無しでは内容が頭に入ってきません。
この場合、アドレスバーに「about:config
」と入力して、設定項目で「browser.display.use_document_colors
」を探してオフにすれば読み易くなります。しかし、そんなページは稀ですので、いちいちabout:configで設定するのは面倒です。
以上のような用途にprefbarアドオンをインストールすると、ツールバーに「カラー」ボタンが追加できるので、必要な時に必要な設定が出来るようになります。
まず、prefbarに予め搭載されているボタンの内で、極めて重要で便利なものを、対応するabout:configの項目があればそれを添えて紹介します。
browser.display.use_document_colors
」を1か0に設定(1: 文書の指定する配色、0: ブラウザが指定する配色、前述のもの)permissions.default.image
」を1か2に設定(1: すべての画像を表示、2: すべての画像を非表示、しかし、3: サイト内の画像のみ表示、を選べず不適当)image.animation_mode
」を'normal
' か'none
'に設定(gifアニメーション、アニメーテッドpng、SVG SMILの有効・無効が設定されます)network.cookie.cookieBehavior
」を2か0に設定(2: すべてのCookieを許可、0: すべてのCookieを拒否、なので1: 文書があるWebサイトから送信されるCookieのみ許可、を選べず不適当)javascript.enabled
」でJavascriptの有効・無効を設定network.http.sendRefererHeader
」を0か2に設定(リンク元のURLをサーバに送信するか否かを設定、送信すると拒否されるサイトが稀にありますので便利です)network.proxy.type
」を0: 直接接続、1: 手動設定、2: 自動検出のいずれかに設定(この手動設定はブラウザのプロキシ設定で予め行っておきます。ssh -D 利用者には便利です)intl.accept_languages
」を規定値か様々な国向けの設定から選択(コンテントネゴシエーションにより英語が閲覧できない場合などで英語を選ぶと便利です)browser.display.use_document_fonts
」を0か1に設定(0: ユーザが指定したフォントを使用、1: 文書が指定したフォントを使用、なのでIEによる悪しきゴシック文化の無効化に便利です)ここで画像、Cookie、Java以外は特に問題なく使え大変便利です。さらに、私が作成したボタンを紹介します。まずは、設定を安全側に倒していない時と安全側に倒した時のスクリーンショットをご覧下さい。
ここで私が作成したボタンのうち、まず雑多なものを紹介します。特に、Cookie、Javaについては上記の問題を解決してあります。
permissions.default.image
」を2: すべての画像を非表示、3: サイト内の画像のみ表示、1: すべての画像を表示のいずれかに設定(視認性考慮)accessibility.blockautorefresh
」の無効・有効を設定(利便性考慮)dom.storage.enabled
」を有効・無効に設定(プライバシー考慮)dom.indexedDB.enabled
」を有効・無効に設定(プライバシー考慮)※ Firefox 35.0.1 ではこれが無効だと「以前のセッションの復元」や「最近閉じたタブ」などが使えなくなるようです。gfx.downloadable_fonts.enabled
」を有効・無効に設定(フォントレンダラに脆弱性が絶対にないとでも?こんなものは必要になったら有効にすればよいのです。セキュリティ考慮)geo.enabled
」を有効・無効に設定(こんなものは必要になったら有効にすればよいのです。プライバシー考慮)media.autoplay.enabled
」を有効・無効に設定(視認性考慮)network.cookie.cookieBehavior
」を1か0に設定(1: 文書があるWebサイトから送信されるCookieのみ許可、0: すべてのCookieを拒否、プライバシー考慮)
network.cookie.cookieBehavior
」を2: すべてのCookieを許可、1: 文書があるWebサイトから送信されるCookieのみ許可、0: すべてのCookieを拒否から選択可能にしたもの(プライバシー考慮)media.wave.enabled
」を有効・無効に設定(こんなものは必要になったら有効にすればよいのです。セキュリティ考慮)media.ogg.enabled
」を有効・無効に設定(こんなものは必要になったら有効にすればよいのです。セキュリティ考慮)media.webm.enabled
」を有効・無効に設定(こんなものは必要になったら有効にすればよいのです。セキュリティ考慮)webgl.disabled
」を無効・有効に設定(こんなものは必要になったら有効にすればよいのです。セキュリティ考慮)svg.smil.enabled
」を有効・無効に設定(視認性考慮)pdfjs.disabled
」を無効・有効に設定(利便性考慮)ここで配布している*.btn
は、prefbarの右クリックのカスタマイズの右クリックのインポートで導入することが出来ます。
さらに、その他の私が作成したボタンを紹介します。
browser.urlbar.trimURLs
」を有効・無効に設定(アドレスバーにURLを入力する時にプロトコルを省略してしまいがちになります。常に無効にしましょう。プライバシー考慮)network.prefetch-next
」を有効・無効に設定(閲覧したつもりもないのにサイトにアクセスしてる場合があります。それはこれがデフォルトで有効だからです。常に無効にしましょう。プライバシー考慮)browser.chrome.favicons
」を有効・無効に設定(faviconのキャッシュ有無検証で訪問済みサイトが漏洩する可能性があります。常に無効にしましょう。プライバシー考慮)browser.chrome.site_icons
」を有効・無効に設定(siteiconのキャッシュ有無検証で訪問済みサイトが漏洩する可能性があります。常に無効にしましょう。プライバシー考慮)browser.urlbar.maxRichResults
」を有効・無効に設定(プライバシー考慮)browser.search.suggest.enabled
」有効・無効に設定(プライバシー考慮)以上の多くのボタンを並べると、ブラウザのウィンドウの幅に入り切らず使いにくいかと思われます。そういった場合は、prefbarで右クリックのカスタマイズの右クリックで、作成、サブメニューを選ぶと、いくつかのボタンをそのなかにまとめることができます。
スクリーショットの「メディア」がそのサブメニューです。そして、そのサブメニューと中身のアイテムをカスタマイズで選んだ上で右クリック、そしてエクスポートできます。
稀に書体の種類を前提としつつも文書に書体指定がなく、意図が伝わり難い場合があります。典型例が、日本語環境IEを前提とした日本特有のアスキーアートです。日本では、プロポーショナルフォントでアスキーアートなどという思いもよらない特異な独自の文化が形成されており、フォントは日本語環境IEの規定値「MS Pゴシック 11pt」を想定しているようです。よって、環境が変わるとこのアスキーアートは作者の意図通りに表示されません。しかし、「IPAモナー、Textar、RobotoJAA、梅P」フォントのいずれかをインストールするとそれに近い閲覧環境が得られるようです(TextarとRobotaJAAはちょっと大きい気がしますが)。それをトグルボタンかメニューで一発で切り替えるprefbarのボタンや、その他フォント関連のボタンを用意してみました。
browser.display.use_document_fonts
」を0か1に設定(prefbar標準搭載の「フォント」と同等、分かり易い翻訳にしただけ。利便性考慮)font.default.ja
」を'serif
'か'sans-serif
' のいずれかに設定(利便性考慮)font.name.serif.ja
」を他のブラウザもよく使う明朝体フォントから選択(利便性考慮)font.name.sans-serif.ja
」を他のブラウザもよく使うゴシック体フォントから選択(利便性考慮)font.name.monospace.ja
」を他のブラウザもよく使う等幅フォントから選択(利便性考慮)font.size.variable.ja
, font.size.fixed.ja
」を「14, 12」に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を「MS P」系に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を「IPAモナーP」系に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を「Textarフォント」に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を「RobotoJAAフォント」系に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を「梅Pフォント」系に切り替えるか、リセットするfont.default.ja
, font.name.sans-serif.ja
, etc」を各種日本語フォントに切り替えるか、リセットするfont.size.variable.ja
, font.size.fixed.ja
」を…「9, 8」「11, 10」「13, 12」「16, 14」「19, 17」「23, 20」「28, 24」…に切り替えるか、リセットするprefbarのカスタマイズで「ボタンの追加」でサードパーティのボタンが追加できます。精査はしていませんが、ここで紹介したものと重なるものもあるようです。その他、いくつか有用なボタンを紹介します。
browser.zoom.full
」を有効・無効に設定(ズームの拡大・縮小がレイアウトを保持したままか、従前のフォントサイズのみかを切り替える。これが「browser.zoom.siteSpecific
」と連動してくれればベターなんですが、今ひとつです)file:///Users/taiji/Sites/index.html
, http://localhost/
などでは出来ないので今ひとつです)。file:///Users/taiji/Sites/index.html
, http://localhost/
なども検証可能です。prefbarではボタンにショートカットキーを割り当てることができ、非常に便利です。以下の二つ目の機能に「ホットキー」と呼ばれるショートカットキーを割り当てました。
prefbarを用いるとJavascriptで簡単にDOM(Document Object Model)操作を行なうことができます。ここでは以下の問題提起とその解決策をprefbarボタンで実現する「ドキュメントURLツール・ボタンセット [2012/09/29]」を紹介します。
http://ime.nu/
)。このボタンを押すと正しいURLにリンクを貼り直します。では具体的にどのように実現されているかいくつかを例に見てみましょう。
function check_img_hrefs(node) { var tag_a = node.getElementsByTagName('a'); // 「a」タグの配列を取得 for (var i=0; i<tag_a.length; ++i) { // すべての「a」タグについて、 if (tag_a[i].href.match(/\.(jpg|gif|png)$/)) { // 「href」属性が画像のときのみ、 if (/^img$/i.test(tag_a[i].lastChild.tagName) && // 「a」タグの最後の子要素が「img」タグ、かつ、 tag_a[i].lastChild.src == tag_a[i].href) // 「img」タグの「src」属性と「href」属性が等しければ、 continue; // 既に埋め込まれている、さもなくば、 return true; // 埋め込まれていない(チェックはtrue)で終了 } } return false; // さもなくば、既にすべて埋め込まれている(チェックはfalse) } value = check_img_hrefs(gBrowser.contentDocument.body); // 以上の操作を document.body 要素から調査し、結果をprefbarのvalueへ代入
function embed_hrefs(node) { var tag_a = node.getElementsByTagName('a'); // 「a」タグの配列を取得 for (var i=0; i<tag_a.length; ++i) { // すべての「a」タグについて、 if (tag_a[i].href.match(/\.(jpg|gif|png)$/)) { // 「href」属性が画像のときのみ、 tag_a[i].innerHTML += '<img src="' + tag_a[i].href + '" border=0/>'; // 「a」タグの内部HTMLの最後に「img」タグを「href」属性を指定して追加 } } } if (!value) { // Get-Function がオンからオフになったら、 embed_hrefs(gBrowser.contentDocument.body); // 以上の操作を document.body 要素から実行 }
基本はgetElementsByTagName
で目的のタグを辿ることにあります。他のボタンも以下の例外を除き、同様に実現しています。
一方で、タグ名を手掛かりに辿れないテキストについては、以下のようにすべての要素を辿る必要があります。
function check_text_link(node) { // すべての要素をこの関数を用いて再帰的に調査 if (node.nodeType === 3) { // テキストノードなら if (node.nodeValue.match(/\b(h?ttp:\/\/(\S+))/)) { // テキストの値がURL(もしくはh抜き)にマッチなら、 return true; // 真を返して終了(チェックはtrue) } } else if (node.nodeType === 1 && // 要素ノード、かつ !/^(style|script|iframe|pre|a)$/i.test(node.tagName)) { // タグ名が調査対象外ではないなら、 for (var i=0; i<node.childNodes.length; ++i) { // すべての子要素について if (check_text_link(node.childNodes[i])) // この関数を再帰的に呼んで、どれかがテキストがURLなら return true; // 真を返して終了(チェックはtrue) } } return false; // さもなくば偽を返して終了(チェックはfalse) }; value = check_text_link(gBrowser.contentDocument.body); // 以上の操作を document.body 要素から調査し、結果をprefbarのvalueへ代入
function text_link(node) { // すべての要素をこの関数を用いて再帰的に操作 var parentNode = node.parentNode; if (node.nodeType === 3) { // テキストノードなら if (node.nodeValue.match(/\b(h?ttp:\/\/(\S+))/)) { // テキストの値がURL(もしくはh抜き)にマッチなら、 var url = 'http://' + RegExp.$2; var a = gBrowser.contentDocument.createElement('a'); // 「a」タグを生成 a.href = url; a.appendChild(document.createTextNode(RegExp.$1)); // 「a」タグにテキスト要素(マッチした元のURL)を追加 parentNode.insertBefore(document.createTextNode(RegExp.leftContext), node); // テキストノードの前にテキスト要素(マッチの左側のテキスト)を追加 parentNode.insertBefore(a, node); // テキストノードの前に「a」タグを追加 parentNode.insertBefore(document.createTextNode(RegExp.rightContext), node); // テキストノードの前にテキスト要素(マッチの右側のテキスト)を追加 parentNode.removeChild(node); // このテキストノードそのものは削除 } } else if (node.nodeType === 1 && // 要素ノード、かつ !/^(style|script|iframe|pre|a)$/i.test(node.tagName)) { // タグ名が調査対象外ではないなら、 for (var i=0; i<node.childNodes.length; ++i) { // すべての子要素について text_link(node.childNodes[i]); // この関数を再帰的に呼んで、操作 } } } if (!value) { // Get-Function がオンからオフになったら、 text_link(gBrowser.contentDocument.body); // 以上の操作を document.body 要素から実行 }
基本はchildNodes
配列ですべての要素を辿ることにあります。また、innerHTML
を書き換えるか、createElement
の追加・削除で書き換えるかは、以上の二つの例のように少々コツが必要です。nodeTypeがいつ決定されるべきなのかを考えればどちらがよいかわかると思います。また、埋め込み画像の追加などは、innerHTML
を書き換える方式じゃないと画像の読み込みと描画がなされないようです。
prefbarのカスタマイズで「初期化」というのがあります。これはボタンIDに従って既定の内容に戻すためのもので、ボタンの配置や別途作成した別のIDのボタンには影響がありません。新しいprefbarをインストールした際に最新の状態に追従したい時に便利です。また、追従したくないボタンについては、複製してIDを別のものにしたものにしておけば、独自のボタン設定が消されないで済みます。
昨今はブラウザも機能過多になり、枯れていない技術だと特にその脆弱性が狙われやすく、使っていない機能は是非とも無効にしておきたいものです。以下のサイトは、ブラウザの機能や設定を確認するために作成したものですのでどうぞ活用して下さい。
もう一つの防衛策として、いくつかのブラウザを使い分ける、そのメリットを述べた文書をなるべく初心者向けに書きました。ブックマークレット作成入門も添えましたので、本稿を基礎から知りたいという方は是非。