Tips on Mozilla

Created: 2012/08/22 | Last modified: 2022/09/11
../

Contents

ここではMozilla系ブラウザ(Firefox/SeaMonkey/Camino)に関するちょっとしたコツを扱います。

拡張機能(アドオン)

Mozilla 系の拡張機能は XUL/XPCOM 技術基盤による実装でしたが、Firefox は Google Chrome とともに WebExtension (ブラウザ拡張機能) へと移行しました。よって、かつての拡張機能は Firefox では使えなくなっています。

また、拡張機能のセキュリティアップデートについては XUL/XPCOM においては特に注意を払う必要があります。よって、更新が滞っている拡張機能などの使用は控えた方が懸命です。

ここでは Firefox/SeaMonkey について筆者がお勧めの拡張機能をまとめておきます。

検索プラグイン

Firefox 40.0 からすべてのユーザ向けの検索プラグインを置いておく場所がなくなってしまいました。どうも、書庫「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/」に置いておけば良いようです))。ちなみに、私は以下の追加の検索プラグインを使っています。但し、(*)が付いたものは最近のデフォルトにて重なるものです。

Bookmarklets

以下、ブックマークレットのリンクの先頭に添えてあるのは、バージョン確認のための CRC32 値です。ブックマークレットの文字列は読み辛いので、ブックマーク管理にそのままドラッグ&ドロップしてタイトルとともに CRC32 値と保持し、手元の版との違いを気付きやすくしています。


Bookmarklet でブラウザをさらに便利に扱うことが出来ます。下記のような Javascript コードを思いついたら、bookmarkletify and unbookmarkletify でエンコードしてブックマークに登録しましょう。そのようにしたものを下記に紹介します。さらにウェブ等でそれを紹介したければ、ソースを preify and unpreify にて pre タグに記述可能にするといいと思います。

duplicate URL ﹘ タブの複製

ブラウザの「タブの複製」は履歴等も新たなタブに複製されますが、これは閲覧している URL を別タブにて再表示するためのブックマークレットです。そのページはそのままに新たに URL を打ち直してみたい時に重宝します。

javascript:
window.open(location.href, '_blank', null);
void(0);
bookmarklet: (e0945da3) duplicate URL

cacheify 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

archive 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

localhost/unlocalhost 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

主旨は同じですが、別タブで切り替え先のホストを開くプックマークレットも作成しました。正直こちらの方が便利です。

bookmarklet: (29f63b58) duplicate localhost/unlocalhost URL

ところで、似たような用途で以下のような URL をブックマークレット一つで置き換えたいとも思いましたが、URL が file:// でも Javascript が発動するので機能するのですが、https?:// からは file:// への参照は許可されていないので機能しません。ちょっと不便ですが一応、紹介しておきます。

bookmarklet: (3a80526c) duplicate file → localhost URL

webmaster/unwebmaster URL ﹘ ドラフトサイト (~webmaster) と公開サイトの切り替え

ドラフトサイト (~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

主旨は同じですが、別タブで切り替え先のサイトを開くブックマークレットも作成しました。どちらでもお好きな方で。

bookmarklet: (386356d1) duplicate webmaster/unwebmaster URL

translate into ja 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 URL
bookmarklet: (6d5198e9) multi translate into ja URL … マルチ翻訳ウェブサービスに対応(サービス提供側による制限が生じること多々あり)

translate into en 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 URL
bookmarklet: (d51aa733) multi translate into en URL … マルチ翻訳ウェブサービスに対応(サービス提供側による制限が生じること多々あり)

validate HTML ﹘ 閲覧中のページの HTML を検証

閲覧中の文書の 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() をブラウザの特性を利用したものに置き換えました。

Validate CSS ﹘ 閲覧中のページの CSS を検証

閲覧中の文書の 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() をブラウザの特性を利用したものに置き換えました。

Validate I18N ﹘ 閲覧中のページの HTML の国際化を検証

閲覧中の文書の 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

history back2 URL ﹘ 閲覧中のページから「2つ戻る」

たまにブラウザの「戻る」ボタンやショートカットで、戻れないサイトがあります。マイクロソフトのページに多いのですが、ブラウザの「戻る」ボタンを長押ししてみると、1ページのつもりが2ページ閲覧していることになっているのですよね。なので、1つ戻ると自動転送で進んでしまうので、普通には戻れないのです。履歴から2つ前を選んで戻ることはできます。素早く「戻る!戻る!」とすれば(上手くすれば2つ前に)戻れます。

このブックマークレットはブラウザの履歴において「2つ戻る」ボタン代わりです。問題提起として、このようなページを作成するサイトが無くなることを祈って。

javascript:window.history.go(-2);
bookmarklet: (fdd1f837) history back2 URL

duplicate VGA window URL ﹘ 閲覧中のページを VGA 解像度の別ウィンドウで閲覧

狭い画面解像度でページを閲覧したらどのように見えるか、別ウィンドウで確認します。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 のウィンドウで閲覧中のページを開く
bookmarklet: duplicate SVGA window URL ﹘ 800x600 のウィンドウで閲覧中のページを開く
bookmarklet: duplicate XGA window URL ﹘ 1024x768 のウィンドウで閲覧中のページを開く
bookmarklet: duplicate SXGA window URL ﹘ 1280x1024 のウィンドウで閲覧中のページを開く
bookmarklet: duplicate FHD window URL ﹘ 1920x1080 のウィンドウで閲覧中のページを開く

++page URL ﹘ 閲覧中のページのページ番号を増分する

ブログ記事などページ番号が指定されている 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

shorten amazon URL ﹘ 閲覧中の Amazon のページの 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

shorten URL ﹘ 閲覧中の Amazon, Youtube のページの 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


noopener URLs ﹘ ターゲットが _blank であるリンクに noopener を設定

このような <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 URLs
bookmarklet: (a0d1965c) 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

normalize 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

emded 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] 画像の埋め込み大き過ぎ、他、改良しました。
bookmarklet: (bd2e3094) link, normalize & embed URLs [2022/02/04] 同上、改良しました。

cacheify URLs ﹘ 閲覧中のページのリンク群をキャッシュへのリンクに変換

閲覧中の文書のリンクを全て 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 URLs
bookmarklet: (f7081c8d) toggle cacheify URLs … そのトグル版で、もう一度適用すると Google キャッシュへのリンクを外します。

archive URLs ﹘ 閲覧中のページのリンク群をアーカイブへのリンクに変換

閲覧中の文書のリンクを全て 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 URLs
bookmarklet: (73474935) toggle archive URLs … そのトグル版で、もう一度適用すると archive.org へのリンクを外します。

monochromize URL ﹘ 閲覧中のページの配色をモノクロへ

閲覧中の文書にスタイルを挿入してモノクロにします。配色が派手すぎて内容が頭に入ってこないページに便利です。

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

hide media 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

remove 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

flipY video URL ﹘ 閲覧中のページの video を Y 軸フリップ

なぜこんなブックマークレットを作ったか覚えてないのですが、視聴中の動画を左右反転します。もう一度適用すると戻します。

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 反転
bookmarklet: (18933ef4) flipX video tags ﹘ X 軸 video 反転
bookmarklet: (fd27470f) flipXY video tags ﹘ X, Y 軸 video 反転
bookmarklet: (9f4406f0) rotate clockwise video tags ﹘ 時計回り回転
bookmarklet: (4516776d) rotate anti clockwise video tags ﹘ 反時計回り回転

body columns two URL ﹘ 閲覧中のページ全体を2段組に

通常の一段組だと間伸びしてビューの情報量が少ないページがあります(例えば本ページとか)。強引に 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

sectioning h2 columns two URL ﹘ 閲覧中のページの h2 範囲を2段組に

前者は 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

hide/reveal HREFs ﹘ a[href] を一時的に隠す/戻す

ウェブページのテキストをコピーしようとして、そこがリンクでテキストのコピーに難儀したことはありませんか?このブックマークレットで一時的にコピーしやすいようにリンクを隠します。もう一度呼べばリンクを戻します。

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

clicked elements remover ﹘ クリックした要素を削除

閲覧中のページでどれかキーを押すまで、クリックした要素を削除し続けます。

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


sans-serif fontify (ja) URL ﹘ pre, tt, code, kbd, samp タグ以外を日本語のゴシック体へ

閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語のゴシック体に切り替えます。再度適用すれば、それを元に戻します。

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

serif fontify (ja) URL ﹘ pre, tt, code, kbd, samp タグ以外を日本語の明朝体へ

閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語の明朝体に切り替えます。再度適用すれば、それを元に戻します。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 sans-serif fontify (ja) URL ﹘ pre, tt, code, kbd, samp タグ以外を日本語のMS P互換ゴシック体へ

閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグ以外のタグを日本語の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

monospace fontify (ja) URL ﹘ pre, tt, code, kbd, samp タグを日本語の等幅フォントへ

閲覧中の文書にスタイルを挿入して等幅フォントがよく使われるタグを日本語の等幅フォントに切り替えます。再度適用すれば、それを元に戻します。プログラミングを教えるにあたって、零「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

cursive fontify (ja) URL ﹘ pre, tt, code, kbd, samp, h1 … タグ以外を日本語の教科書体へ

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語の教科書体や筆記体に切り替えます。再度適用すれば、それを元に戻します。文書がとても読みやすくなることを感じることができると思います。

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

fantasy fontify (ja) URL ﹘ pre, tt, code, kbd, samp, h1 … タグ以外を日本語の丸ゴシック体へ

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語の丸ゴシック体やポップ体に切り替えます。再度適用すれば、それを元に戻します。文書がくだけた雰囲気になることを感じることができると思います。

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

kern glyphs fontify (ja) URL ﹘ pre, tt, code, kbd, samp, h1 … タグ以外を日本語のカーニングを変更

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグについて、以下の日本語のカーニングの種類を逆順に切り替えます。一周したら元に戻ります。

なし
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅全角字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅全角字形&字幅半角メトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&字幅半角メトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅三分字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅三分字形&字幅半角メトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅四分字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅四分字形&字幅半角メトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅半角字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅半角字形&字幅半角メトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

prop glyphs fontify (ja) URL ﹘ pre, tt, code, kbd, samp, h1 … タグ以外を日本語をプロポーショナルへ

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグを日本語をプロポーショナルに切り替えます。再度適用すれば逆に固定幅へ、再々度適用すれば、それを元に戻します。

プロポーショナル数字&プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
等幅数字&等幅半角字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

fixw glyphs fontify (ja) URL ﹘ pre, tt, code, kbd, samp タグを日本語を固定幅へ

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグを日本語を固定幅に切り替えます。再度適用すれば逆にプロポーショナルへ、再々度適用すれば、それを元に戻します。

等幅数字&等幅半角字形
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。
プロポーショナル数字&プロポーショナル字形&プロポーショナルかな&プロポーショナルメトリクス
1の総和は-1/2に、自然数の総和は -1/12に、2の冪の総和は-1に収束する。

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

vkrn glyphs fontify (ja) URL ﹘ pre, tt, code, kbd, samp, h1 … タグ以外を日本語の縦書きカーニングを変更

閲覧中の文書にスタイルを挿入して見出しおよび等幅フォントがよく使われるタグ以外のタグについて、以下の縦書きの日本語のカーニングの種類を逆順に切り替えます。一周したら元に戻ります。

縦組み用字形
吾輩わがはいは猫である。名前は「イヌ」である。(パンクブーブー)
縦組み用字形&縦組み字幅半角メトリクス
吾輩わがはいは猫である。名前は「イヌ」である。(パンクブーブー)
縦組み用字形&縦組みプロポーショナルメトリクス
吾輩わがはいは猫である。名前は「イヌ」である。(パンクブーブー)

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

variant glyphs fontify (ja) URL ﹘ * タグを日本語の字形を変更

閲覧中の文書にスタイルを挿入してすべてのタグについて、以下の日本語の字形の種類を順に切り替えます。一周したら元に戻ります。

なし
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
JIS78 字形
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
JIS83 字形
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
JIS90 字形
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
JIS2004 字形
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
旧字体
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩
印刷標準字体
喝 祇 竈 龜 唖啞 鴎鷗 噛嚙 蝉蟬 塚塚 攅攢 靫靭 鯵鰺 鶯鴬 頚頸 莱萊 賎賤 壺壷 迩邇 籠篭 蕊蘂 檜桧 晟燿渣氈鯱凛匕喩巉檐魍贏贅癲均漾襪 隙厩

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

frac other glyphs fontify URL ﹘ * タグを字形を分数や他に変更

閲覧中の文書にスタイルを挿入してすべてのタグについて、以下の字形の種類を順に切り替えます。一周したら元に戻ります。

分数 'frac'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
上付き文字 'sups'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
下付き文字 'subs'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
上付き序数表記 'ordn'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
ライニング数字 'lnum'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
オールドスタイル数字 'onum'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
プロポーショナル数字 'pnum'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
等幅数字 'tnum'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
一般的な合字/標準合字 'liga' 0, 'clig' 0
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
前後関係に依存する字形 'calt' 0
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
任意の合字 'dlig'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
スモールキャップス 'smcp'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
大文字のスモールキャップス 'c2sc'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
スワッシュ字形 'swsh'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
カーニング 'kern'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
字体組版/分解 'ccmp' 0
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
ローカライズの字形 'locl' 0
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
デザインのバリエーション 'salt'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
デザインのバリエーション 2 'salt' 2
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
デザインのセット 1 'ss01'
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙
なし
0123456789 ff fi fl ffi. The bloom has gone off the rose. ct sp st. Fred And Ginger. An easy & breezy Sunday morning. Add 1 3/4 C of floor, 1/2 cup at a time. 1st, 2nd, 3rd. あ゙

指定しているフォントの種類によっては、以上のような機能を持たず「何しても変化しない」ということもありえます。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

cursive font rotate (ja) URL and others ﹘ * タグを日本語の字形を教科書体の中から順に変更、他

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
bookmarklet: serif cursive font rotate (ja) URL
bookmarklet: MS P sans-serif font rotate (ja) URL
bookmarklet: monospace font rotate (ja) URL
bookmarklet: cursive font rotate (ja) URL
bookmarklet: fantasy font rotate (ja) URL

しかし、それでも相当長いブックマークレットでもブックマークに登録できることが分かります。

emoji font rotate 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 specify URL ﹘ * タグの行の高さを固定

指定したフォントに依っては、いやに行送りが狭かったり、逆に広かったりします。調べてみると、ブラウザ既定の line-heightnormal とやらが、どうもフォントから決定しているようです。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/unjascientify URL ﹘ 閲覧中のページの約物(、。「」『』)⇔(,. ‘’ “” )の相互変換

閲覧中の文書のノードをパースしてしてテキスト及びコメントの約物(、。「」『』)を(,. ‘’ “” )に変換します。再度適用すれば、逆変換します。技術文書のようになることを感じることができると思います。ちなみに、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

janormalize/unjanormalize URL ﹘ 閲覧中のページの JIS X 0213 で非推奨の全角のラテン文字や半角のカタカナ ⇔ 推奨の半角のラテン文字や全角のカタカナの相互変換

閲覧中の文書のノードをパースしてしてテキスト及びコメントの 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

root vertical-rl writing-mode URL ﹘ 閲覧中のページの body スタイルを縦書き仕様に変更

縦書き仕様のスタイルに変更します。青空文庫などが縦書きで読めて、便利です。

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
bookmarklet: janormalize and root vertical-rl writing-mode URL … 先の janormalize (ja) URL を施してから縦書きに変更
bookmarklet: root vertical-rl writing-mode 青空文庫 URL … 青空文庫の XML 文書向けに縦書きに変更


CSS reset URL – 閲覧中のページのスタイルにCSSリセットスタイルを挿入

ユーザーエージェントの種類に依らず見た目を統一したいという目的で、リセット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 URL
bookmarklet: (92bd1d9d) CDN CSS reset URL CSS は CDN で最新を使いたい、という方のために base64 でスタイルシートを埋め込まない版も用意しました。

unhide/rehide URL – 閲覧中のページの hidden 属性をもつタグを顕にする

これは特に執筆途中に節など、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 URL
bookmarklet: (09c18191) +unhide/rehide URL 前者はレイアウトをオリジナルの壊さないように position: absolute で顕にさせてましたが、そうすると重なって見えない画像などがあるので、レイアウトが崩れても (position: relative というか) スタイルなしで顕にする版です。

display/undisplay URL – 閲覧中のページの display: none スタイルをもつタグを顕にする

先の 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

open/close details URL – 閲覧中のページの閉じてある details タグを開いて summary タグを顕にする

これも主に 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

sink/unsink background URL – 閲覧中のページの background 属性を除去

閲覧環境が違いすぎるのか意図しているのか不明ですが、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

remove stylesheets URL and others ﹘ 閲覧中のページのスタイルシートを除去、他

主に自作の 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;
}
})();
bookmarklet: (80747c9c) remove stylesheets URLlink[rel='stylesheet'] タグをすべて除去
bookmarklet: (15f98bb0) remove styles URLstyle タグをすべて除去
bookmarklet: (f8ea0072) remove tagstyles URLstyle 属性をすべて除去

leave rt only in ruby URL ﹘ 閲覧中のページのルビを rt タグのみにする(読み上げ向け)

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

insert location style hrefs URL ﹘ 閲覧中のページの a[href] タグのスタイルを挿入

私が古くに書いた HTML 文書もそうなのですが、ドメイン内リンクと文書ローカルリンクと外部リンクのスタイルを違えてなくて、多少気軽にリンクを辿れないページがあります。これを適用すると多少読みやすくなると思います。もう一度適用すると元に戻ります。

bookmarklet: (789cb9c8) insert location style hrefs URL
bookmarklet: (1d71365c) 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 … セキュリティ的見地による着色を加えて、さらにリッチなスタイルを挿入します。


video time duration URL ﹘ 閲覧中のページの video[src*='#t='] タグの各種時間をログに印字

これは自分が必要だったのですが、ページに動画をある時間間隔に切り取って貼り付けている場合、それらの「開始時刻,終了時刻=閲覧時間」を人間が見てわかりやすい表示で確認したいときがありました。

,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

prefbarとabout:config

私が重宝しているのはprefbarアドオンで、それに関連したabout:configの設定などをまとめておきたいと思います。

文書の配色

稀に色を多用していて非常に読みづらいページがあります。私には、やり過ぎな配色が邪魔して努力無しでは内容が頭に入ってきません。

この場合、アドレスバーに「about:config」と入力して、設定項目で「browser.display.use_document_colors」を探してオフにすれば読み易くなります。しかし、そんなページは稀ですので、いちいちabout:configで設定するのは面倒です。

以上のような用途にprefbarアドオンをインストールすると、ツールバーに「カラー」ボタンが追加できるので、必要な時に必要な設定が出来るようになります。

prefbar標準搭載の主なボタンとabout:config

まず、prefbarに予め搭載されているボタンの内で、極めて重要で便利なものを、対応するabout:configの項目があればそれを添えて紹介します。

ここで画像、Cookie、Java以外は特に問題なく使え大変便利です。さらに、私が作成したボタンを紹介します。まずは、設定を安全側に倒していない時と安全側に倒した時のスクリーンショットをご覧下さい。

ここで私が作成したボタンのうち、まず雑多なものを紹介します。特に、Cookie、Javaについては上記の問題を解決してあります。

ここで配布している*.btnは、prefbarの右クリックのカスタマイズの右クリックのインポートで導入することが出来ます。

さらに、その他の私が作成したボタンを紹介します。

prefbarのサブメニュー

以上の多くのボタンを並べると、ブラウザのウィンドウの幅に入り切らず使いにくいかと思われます。そういった場合は、prefbarで右クリックのカスタマイズの右クリックで、作成、サブメニューを選ぶと、いくつかのボタンをそのなかにまとめることができます。

スクリーショットの「メディア」がそのサブメニューです。そして、そのサブメニューと中身のアイテムをカスタマイズで選んだ上で右クリック、そしてエクスポートできます。

prefbarと文書の書体

稀に書体の種類を前提としつつも文書に書体指定がなく、意図が伝わり難い場合があります。典型例が、日本語環境IEを前提とした日本特有のアスキーアートです。日本では、プロポーショナルフォントでアスキーアートなどという思いもよらない特異な独自の文化が形成されており、フォントは日本語環境IEの規定値「MS Pゴシック 11pt」を想定しているようです。よって、環境が変わるとこのアスキーアートは作者の意図通りに表示されません。しかし、「IPAモナー、Textar、RobotoJAA、梅P」フォントのいずれかをインストールするとそれに近い閲覧環境が得られるようです(TextarとRobotaJAAはちょっと大きい気がしますが)。それをトグルボタンかメニューで一発で切り替えるprefbarのボタンや、その他フォント関連のボタンを用意してみました。

prefbarのサードパーティのボタン

prefbarのカスタマイズで「ボタンの追加」でサードパーティのボタンが追加できます。精査はしていませんが、ここで紹介したものと重なるものもあるようです。その他、いくつか有用なボタンを紹介します。

prefbarとショートカットキー

prefbarではボタンにショートカットキーを割り当てることができ、非常に便利です。以下の二つ目の機能に「ホットキー」と呼ばれるショートカットキーを割り当てました。

prefbarによるDOM操作

prefbarを用いるとJavascriptで簡単にDOM(Document Object Model)操作を行なうことができます。ここでは以下の問題提起とその解決策をprefbarボタンで実現する「ドキュメントURLツール・ボタンセット [2012/09/29]」を紹介します。

  1. link URLs … 文書にURLを書いておきながらリンクを貼っていないサイトを多く見かけます。おそらく、リファラからリンク元サイトを知られたくない等の事情があるのでしょうが、閲覧者にとってはリンクを辿るのが面倒です。このボタンを押すとリンクを貼られていないURLにリンクを貼ります。
  2. normalize URLs … リンクを貼っておきながらリダイレクトサイトに誘導されて、見たくもない広告を見せられてから、目的のサイトへリダイレクトするといったサイトがあります(具体的にはhttp://ime.nu/)。このボタンを押すと正しいURLにリンクを貼り直します。
  3. embed URLs … 画像のリンクのみで画像は埋め込まれていないサイトがありますが、いちいち一つずつ閲覧するのは面倒です。このボタンを押すとすべての画像のリンクを文書に埋め込みます。
  4. cachefy URLs … 稀にリンク切れになってしまっている文書があります。このボタンを押すとすべてのリンクがgoogleキャッシュに貼り直されます。
  5. archive URLs … 稀にリンク切れになってしまっている文書があります。このボタンを押すとすべてのリンクがarchive.orgに貼り直されます。

では具体的にどのように実現されているかいくつかを例に見てみましょう。

embed URLs の Get-Function

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へ代入

embed URLs の Set-Function

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の初期化

prefbarのカスタマイズで「初期化」というのがあります。これはボタンIDに従って既定の内容に戻すためのもので、ボタンの配置や別途作成した別のIDのボタンには影響がありません。新しいprefbarをインストールした際に最新の状態に追従したい時に便利です。また、追従したくないボタンについては、複製してIDを別のものにしたものにしておけば、独自のボタン設定が消されないで済みます。

おわりに

ブラウザの機能や設定の確認

昨今はブラウザも機能過多になり、枯れていない技術だと特にその脆弱性が狙われやすく、使っていない機能は是非とも無効にしておきたいものです。以下のサイトは、ブラウザの機能や設定を確認するために作成したものですのでどうぞ活用して下さい。

どのブラウザがいいのか?

もう一つの防衛策として、いくつかのブラウザを使い分ける、そのメリットを述べた文書をなるべく初心者向けに書きました。ブックマークレット作成入門も添えましたので、本稿を基礎から知りたいという方は是非。

Written by Taiji Yamada