概要
Electronでアプリを作る際に、ブラウザにはデフォルトで備わっているページ内テキスト検索(Cmd+F / Ctrl+F)がどうなっているのかを調べた。結論としては、Electronにはテキスト検索のUIは付いてこないが、Chromiumの検索エンジン自体はAPIとして使える。ただ、Electron専用アプリを作るならカスタム実装の方が適しているだろうというところ。そのまとめ。
ElectronにはビルトインのFind in Page UIがない
一般的なブラウザにはFind in Page機能がデフォルトで搭載されている。Cmd+F(macOS)/ Ctrl+F(Windows/Linux)を押すと検索バーが出てきて、ページ内のテキストを検索できる。
Electronアプリにはこの検索UIが付いてこない。Chromiumベースではあるが、ブラウザのUIパーツ(検索バー、ブックマークバーなど)はElectronには含まれていない。ただし、Chromiumのテキスト検索エンジン自体はAPIとして公開されている。
webContents.findInPage() API
Electronは以下のAPIを提供している。
webContents.findInPage(text, options)— テキスト検索を実行webContents.stopFindInPage(action)— 検索を終了found-in-pageイベント — 検索結果を受け取る
found-in-pageイベントのresultオブジェクトにはresult.matchesで総マッチ数、result.activeMatchOrdinalで現在のマッチ位置が入っている。
これはChromiumのネイティブFind in Pageエンジンをラップしたもので、マッチ箇所のハイライト表示やスクロールも自動で行われる。ただし検索バーなどのUIは自分で作る必要がある。
<webview>タグやBrowserViewでも同じ.findInPage() APIが使える。
コードとしてはこういう感じになる。
// 検索を開始
webContents.findInPage("検索テキスト");
// 検索結果を受け取る
webContents.on("found-in-page", (event, result) => {
console.log(`${result.activeMatchOrdinal} / ${result.matches}`);
});
// 検索を終了(ハイライトをクリア)
webContents.stopFindInPage("clearSelection");ネイティブハイライトのCSS制御は不可
findInPage()によるハイライトはChromiumのコンポジターレベルで描画される。DOMの上にChromiumが直接オーバーレイを描いている形なので、CSSで直接スタイルを変更することはできない。
デフォルトのハイライト色は以下の通り。
- 全マッチ: 黄色背景
- アクティブマッチ: オレンジ背景
::highlight疑似要素やCSS Custom Highlight APIは存在するが、ElectronのfindInPageはそれらを使っていないため適用できない。findInPageのハイライトとCSS Custom Highlight APIは別の仕組み。
カスタム実装の方がElectronアプリ向き
Electron専用アプリを作る場合、ネイティブのfindInPage()よりも自前実装の方が適していると考えられる。
理由は以下。
- スタイルの完全制御 — アプリのデザインシステムに合わせたハイライト色やUIにできる
- カスタム動作 — 正規表現検索、大文字小文字の切り替え、特定パネル内のみの検索など、要件に応じた機能を追加できる
- 一貫したUX — ネイティブの
findInPageはブラウザっぽい見た目になり、専用アプリだと浮いてしまう
実装方法としてはmark.jsのようなライブラリが有力。mark.jsはマッチ箇所を<mark>タグで囲むため、CSSで自由にスタイリングできる。
import Mark from "mark.js";
const instance = new Mark(document.querySelector(".search-target"));
// マッチ箇所を<mark>タグで囲む
instance.mark("検索テキスト", {
className: "my-highlight",
});
// マッチを解除
instance.unmark();.my-highlight {
background-color: #ffd54f;
border-radius: 2px;
}ただし、カスタム実装だと以下の対応が必要になる。
- マッチ箇所へのスクロール
- 次/前のナビゲーション
- マッチ数のカウント表示
- 大きなドキュメントでのパフォーマンス
findInPage()はこれらをChromiumが全部やってくれるので、そこは楽。
まとめ
| 方法 | メリット | デメリット |
|---|---|---|
findInPage() API | 実装が簡単、パフォーマンス良好 | UIは自作必要、ハイライトのCSS変更不可 |
| カスタム実装(mark.js等) | スタイル自由、機能拡張可能 | 実装コスト高め、パフォーマンス管理必要 |
findInPage()はプロトタイピングや、ハイライトの見た目にこだわらない場合に手軽。Electron専用アプリとしてUIの一貫性を求めるならカスタム実装の方が良さそう。