2 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
9 import type {LexicalNode, SerializedLexicalNode} from '../LexicalNode';
10 import type {SerializedElementNode} from './LexicalElementNode';
12 import invariant from 'lexical/shared/invariant';
14 import {NO_DIRTY_NODES} from '../LexicalConstants';
15 import {getActiveEditor, isCurrentlyReadOnlyMode} from '../LexicalUpdates';
16 import {$getRoot} from '../LexicalUtils';
17 import {$isDecoratorNode} from './LexicalDecoratorNode';
18 import {$isElementNode, ElementNode} from './LexicalElementNode';
20 export type SerializedRootNode<
21 T extends SerializedLexicalNode = SerializedLexicalNode,
22 > = SerializedElementNode<T>;
25 export class RootNode extends ElementNode {
27 __cachedText: null | string;
29 static getType(): string {
33 static clone(): RootNode {
34 return new RootNode();
39 this.__cachedText = null;
42 getTopLevelElementOrThrow(): never {
45 'getTopLevelElementOrThrow: root nodes are not top level elements',
49 getTextContent(): string {
50 const cachedText = this.__cachedText;
52 isCurrentlyReadOnlyMode() ||
53 getActiveEditor()._dirtyType === NO_DIRTY_NODES
55 if (cachedText !== null) {
59 return super.getTextContent();
63 invariant(false, 'remove: cannot be called on root nodes');
66 replace<N = LexicalNode>(node: N): never {
67 invariant(false, 'replace: cannot be called on root nodes');
70 insertBefore(nodeToInsert: LexicalNode): LexicalNode {
71 invariant(false, 'insertBefore: cannot be called on root nodes');
74 insertAfter(nodeToInsert: LexicalNode): LexicalNode {
75 invariant(false, 'insertAfter: cannot be called on root nodes');
80 updateDOM(prevNode: RootNode, dom: HTMLElement): false {
86 append(...nodesToAppend: LexicalNode[]): this {
87 for (let i = 0; i < nodesToAppend.length; i++) {
88 const node = nodesToAppend[i];
89 if (!$isElementNode(node) && !$isDecoratorNode(node)) {
92 'rootNode.append: Only element or decorator nodes can be appended to the root node',
96 return super.append(...nodesToAppend);
99 static importJSON(serializedNode: SerializedRootNode): RootNode {
100 // We don't create a root, and instead use the existing root.
101 const node = $getRoot();
102 node.setFormat(serializedNode.format);
103 node.setIndent(serializedNode.indent);
104 node.setDirection(serializedNode.direction);
108 exportJSON(): SerializedRootNode {
111 direction: this.getDirection(),
112 format: this.getFormatType(),
113 indent: this.getIndent(),
119 collapseAtStart(): true {
124 export function $createRootNode(): RootNode {
125 return new RootNode();
128 export function $isRootNode(
129 node: RootNode | LexicalNode | null | undefined,
130 ): node is RootNode {
131 return node instanceof RootNode;