コンテンツにスキップ

AI Session Notes - 2026-03-21

Chrome拡張: unpacked extensionにおけるchrome.storage.syncの制約

学んだこと

  • chrome.storage.sync はChrome Web Storeに公開された拡張機能でのみPC間同期が機能する
  • unpacked extension(デベロッパーモードで読み込んだ拡張)では、同じGoogleアカウントでログインしていてもデバイス間で同期されない
  • manifest.jsonkey を指定すれば拡張機能IDは固定できるが、それだけではsyncの問題は解決しない
  • unpacked extensionはPCごとにディレクトリパスから拡張機能IDが生成されるため、key 未指定だとそもそもIDが異なり chrome.storage.sync の対象にならない

詳細

unpacked extensionでデバイス間同期が必要な場合の代替手段:

  1. Chrome Web Store に Unlisted で公開chrome.storage.sync が使える(デベロッパー登録$5必要)
  2. 外部ストレージ(GitHub Gist等)を使った自前同期 — 実装コストが高い
  3. 各PCで個別管理 — 最もシンプル

Chrome Web Storeの公開範囲オプション

学んだこと

  • Chrome Web Storeには3つの公開範囲がある:
  • Public: 誰でも検索・インストール可能
  • Unlisted: URLを知っている人のみインストール可能。ストア検索には表示されない
  • Private: 指定したユーザー(Google Workspace等)のみインストール可能
  • 個人利用で「公開したくないが同期は使いたい」場合は Unlisted が適している
  • どの公開範囲でもGoogleの審査プロセスは必要

MutationObserverによるSPAのDOMフィルタリング

学んだこと

  • SPAではページ遷移なしにDOMが動的に変更されるため、MutationObserverchildListsubtree を監視することでリアルタイムにコンテンツをフィルタリングできる
  • X(Twitter)のツイート要素は article[data-testid="tweet"]、テキスト部分は div[data-testid="tweetText"] で取得可能
  • chrome.storage.onChanged リスナーと組み合わせることで、ポップアップでの設定変更を即座にコンテンツスクリプトに反映できる
  • 既存の表示済み要素の再スキャンと、新規追加要素の監視を両立させることで、設定変更時にも漏れなくフィルタリングを適用できる

MkDocs Material の検索と CJK 言語のセグメンテーション

学んだこと

  • MkDocs Material の検索プラグインにおいて、jieba パッケージは中国語専用のテキスト分割ライブラリである
  • 日本語と韓国語は クライアント側(ブラウザ)で分割処理されるため、jieba のインストールは不要
  • 公式ドキュメントに明記されている: "The plugin supports text segmentation of Chinese via jieba" / "Other languages like Japanese and Korean are currently segmented on the client side"
  • jieba は「中国語の形態素解析」が本来の用途であり、日本語の形態素解析には MeCab 等が適切だが、MkDocs Material の検索用途ではそもそもサーバー側の形態素解析自体が日本語には不要

詳細

MkDocs Material の検索は lunr.js ベースで、基本的にスペース区切りでトークンを生成する。CJK 言語はスペース区切りがないため特別な対応が必要だが、その対応方法が言語によって異なる:

言語 セグメンテーション方法 jieba 必要
中国語 サーバー側(jieba によるビルド時分割) Yes
日本語 クライアント側(ブラウザで分割) No
韓国語 クライアント側(ブラウザで分割) No

TinySegmenter: ブラウザで動く日本語トークナイザ

学んだこと

  • TinySegmenter は MeCab の開発者(工藤拓氏)が作った、JavaScript だけで動く軽量な日本語トークナイザ
  • 辞書不要で動作する。機械学習で訓練済みのモデルパラメータを JS コードに直接埋め込んでいるため、外部ファイルの読み込みが不要
  • サイズは約25KBと非常に小さく、ブラウザにバンドルしても負担にならない
  • 精度は MeCab より低いが、検索インデックスのトークン生成のように「だいたい分割できればよい」用途には十分

MeCab との比較

TinySegmenter MeCab
動作環境 ブラウザ(JavaScript) サーバー側(C++)
辞書 不要(モデル埋め込み) 必要(IPAdic 等、数十MB)
サイズ 約25KB 辞書込みで数十〜数百MB
精度 低め(検索用途には十分) 高い(品詞・活用まで解析可能)
用途 ブラウザ内検索、軽量な分かち書き 本格的な形態素解析、NLP

MkDocs Material での使われ方

MkDocs Material は lunr.js の検索エンジンに TinySegmenter を組み込んでいる。関連するソースコードの構造:

ファイル 役割
material/templates/assets/javascripts/lunr/tinyseg.js TinySegmenter 本体
src/templates/assets/javascripts/integrations/search/_/index.ts lunr.segmenter に TinySegmenter インスタンスをセット
src/templates/assets/javascripts/integrations/search/internal/tokenize/index.ts 実際のトークン化処理(lunr.segmenter.segment() の呼び出し)
src/templates/assets/javascripts/integrations/search/worker/main/index.ts Worker 内での segmenter 追加

中国語が jieba(辞書数MB)をビルド時に使うのに対し、日本語は TinySegmenter が軽量・辞書不要なのでブラウザで十分動く、という棲み分けになっている。

gh search code で OSS の内部実装を追う方法

学んだこと

  • 公式ドキュメントに具体的な技術名が書かれていない場合でも、gh search code でリポジトリのソースコードを横断検索すれば実装の詳細を特定できる
  • 検索キーワードは抽象度を変えて複数回試すと効果的(例: "Segmenter""segment"
  • 検索結果のファイルパスとコードスニペットを突き合わせることで、初期化・実行・定義がどこに分散しているか構造的に把握できる

詳細: MkDocs Material の日本語セグメンテーションを調査した具体例

疑問: MkDocs Material は日本語の検索をブラウザ側で処理すると書いてあるが、具体的に何を使っているのか?

ステップ 1: ドキュメントを確認 → 具体的な技術名がない

公式ドキュメント(search plugin の Segmentation セクション)には以下しか書かれていなかった:

"Other languages like Japanese and Korean are currently segmented on the client side"

ステップ 2: gh search code でソースを検索

gh search code "Segmenter" --repo squidfunk/mkdocs-material
gh search code "segment" --repo squidfunk/mkdocs-material

これにより TinySegmenter というキーワードが複数ファイルにヒットした。

ステップ 3: ヒットしたファイルから役割を整理

ファイルパスからモジュール構造がわかり、スニペットから具体的な処理がわかる。両方を突き合わせて全体像を掴む:

  • tinyseg.js → 本体がバンドルされている
  • _/index.ts → 初期化コード
  • tokenize/index.ts → 実際の segment() 呼び出し
  • CHANGELOG"Fixed #3112: Japanese segmenter not executed" で日本語向けであることの裏付け

ステップ 4: 結論をまとめる

ドキュメントの「client side」の正体は TinySegmenter だった。ソース検索 → ファイル構造の把握 → CHANGELOG での裏付けという流れで、ドキュメントに書かれていない実装詳細を特定できた。

汎用的なポイント

  • ドキュメントで曖昧なときはソースを読む: gh search code は clone しなくても GitHub リポジトリを横断検索できる
  • キーワードは段階的に広げる: ピンポイントのキーワードで探し、ヒットしなければ抽象度を上げる
  • CHANGELOG も根拠になる: Issue 番号やバグ修正の記述から、機能の存在や対象言語を裏付けられる
  • ソースファイルのヘッダで裏取りする: 今回 TinySegmenter の作者が工藤拓氏であることは事前知識から述べたが、実際に tinyseg.js のファイルヘッダには (c) 2008 Taku Kudo <taku@chasen.org> と明記されていた。「知っている」ことと「根拠がある」ことは別なので、ソースコードのライセンスヘッダ・著作権表記・コメントを一次情報として確認する癖をつけるべき

参考リンク

メタ情報

  • ツール: Claude Code
  • 関連技術: Chrome Extension (Manifest V3), JavaScript, MutationObserver, chrome.storage API, MkDocs Material, lunr.js, jieba, TinySegmenter, gh CLI