Open7

Lexicalの仕様のなんとなくまとめ

siroyakasiroyaka

Lexicalはドキュメントとコードを読めばなんとなく動きがわかるようになっているのだけど、毎回調べ直すのは大変なのでなんとなく理解した挙動をここに整理しておく。

siroyakasiroyaka

RichTextPluginを適用したときの改行の処理について(2024/3/8)

コマンドを登録している処理

registerRichText
なんやかんや処理された結果INSERT_PARAGRAPH_COMMANDで登録されたコマンドが実行されるようになっている。

Selection.insertParagraphについて

この処理はSelectionのanchorがrootNodeにある場合にだけParagraphを作成する処理を実行する。
ほかのnodeにanchorがある場合にはそのnodeのinsertNewAfterを実行するようになっている。
このときにinsertNewAfterがnullを返せばnodeの追加も起こらない(NodeがParagraphをextendsしているとinsertNewAfterはnullを返せないので注意。)

siroyakasiroyaka

ElementNodeのcanBeEmptyについて(2024/3/8)

canBeEmptyはそのノードに子ノードが無くなった場合にノードを削除するための判定処理。
子ノードが必要な処理ではなく、すべての子ノードが削除されたときに自分が消えるためのもの。

siroyakasiroyaka

$applyNodeReplacementについて(2024/3/8)

この処理は$applyNodeReplacement(NodeA)となっている場合、nodeAをReplaceする設定がeditorに登録されている場合Replaceするという処理。Replaceしない場合はNodeAがそのままreturnされる。
replaceの設定はLexicalComposerを呼び出すところで渡すinitialConfigのnodesに記載する。

{
  replace: {replaceする元のNodeのType},
  with: (node) => return replace後のNodeを作成する処理
}

他にも登録する処理があるかもしれないけど調べていない。

自分で作ったNodeには入れなくてもいい気がする。

siroyakasiroyaka

拡張したTextNodeの結合とstyleの扱いについて

TextNodeのisSimpleTextが有効でかつformatの数値とstyleの文字列とmodeの文字列が同じであれば結合する仕組みが入っている。($canSimpleTextNodesBeMergedで同じと定義される。Node自体にisEqualみたいなのを持たせてやってくれればもう少し拡張性があったと思うのだが)

TextNodeを拡張して独自のプロパティを定義しそのプロパティも結合条件に入れたい場合に困る。Nodeがばらばらなままで問題なければisSimpleTextをfalseにすればいいが、そうでない場合はformat、style、modeのどれかを使ってプロパティの値を表現する必要がある。
3つの中で扱いやすいのはstyle。ただし、dom生成時(createDOM、importDOM)にTextNodeは__styleをdom.cssTextにそのまま適用するので、そこだけ考慮が必要。

siroyakasiroyaka

extractWithChildについて

TextNodeを子にもつ拡張したnode(公式のListItemNodeのような)を作成した場合、コピーをするときの挙動に関わるので設定することを推奨する。
コピーされるときに自分のnodeを含めるかを設定しているっぽい。
公式のListItemNodeは下記のような実装をしている

        if (!$isRangeSelection(selection)) {
            return false;
        }

        const anchorNode = selection.anchor.getNode();
        const focusNode = selection.focus.getNode();

        return (
            this.isParentOf(anchorNode) &&
            this.isParentOf(focusNode) &&
            this.getTextContent().length === selection.getTextContent().length
        );
siroyakasiroyaka

nodeの整形について

何かしらの入力のあとにその結果に基づいてnodeに変更を加える場合、editor.registerNodeTransformで実行するのがおそらく一番いい。
例えば一定の文字数で文字数制限をしたい場合などにTextNodeのsetTextContentやspliceTextの中で処理を実行することもできる。nodeを分割することで制限文字数を超えたものを表現するばあい、setTextContentやspliceTextで処理を実行すると日本語入力で確定前の文字が自動的に確定される。
registerNodeTransformは入力確定前には実行されないようなので、おそらくこれが一番いい。