Let’s search inside web pages

たいていのブラウザに組み込みのページ内検索機能があり、Chromeにもある。ただし、ブラウザがもっと小規模なアプリケーションだった頃からある機能のせいか微妙に素朴な動きしかしてくれない。例えば標準で正規表現が使えると嬉しいのだけど、できない。ページの密度が高くなってくると単に色でハイライトされたキーワードを見つけづらかったりするのも不便。検索ダイアログをEscapeでしか閉じられないのもめんどう。

そこで必要な機能を備えた拡張を作るかということになる。もちろん正規表現でページ検索できる拡張はすでにたくさんあるのだが…例えば現代だとそこかしこに絵文字が使われてるわけだが、最新の絵文字は複数のコードポイントから形成されてたりする。つまり検索を行う拡張側でも正確な書記素クラスタの認識ができないとハイライト処理などが盛大に壊れたりする可能性があり…実際いくつか試してみたところ盛大に壊れる。

また、正規表現によるページ内検索を実装する場合、要素を走査して要素ごとに検索を行う場合とそれ以外が考えられる。前者だと パンケーキとどら焼きって<b>ぶっちゃけ同じ</b>だよね のようなテキスト全体を検索することができない。既存の拡張は、全て試したわけではないが、だいたい半々くらいに分けられると思う。シンプルな実装の方が堅牢だし応答もよいだろうから明確に優劣があるわけではないのだが、まあできるのなら要素をまたいだ検索が可能な方がよい。

ついでに言うと migemo 検索ができると若干嬉しい。若干というのは、Chrome で migemo 検索というのは10年くらい前にはそういう拡張があったのだが、知らないうちに公開停止になっていて、しかもそれが特に話題にもなってないっぽくて、特に代替の拡張も登場しないまま10年経っているという現実が引っかかるからである。要するに非常にニッチにしか刺さらなくて、あんまり広い需要はないし売りにもならないのかもしれない。まあ個人的にはあれば嬉しい。

以上の要件を勘案すると、じゃあ新しいの作るかーということになる。

* * *

というわけで、作った

Installing Vimium

そういえばずっと以前にブラウザをvimっぽくする拡張の評価をいろいろして、最終的にcVimを選択したことがあった。それでずっとcVimを使っていたのだけど、メンテされなくなって随分経ち、いろいろと不具合が目立ってきたので別の何かに乗り換えることにした。

乗り換え先はタイトルの通りVimiumだ。VimiumはcVimに比べると

  • 内包している機能を直接呼び出すコマンドラインモードがない
  • 編集できる要素に対する拡張の余地がない

という明確なconsがあるが、それ以外はまあ何とかなる。軽いしよくできている。今までありがとうcVim…!

The death sentence from Google

以前書いたChromeの拡張の中にTabQueueというものがある。

これは主に3つの機能を備えていて:

  • タブをアクティブにした順番を覚えてくれる。あるタブを閉じた場合、その前にアクティブだったタブを再度アクティブにする。これはPresto Operaの同機能の移植である
  • タブを開いたとき、自動的にそれをフォアグランドにする
  • グローバルなホットキーをひとつ定義でき、それを押すとアクティブタブオーダーをポップできる。デフォルトではCtrl+,である。例えば右端のタブでyoutubeを開いて何かの動画を流しているがボリュームの調整だとか、何かちょっとした操作をしたいとする。そんな場合はg$で右端のタブに飛び(これはcVImの機能だが)、何か動画を操作し、Ctrl+,を押すと元のタブに戻れる。

というわけでかなりニッチな個人的ニーズを満たすものではあるがそれだけに欠かせないものであり毎日あたり前に使っている。

で。

先日Googleからメールが来て曰く、「TabQueueはウェブストアのポリシーに違反しています!説明に表記されている機能を提供していません!14日以内にアクションがない場合はウェブストアから削除される可能性があります!」…というのである。

何言ってんだおめえぶっころがすぞ…という感じである。何かよく分からないので無視している。ちなみにすでに14日以上経過している。

chrome.input.ime

ブラウザの中にはたくさんの文字入力可能なオブジェクトがありさまざまな種別の文字が入力される。一方で IME には入力モードというものがある。そのため時々入力したいものと入力されるもののミスマッチが起こる。

そんなわけで、その辺をブラウザと IME が密接にやりとりして調整してくれると嬉しい。しかし実際には、ブラウザから IME を制御することはほとんどできないし、HTML の規格を見るにむしろできないようにしている感すらある。

ところで、タイトルのような chrome extension の API がある。これは本来は ChromeOS のためのもので、IME の機能のうちプリエディットや変換候補リストといった UI 部分を担当する。つまり変換エンジン自体は自分で書かないといけないのだが、これを活用すればブラウザから制御できる IME ができるかもしれない。

で、すでにこの API を用いて作成された SKK というものがあって:
http://blog.jmuk.org/2012/07/chromeosskk.html
インストールしてみたものの、ChromeOS には存在するのであろう入力メソッド選択インターフェースが ChromeOS 以外の OS で動くブラウザにはないので、つまりこの SKK をアクティブにする手段がない。おのれ…おのれ…!

tab emphasis

アクティブでないタブがトラッカーによって更新された場合、文書のタイトルを点滅させるようにした。しかし単に点滅だと意外に目立たない。タブの背景色をいじれるといいんだけどな。あるいは音を出せばいいのかな?

数年前の赤福プラスは (Presto)Opera、Chrome、Firefox(Add-on SDK) で動いていた。これらのブラウザがサポートするエクステンションの API は微妙に、あるいはかなり異なっていたので、それらの差異を吸収する層が必要で、赤福プラスにおいてはそれは Kosian というライブラリだった。

さてそこから時が過ぎてブラウザのエクステンションは Chromium のそれで統一されてしまう勢いになったので、Kosian の存在意義が危うくなってしまった。なのでラッパの層を段階的に剥がしていきたい。同時に、個々のモジュールは ECMAScript Module で組み込むようにしたい。

ということで、そうした。文章で書くと簡潔だけどこれはなかなか大変でした。

become a historian

ふたばの画像掲示板で履歴機能が拡充されたので見てみる。

もともと、カタログの1モードとして過去にレスしたスレッドを集計する機能があり、それが履歴という扱いだった。内部的に考えれば、post したリモートホストが自分であるレスを含むスレッドを select するというサーバ側の SQL のクエリの話になる。

最近拡充されたのはそれとは別立てで、開いたスレッドの履歴を持っていてその一覧を表示するというものである。開いたスレッドの一覧データはどこにあるかと言うと、サーバ側ではなく、クライアントの cookie である。つまりカタログをサーバへリクエストする際にその cookie を投げると、サーバはそれに対応したスレッドの一覧を組み立てて返してくる。

これは良くない設計に思える。これに限らず、クライアント側はセッション ID だけを持たせてセッションにぶら下がるデータはサーバ側が持つほうが正道に思える箇所が色々あるのだが、長いことふたばはその方法を取らない。

それはそれとしてもう1つ不思議なのは、post した履歴と開いた履歴は分ける必要なくない? ということだ。常に post した履歴は開いた履歴の部分集合であるはずだ。これは誰でもそう思う疑問のはずで、まあまだ色々と作りかけなのかもしれない。

そういうわけなのでとりあえず見た履歴の機能をベースにして、post したスレッドを先頭に寄せるという加工を施すようにした。見た履歴を追加したり削除したりする機能はまだ作ってない。

背景色が付いている方が見たスレッド、かつ post したスレッド。そうではない方は見ただけのスレッド

introduce the passive tracking

スレッドの自動追尾というものを先日作った。これはユーザの指示によってスレッドのオートリロードをオンオフするものであり、かつスレッドの勢いに応じたリロード頻度を用いるので、いわばアクティブトラッキングと言える。作った際の感想としては例えば実況スレとかよりもむしろ寝落ちしてしまった際に有効かもしれない…というのは以前書いた。ただし寝落ちするくらいフニャフニャな状態だと、自動追尾を事前にオンにしていない場合がほとんどである。これをどうするか。

というわけで今回はそれと対になるパッシブトラッキングというものを作った。これはスレッドの消える時刻を算出した際、その消える時刻と現在の時刻との中間地点で1回タイマーを仕掛け、そこで続きを読むものだ。例えばスレッドの寿命が最低1時間保証されている板でスレッドを立てた場合、30分後に自動的に続きを読む。その次は15分後、その次は7分30秒後…という調子だ。スレッドの寿命が尽きるまで追いかける機能はそのままで、アクティブトラッキングに対して続きを読む頻度は相当抑えられる。

パッシブトラッキングは常に有効で、どのスレッドでも開いた時点から動作する。ただしアクティブトラッキングとの併存はできず、アクティブ側が優先される。

Link to anything #2

めったにないことではあるが、塩辛瓶やあぷ小のファイル名をコメントに含める際、拡張子を省略する人がいる。その場合の自動リンクはどうあるべきか。

その場合、赤福プラスはいずれのアップローダに対してもファイル名の補完を試みるようになっている。塩辛瓶の場合は、補完のための JSONP インターフェースが用意されているのでそれを使う。誰が作ってくれたのか知らないけど、ありがたいことです。

さて、あぷとあぷ小のサムネイルサービスの場合はと言うとこちらも似たようなインターフェースを用意してある。https://appsweets.net/thumbnail/up2/fu99999s.js などと呼び出すと、拡張子は js だが、そのファイルの情報が json で返ってくる。なぜ js かと言えばそれによって CloudFlare のキャッシュに乗るからである。ちなみに Access-Control-Allow-Origin: * としているので cors の制限は受けない。普通に xhr や fetch で読み出せばいい。

{
  "content": "data:image/png;base64,...",
  "board":"up2",
  "name":"fu25465.png",
  "base":"fu25465",
  "mime":"image/png",
  "size":9152,
  "comment":"",
  "dimensions":{
    "thumbnail":{
      "width":188,
      "height":250
    },
    "original":{
      "width":300,
      "height":400
    }
  }
}

こんな感じで返ってくる。content はサムネイル画像を data URI にエンコードしたものだ。

Link to anything

コメント中の自動リンク処理を整理し、100件弱くらいのテストケースを書き、それにパスするようにした。また、いくつかの既知のサイトに関して override scheme/preferred schemeの機構を設けた。前者はつまり、youtube とかは http://〜 と書かれていても https でリンクされる。逆に塩辛瓶は https://〜 と書いても http でリンクされる。後者はスキームが省略された時に選択されるデフォルトのスキームであり、ふたば内のリンクに https が適用される。

several thumbnails

-bash-4.2$ php70cli -r 'echo implode("\n",get_defined_functions()["internal"]);'| grep '^imagecreate'
imagecreatefromstring
imagecreate
imagecreatetruecolor
imagecreatefrompng
imagecreatefromwebp
imagecreatefromgif
imagecreatefromjpeg
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
imagecreatefromgd
imagecreatefromgd2
imagecreatefromgd2part
-bash-4.2$ php71cli -r 'echo implode("\n",get_defined_functions()["internal"]);'| grep '^imagecreate'
imagecreatefromstring
imagecreate
imagecreatetruecolor
imagecreatefrompng
imagecreatefromgif
imagecreatefromjpeg
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromgd
imagecreatefromgd2
imagecreatefromgd2part
-bash-4.2$ php72cli -r 'echo implode("\n",get_defined_functions()["internal"]);'| grep '^imagecreate'
imagecreatefromstring
imagecreate
imagecreatetruecolor
imagecreatefrompng
imagecreatefromgif
imagecreatefromjpeg
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromgd
imagecreatefromgd2
imagecreatefromgd2part
imagecreatefrombmp

ここのサーバであぷ/あぷ小のサムネイルを作っているが、jpg/gif/png に加えて webp にも対応した。これがなかなか面倒くさい。というのは現在このサーバの php のバージョンは 7.2 なのだがどういうわけかそれについてくる GD には webp を操作する機能が外されているからだ。

そういうわけで仕方がないのでごにょごにょっとして対応。