Help us understand the problem. What is going on with this article?

DenoでGoogle Chromeでもブックマークニックネーム!

はじめに

Google Chrome でもブックマークニックネーム機能を使うために、検索エンジンを追加する拡張機能を Deno で自動作成し、それを読み込むことにしました。

Google Chrome とは

天下の Google 様がお作りになった Web ブラウザです。
残念ながら私にとって必要な機能が存在しないため使えません。
私も普段は使っていません。Firefox のほうがいいです。

Q. 必要な機能って何だよ
A. ↓

ブックマークニックネームとは

ブックマークに一意のニックネーム(キーワード)を与えることで、アドレスバー(オムニボックス)での補完をより使いやすくする機能です。

あらかじめブックマークに与えた一意の文字列をアドレスバーに入力すると、該当するブックマークが強制的に 1 位にサジェストされ、選択状態になります。
そして、そのまま Enter キーを押下することでそのブックマークが開かれます。

キーボード操作だけですぐにブックマークを開くことができるのです。
とても素晴らしい機能なのですが、なぜか天下のGoogle Chrome様にはありません。

Google Chrome でのその機能の再現方法

しかし、裏技的な感じにはなりますが再現は可能です。

カスタム検索エンジンとは

検索エンジンをカスタマイズする機能です。
検索エンジンの名前・検索エンジンを呼び出すキーワード・URLを設定画面で登録します。
通常はそのURLとして検索語句を%sに置換した文字列を指定するのですが、%sが含まれない文字列を指定した場合、ブックマークニックネームと同じような挙動をするようになります。

その自動化方法

しかし設定画面(chrome://settings/searchEngines)は恐ろしいほど使い勝手が悪いです。
腱鞘炎になります。

そこで…

拡張機能の作成

本題です。
検索エンジンを追加する拡張機能を作成し、それをWebブラウザに自動で読み込ませることで省力化を図ります。

拡張機能の仕様

細かな説明は省きますが、manifest.jsonにてchrome_settings_overridesキーを使えばsearch_providerを追加することが可能です。

しかし、拡張機能では一つしかmanifest.jsonを使えず、一つのmanifest.jsonでは一回しかchrome_settings_overridesできません。
よって、複数のブックマークを登録するためにはその分の拡張機能を作る必要があります。

拡張機能の自動作成

Denoを使いました。
src/main.tsが、src/bookmarks.tsという設定を記述したモジュールをインポートして生成します。

特に解説することがないのでGitHubを参照してください。


GitHub見に行くのが怠い人用
main.ts
#!/usr/bin/env deno run --allow-read --allow-write

// config /////////////////////////////////////////////////
const chromePath =
  '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"';

import { bookmarks } from './bookmarks.ts';

// init ///////////////////////////////////////////////////
const tmpDir = Deno.makeTempDirSync();
Deno.chdir(tmpDir);

const textEncoder = new TextEncoder();

const generateUUID = () => {
  const $ = (a: number, b: number) =>
    (Math.floor(Math.random() * a) + b).toString(16);

  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    .replace(/x/g, () => $(16, 0))
    .replace(/y/g, () => $(4, 8));
};

// main ///////////////////////////////////////////////////
const extensions = bookmarks
  .map(({ key, name, url }) => {
    const searchUrl = new URL(url.replace('%s', '{searchTerms}'));

    const faviconUrl = new URL('https://www.google.com/s2/favicons');
    faviconUrl.searchParams.set('domain', searchUrl.host);

    const manifest = {
      chrome_settings_overrides: {
        search_provider: {
          encoding: 'utf-8',
          favicon_url: faviconUrl.toString(),
          is_default: false,
          keyword: key,
          name,
          search_url: searchUrl.toString(),
        },
      },
      manifest_version: 2,
      name,
      version: '1.0.0',
    };

    return manifest;
  })
  .map((manifest) => {
    const uuid = generateUUID();

    Deno.mkdirSync(uuid);
    Deno.writeFileSync(
      `${uuid}/manifest.json`,
      textEncoder.encode(JSON.stringify(manifest)),
    );

    return uuid;
  })
  .map((uuid) => Deno.realPathSync(uuid));

console.log(chromePath + ' --load-extension=' + extensions.join(','));


拡張機能の自動読み込み

できません。
よってコマンドラインからの起動時に引数として指定します。

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --load-extension=path/to/extension-foo,path/to/extension-bar

みたいな感じです。

src/main.tsを実行すると起動用コマンドが標準出力(console.log)されるのでshにパイプして使っています。

おわりに

特に解説することがないので感想を。

Denoはいいぞ。
小難しいことなくTypeScript使えるのいいぞ。
ESModulesも標準でいい感じだしいいぞ。

okayurisotto
Webすき TypeScriptちょっとできる
https://twitter.com/@okayu_tar_gz
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした