WYSIWYGエディタのドキュメントモデル
WYSIWYGエディタにおいてドキュメントをどう内部表現するかの設計。この選択がエディタのアーキテクチャ全体を規定する最重要の決定となる。
3つのアプローチ
HTML直接(レガシー)
contenteditableとexecCommand APIを使い、ブラウザのDOM操作に依存する方式。実装は簡単だが、ブラウザごとに出力が異なり、複雑な構造で壊れやすい。Undo/Redoも不安定。
独自AST(現代の主流)
{
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "通常テキスト" },
{ "type": "text", "text": "太字", "marks": [{ "type": "bold" }] }
]
}
]
}
ドキュメントを独自のツリー構造(AST)として保持し、そこからDOMをレンダリングする。仮想DOM的な「状態からUIを導出する」思想を応用。ProseMirror、Slate、Lexicalが採用。
3つの構造要素:
- ノード階層 -
doc > paragraph > textのようなツリー - マーク - bold, italicなどテキストに付与される装飾
- 属性(attrs) - ノード固有の設定値
操作ログ(協調編集向け)
{ type: "insert", pos: 5, text: "こんにちは" }
{ type: "delete", pos: 10, length: 3 }
状態ではなく「操作」を記録する。CRDTやOT(Operational Transformation)と組み合わせてリアルタイム協調編集に対応する。
アーキテクチャへの影響
データモデルの選択
↓
実装の複雑さ・機能性が決まる
どのデータモデルを選ぶかは「どのライブラリを使うか」以前の、アーキテクチャ上の根本的な決定である。後から変更することは非常に困難。
スキーマによる構造の制約
ProseMirrorのような厳格なスキーマを持つライブラリでは、ドキュメントに含められるノードの種類と階層構造をあらかじめ定義する。「スキーマに定義されていないものは入らない」という制約がバグ防止になり、不正なHTMLがペーストされても正規化される。
関連
- WYSIWYGエディタの設計と実装 - 実装全体の解説
- 仮想DOM - 独自ASTアプローチに影響を与えた思想
- CRDT - 操作ログアプローチと組み合わせる協調編集の仕組み
- Yjs - CRDTベースの協調編集ライブラリ