WYSIWYGエディタのドキュメントモデル

WYSIWYGエディタにおいてドキュメントをどう内部表現するかの設計。この選択がエディタのアーキテクチャ全体を規定する最重要の決定となる。

3つのアプローチ

HTML直接(レガシー)

contenteditableexecCommand 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つの構造要素:

操作ログ(協調編集向け)

{ type: "insert", pos: 5, text: "こんにちは" }
{ type: "delete", pos: 10, length: 3 }

状態ではなく「操作」を記録する。CRDTやOT(Operational Transformation)と組み合わせてリアルタイム協調編集に対応する。

アーキテクチャへの影響

データモデルの選択
    ↓
実装の複雑さ・機能性が決まる

どのデータモデルを選ぶかは「どのライブラリを使うか」以前の、アーキテクチャ上の根本的な決定である。後から変更することは非常に困難。

スキーマによる構造の制約

ProseMirrorのような厳格なスキーマを持つライブラリでは、ドキュメントに含められるノードの種類と階層構造をあらかじめ定義する。「スキーマに定義されていないものは入らない」という制約がバグ防止になり、不正なHTMLがペーストされても正規化される。

関連