LoginSignup
13
10

More than 5 years have passed since last update.

Draft.jsのデータ構造

Posted at

Draft.jsがリッチテキストを表現するために、どのようにメタデータを保持しているか実例を踏まえて解説します。(0.10時点)

Draft.jsを単純に使う分にはあまり意識する必要はありませんが、拡張して独自のstyleを表現したりするにはこの辺りを理解しておく必要があります。

データ構造

メタデータはconvertToRaw()というメソッドを使うことで取得することができます。

blocksというBlockのArrayと
entityMapというEntityのMapからできています。

    export type RawDraftContentState = {
      blocks: Array<RawDraftContentBlock>;
      entityMap: { [key: string]: RawDraftEntity };
    };

entityMapのkeyはEntityのidentifierとなります。

Block

Blockはコンテンツの一塊で、これらが集まったものが文章になるといったイメージです。HTMLでいうとパラグラフに近いです。

Blockは以下のような要素で構成されています。

    export type RawDraftContentBlock = {
      key: ?string;
      type: DraftBlockType;
      text: string;
      depth: ?number;
      inlineStyleRanges: ?Array<InlineStyleRange>;
      entityRanges: ?Array<EntityRange>;
      data?: Object;
    };
  • key
    • blockのidentifier
  • type
    • Blockの種類
    • デフォルトで用意されているtype
      • unstyled
      • paragraph
      • header-one, header-two, header-three, header-four, header-five, header-six
      • unordered-list-item
      • ordered-list-item
      • blockquote
      • code-block
      • atomic
    • 独自のタイプを加えることも可能
  • text
    • Block内に記述されたテキスト
  • depth
    • unordered-list-itemやordred-list-itemでインデントしたときに使われる深さ
  • inlineStyleRanges
    • boldなどといったinline styleをテキストのどこに反映するかといった情報を持ったArray
    • InlineStyleRange
      • InlineStyleRangeはstyleとoffsetとlengthを持ち、これらの情報からどの位置にどのstyleを反映するかわかります
  • entityRanges
    • Entityをテキストのどこに反映するかといった情報を持ったArray
    • EntityRange
      • EntityRangeはkeyとoffsetとlengthを持ち、これらの情報からどの位置にどのEntityを反映するかわかります。keyはEntityのidentifierにあたります。
  • data
    • blockにメタデータを持たせたいときに使います。

Entity

Entityはテキストを装飾するのにmeta dataを必要とする場合に用います。(inline styleのようにmeta dataが必要ない、つまりtypeだけわかればよい場合はinline styleを用います)

Entityは以下のような要素で構成されています。

    export type RawDraftEntity = {
      type: DraftEntityType;
      mutability: DraftEntityMutability;
      data: ?{ [key: string]: any };
    };
  • type
    • Entityの種類
  • mutability
    • Entityを適用するテキストが変更可能かどうかを示します
    • MUTABLE
    • IMMUTABLE
    • SEGMENTED
  • data
    • Entityを適用するのに必要なデータをMapで保持します。
    • 例えばLINKというtypeの場合だとLINKにはurlが必要なので
      • {url: "http://google.com"}といったデータにします。

実例

Block全体のスタイルを変える場合

引用やコードブロックなどのようにBlock全体のスタイルを変更する場合のデータ構造の使われ方です。

「引用です」という文字列でできたBlockを引用にしたときのデータ構造はこのようになります。

    {
        "entityMap": {},
        "blocks": [
            {
                "key": "1r71t",
                "text": "引用です",
                "type": "blockquote",
                "depth": 0,
                "inlineStyleRanges": [],
                "entityRanges": [],
                "data": {}
            }
        ]
    }

blockは「引用です」というtextを持ち、typeにblockquoteeを適用するというふうに設定されています。

Blockの中の文字列の一部のスタイルを変える場合

太字や斜体などBlockの中の文字列の一部のスタイルを変える場合のデータ構造の使われ方です。

「これが太字です」という文字列の中の太字という文字に太字を設定したときのデータ構造はこのようになります。

    {
        "entityMap": {},
        "blocks": [
            {
                "key": "4atgo",
                "text": "これが太字です",
                "type": "unstyled",
                "depth": 0,
                "inlineStyleRanges": [
                    {
                        "offset": 3,
                        "length": 2,
                        "style": "BOLD"
                    }
                ],
                "entityRanges": [],
                "data": {}
            }
        ]
    }

blockは「これが太字です」というtextを持ち、inlineStyleRangeで3文字目から2文字の範囲の文字にBOLDのstyleを適用するというふうに設定されています。

また、LINKの場合はstyleだけでなくurlといった別のメタデータも必要となるのでinline styleでは対応できません。

Blockの中の文字列の一部に特殊な装飾を加える場合

LINKなどBlockの中の文字列の一部のに特殊な装飾を加える場合のデータ構造の使われ方です。

「これがLINKです」という文字列の中のLINKという文字にlinkを設定したときのデータ構造はこのようになります。

    {
        "entityMap": {
            "0": {
                "type": "LINK",
                "mutability": "IMMUTABLE",
                "data": {
                    "url": "https://google.com"
                }
            }
        },
        "blocks": [
            {
                "key": "4atgo",
                "text": "これがLINKです",
                "type": "unstyled",
                "depth": 0,
                "inlineStyleRanges": [],
                "entityRanges": [
                    {
                        "offset": 3,
                        "length": 4,
                        "key": 0
                    }
                ],
                "data": {}
            }
        ]
    }

0というEntityにtypeがLINK、dataにlink先のurlが設定されています。

blockは「これがLINKです」というtextを持ち、enittyRangeで3文字目から4文字の範囲の文字をEntityの0を適用するというふうに設定されています。

Blockでテキスト以外にも情報を使って表現したい場合

文章の中に画像を入れたい場合に、Blockを画像にする場合にBlockに独自のtypeを追加してdataを用いるという方法があります。

    {
        "entityMap": {},
        "blocks": [
            {
                "key": "7va9s",
                "text": "",
                "type": "IMAGE",
                "depth": 0,
                "inlineStyleRanges": [],
                "entityRanges": [],
                "data": {
                    "src": "http://example.com/images/example1.jpg"
                }
            },
        ]
    }

typeにIMAGEという値を設定し、dataに画像ファイルのパスを設定しています。

これらのtypeやdataには任意の値を設定することができるので、どのようなBlockを表現したいかの用途によって決めるとよいです。これらの値を元にBlockの表示を行うCustom Blockを実装します。Custom Blockの実装方法は別の記事で説明したいと思います。

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10