Diffine
テキストと画像の差分を求めるエンジンと、左右に並べて見せるビューアーをひとつにしたもので、React ライブラリと Flutter パッケージとして提供されます。二つの版を行単位で対応づけたうえで、変わった行の中では語単位まで拾い、二枚の画像はピクセル単位で比べ、左右を同じ高さに保って描くので、比較も位置合わせもアプリケーション側で作る必要がありません。
このプロジェクトについて
Diffine は、二つの版のあいだで何が変わったかを求めて画面に載せます。対象はテキストと画像で、React でも Flutter でも使えます。比較と表示が別々にあるのではなくひとつのライブラリで、両者が出会う場所は値です。diffText は行と変更箇所と件数を返し、diffImage はマスク、変わった領域を表す矩形、件数を返します。どちらの中にもコンポーネントもウィジェットもありません。ビューアーはその値を使う一つの消費者であって、値にたどり着く唯一の道ではないので、同じ比較結果を端末に出力することも、ワーカーで動かすことも、ビルドの中でしきい値と照らし合わせることもできます。unified 形式のパッチも比較結果の一つです。parsePatch はパッチを読み込んで同じ値にし、formatPatch はその値をパッチとして書き出します。
テキストの対応づけは一度の走査で二つの段階に分かれます。まず行どうしを組にし、丸ごと置き換わったのではなく直された組の中では、実際に動いた語や文字をもう一度拾います。ビューアーはそれを、同じ高さに保った二つの面に描き、あいだの隙間を線でつなぎます。行番号、折り返し、高さの揃え、つなぎの線、ひとつにまとめた表示、誰も手を入れていない行の折りたたみ——表示を作るものはどれも既定値を持つ設定です。エディターモードでは左右の面それぞれに入力欄が重なり、キーを打つたびに比較をやり直します。画像は横に並べる、半透明で重ねる、境目を動かして切り替える、マスクだけを見る、のいずれかで比べられます。許容差を設けることも、レンダラーが加えたスムージングを無視することも、位置の揃っていない二枚の画像からずれを見つけることもできます。diffImages は三枚以上を一度に比べ、imageSimilarity は一つの数値で答えます。マウスがなくても読めます。左右の面は焦点を受け取る領域であり、変更点を一つずつたどるボタンには名前がついていて、何が変わったかは変わるたびに読み上げられます。
導入は、Web ではパッケージ一つと CSS 一行、Flutter では import 一つです。どちらのパッケージも依存は一つだけです。React 側はシンタックスハイライトのために highlight.js を加えますが、言語ごとの文法定義は動的インポートで一つずつ読み込むので、プレーンテキストの比較では何もダウンロードしません。Flutter 側が加えるのは characters で、これは Flutter にもともと同梱されています。react と react-dom はピア依存なので、アプリケーションがすでに持っているものがそのまま使われます。二つのパッケージはエンジンを共有し、パレットも色の値まで同じで、暗い配色は端末の設定に従います。React のパッケージは ESM で TypeScript の型定義つき、ルートはエンジンだけで、ビューアーは diffine-react/text-diff と diffine-react/image-diff に分かれているので、比較結果だけが欲しいアプリケーションがビューアーまで引き連れてくることはありません。
機能
ドキュメントサイトあり
TypeScript 型定義
多言語対応
テストで検証済み
クロスプラットフォーム対応
アクセシビリティ対応
ダークモード
ツリーシェイキング対応
