概要
Sublime Text のようなエディタが減少している現状に着目し、自作テキストエディタ開発の試行錯誤を記録。 canvas ・ contenteditable ・ textarea の各アプローチのメリット・課題を比較。 アクセシビリティやパフォーマンス、機能実装の難しさを具体的に解説。 ブラウザAPI 活用やハイライト処理の工夫も紹介。 最終的な課題と今後の展望についての所感。
ソフトウェアの現状とテキストエディタ自作動機
- Sublime Text のような高品質エディタが減少している現状への共感
- 現代のソフトウェアは 品質低下 が目立つという問題意識
- 自分でも 独自のテキストエディタ を作れるのではという発想
- VS Code はMonaco Editorベースで、要素の複雑さ(<div>の多用)に課題
- Apple silicon への移行でパフォーマンスの問題が解消されたことが契機
canvasによる実装実験
- canvas要素 で全描画を行う初期実験
- CPU負荷 が高く、60〜120fpsでレンダリングされる仕組み
- インタラクティブ性の欠如 が明らかな課題
- 最小限の機能(カーソル移動、入力、行ハイライトなど)を実装
- テキスト選択・Undo/Redo・複数行ペースト・スクロール など多くの機能が未実装
- スクロールは hidden要素のoverflow を活用して実現
- canvasのアクセシビリティ問題 が根本的な課題
contenteditableの採用とその評価
- canvas の代替案として、 contenteditable属性 を持つ<div>の利用を検討
- plaintext-only でコード編集に最適化
- spellcheck 等を無効化して入力遅延を防止
- ブラウザのネイティブ機能 (選択・Undo履歴・アクセシビリティ)を活用
- Selection API や ::selection でカスタムカーソルや選択範囲の装飾が可能
- ただし、 大量テキストでのパフォーマンス低下 が見られる
- Chromium系 で特に遅延が発生しやすい
textareaの利用とハイライト処理
- textarea は大量テキストでも高パフォーマンスを維持
- contenteditable よりも長文編集に向く
- シンタックスハイライト は追加レイヤー(<div>)で実現
- CSSハイライト の多用はパフォーマンスの新たな課題
- Tree-sitter で構文木を生成し、表示行のみハイライトする案
- 仮想スクロール や 逆sticky手法 で最適化を検討
- OpaqueRange API や EditContext API など新APIで機能拡張が可能
実装の限界と今後の展望
- 現状は 90%の見た目で1%の機能 しかない状態
- 細かい機能(タブインデント等)の実装は手間が大きい
- アクセシビリティ や 最適化 は今後の課題
- canvas ベースは最初から不利な選択肢であったと総括
- プロジェクトは一旦保留し、将来の課題として保存
JavaScriptにおけるテキスト処理の注意点
-
JavaScriptの文字列・範囲操作 はUTF-16コードユニット単位
-
絵文字 等でバグを起こしやすい
-
サンプルコードによる 文字数カウントの違い の例示
- "🍋🟩".length; // 5
- [..."🍋🟩"].length; // 3
- const segmenter = new Intl.Segmenter("en", {granularity: "grapheme"}); [...segmenter.segment("🍋🟩")].length; // 1
-
Intl.Segmenter で正確なグラフェム単位のカウントが可能
まとめ
- canvas は表現力が高いがアクセシビリティと実装コストが大きい
- contenteditable は手軽だが大量テキストで不安定
- textarea はパフォーマンスに優れるが装飾に制約
- APIや構文解析 を使い分けて最適解を模索する必要
- テキストエディタ開発は 奥が深く、地道な改善 が不可欠