@lobehub/editor 3.3.2 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/es/editor-kernel/index.d.ts +1 -0
  2. package/es/editor-kernel/index.js +3 -1
  3. package/es/editor-kernel/kernel.js +1 -0
  4. package/es/editor-kernel/lexical/Lexical.dev.js +3052 -0
  5. package/es/editor-kernel/lexical/Lexical.dev.mjs +15365 -0
  6. package/es/editor-kernel/lexical/Lexical.js +7634 -0
  7. package/es/editor-kernel/lexical/Lexical.mjs +7258 -0
  8. package/es/editor-kernel/lexical/LexicalCommands.d.ts +175 -0
  9. package/es/editor-kernel/lexical/LexicalConstants.d.ts +54 -0
  10. package/es/editor-kernel/lexical/LexicalEditor.d.ts +672 -0
  11. package/es/editor-kernel/lexical/LexicalEditorState.d.ts +39 -0
  12. package/es/editor-kernel/lexical/LexicalEvents.d.ts +22 -0
  13. package/es/editor-kernel/lexical/LexicalGC.d.ts +23 -0
  14. package/es/editor-kernel/lexical/LexicalMutations.d.ts +12 -0
  15. package/es/editor-kernel/lexical/LexicalNode.d.ts +689 -0
  16. package/es/editor-kernel/lexical/LexicalNodeState.d.ts +569 -0
  17. package/es/editor-kernel/lexical/LexicalNormalization.d.ts +11 -0
  18. package/es/editor-kernel/lexical/LexicalReconciler.d.ts +28 -0
  19. package/es/editor-kernel/lexical/LexicalSelection.d.ts +368 -0
  20. package/es/editor-kernel/lexical/LexicalUpdateTags.d.ts +67 -0
  21. package/es/editor-kernel/lexical/LexicalUpdates.d.ts +72 -0
  22. package/es/editor-kernel/lexical/LexicalUtils.d.ts +492 -0
  23. package/es/editor-kernel/lexical/caret/LexicalCaret.d.ts +635 -0
  24. package/es/editor-kernel/lexical/caret/LexicalCaretUtils.d.ts +224 -0
  25. package/es/editor-kernel/lexical/extension-core/defineExtension.d.ts +126 -0
  26. package/es/editor-kernel/lexical/extension-core/index.d.ts +38 -0
  27. package/es/editor-kernel/lexical/extension-core/internal.d.ts +32 -0
  28. package/es/editor-kernel/lexical/extension-core/safeCast.d.ts +15 -0
  29. package/es/editor-kernel/lexical/extension-core/shallowMergeConfig.d.ts +20 -0
  30. package/es/editor-kernel/lexical/extension-core/types.d.ts +371 -0
  31. package/es/editor-kernel/lexical/index.d.ts +368 -0
  32. package/es/editor-kernel/lexical/nodes/ArtificialNode.d.ts +16 -0
  33. package/es/editor-kernel/lexical/nodes/LexicalDecoratorNode.d.ts +32 -0
  34. package/es/editor-kernel/lexical/nodes/LexicalElementNode.d.ts +235 -0
  35. package/es/editor-kernel/lexical/nodes/LexicalLineBreakNode.d.ts +30 -0
  36. package/es/editor-kernel/lexical/nodes/LexicalParagraphNode.d.ts +39 -0
  37. package/es/editor-kernel/lexical/nodes/LexicalRootNode.d.ts +35 -0
  38. package/es/editor-kernel/lexical/nodes/LexicalTabNode.d.ts +30 -0
  39. package/es/editor-kernel/lexical/nodes/LexicalTextNode.d.ts +311 -0
  40. package/es/plugins/common/data-source/json-data-source.js +29 -3
  41. package/es/plugins/common/react/ReactPlainText.js +9 -0
  42. package/es/plugins/common/utils/index.d.ts +2 -1
  43. package/es/plugins/common/utils/index.js +33 -0
  44. package/es/plugins/litexml/command/index.js +9 -1
  45. package/es/plugins/litexml/data-source/litexml-data-source.js +12 -2
  46. package/es/plugins/litexml/plugin/index.js +41 -3
  47. package/es/plugins/litexml/utils/index.d.ts +2 -1
  48. package/es/plugins/litexml/utils/index.js +7 -1
  49. package/es/plugins/markdown/data-source/markdown-data-source.js +6 -25
  50. package/es/plugins/markdown/data-source/markdown-writer-context.d.ts +5 -1
  51. package/es/plugins/markdown/data-source/markdown-writer-context.js +27 -2
  52. package/es/plugins/markdown/service/shortcut.d.ts +7 -0
  53. package/es/types/kernel.d.ts +4 -0
  54. package/package.json +8 -2
  55. package/scripts/patch-lexical.js +39 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { EditorConfig, KlassConstructor, LexicalEditor, Spread } from '../LexicalEditor';
9
+ import type { DOMConversionMap, DOMExportOutput, LexicalNode } from '../LexicalNode';
10
+ import type { RangeSelection } from '../LexicalSelection';
11
+ import type { SerializedElementNode } from './LexicalElementNode';
12
+ import { ElementNode } from './LexicalElementNode';
13
+
14
+ export type SerializedParagraphNode = Spread<
15
+ {
16
+ textFormat: number;
17
+ textStyle: string;
18
+ },
19
+ SerializedElementNode
20
+ >;
21
+ /** @noInheritDoc */
22
+ export declare class ParagraphNode extends ElementNode {
23
+ /** @internal */
24
+ ['constructor']: KlassConstructor<typeof ParagraphNode>;
25
+ static getType(): string;
26
+ static clone(node: ParagraphNode): ParagraphNode;
27
+ createDOM(config: EditorConfig): HTMLElement;
28
+ updateDOM(prevNode: ParagraphNode, dom: HTMLElement, config: EditorConfig): boolean;
29
+ static importDOM(): DOMConversionMap | null;
30
+ exportDOM(editor: LexicalEditor): DOMExportOutput;
31
+ static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode;
32
+ exportJSON(): SerializedParagraphNode;
33
+ insertNewAfter(rangeSelection: RangeSelection, restoreSelection: boolean): ParagraphNode;
34
+ collapseAtStart(): boolean;
35
+ }
36
+ export declare function $createParagraphNode(): ParagraphNode;
37
+ export declare function $isParagraphNode(
38
+ node: LexicalNode | null | undefined,
39
+ ): node is ParagraphNode;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { LexicalNode, SerializedLexicalNode } from '../LexicalNode';
9
+ import type { SerializedElementNode } from './LexicalElementNode';
10
+ import { ElementNode } from './LexicalElementNode';
11
+
12
+ export type SerializedRootNode<T extends SerializedLexicalNode = SerializedLexicalNode> =
13
+ SerializedElementNode<T>;
14
+ /** @noInheritDoc */
15
+ export declare class RootNode extends ElementNode {
16
+ /** @internal */
17
+ __cachedText: null | string;
18
+ static getType(): string;
19
+ static clone(): RootNode;
20
+ constructor();
21
+ getTopLevelElementOrThrow(): never;
22
+ getTextContent(): string;
23
+ remove(): never;
24
+ replace<N = LexicalNode>(node: N): never;
25
+ insertBefore(nodeToInsert: LexicalNode): LexicalNode;
26
+ insertAfter(nodeToInsert: LexicalNode): LexicalNode;
27
+ updateDOM(prevNode: this, dom: HTMLElement): false;
28
+ splice(start: number, deleteCount: number, nodesToInsert: LexicalNode[]): this;
29
+ static importJSON(serializedNode: SerializedRootNode): RootNode;
30
+ collapseAtStart(): true;
31
+ }
32
+ export declare function $createRootNode(): RootNode;
33
+ export declare function $isRootNode(
34
+ node: RootNode | LexicalNode | null | undefined,
35
+ ): node is RootNode;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import { EditorConfig } from '../LexicalEditor';
9
+ import type { DOMConversionMap, NodeKey } from '../LexicalNode';
10
+ import { LexicalNode } from '../LexicalNode';
11
+ import { SerializedTextNode, TextDetailType, TextModeType, TextNode } from './LexicalTextNode';
12
+
13
+ export type SerializedTabNode = SerializedTextNode;
14
+ /** @noInheritDoc */
15
+ export declare class TabNode extends TextNode {
16
+ static getType(): string;
17
+ static clone(node: TabNode): TabNode;
18
+ constructor(key?: NodeKey);
19
+ static importDOM(): DOMConversionMap | null;
20
+ createDOM(config: EditorConfig): HTMLElement;
21
+ static importJSON(serializedTabNode: SerializedTabNode): TabNode;
22
+ setTextContent(text: string): this;
23
+ spliceText(offset: number, delCount: number, newText: string, moveSelection?: boolean): TextNode;
24
+ setDetail(detail: TextDetailType | number): this;
25
+ setMode(type: TextModeType): this;
26
+ canInsertTextBefore(): boolean;
27
+ canInsertTextAfter(): boolean;
28
+ }
29
+ export declare function $createTabNode(): TabNode;
30
+ export declare function $isTabNode(node: LexicalNode | null | undefined): node is TabNode;
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type { EditorConfig, KlassConstructor, LexicalEditor, Spread } from '../LexicalEditor';
9
+ import type {
10
+ DOMConversionMap,
11
+ DOMExportOutput,
12
+ LexicalUpdateJSON,
13
+ NodeKey,
14
+ SerializedLexicalNode,
15
+ } from '../LexicalNode';
16
+ import { LexicalNode } from '../LexicalNode';
17
+ import type { BaseSelection, RangeSelection } from '../LexicalSelection';
18
+ import type { ElementNode } from './LexicalElementNode';
19
+
20
+ export type SerializedTextNode = Spread<
21
+ {
22
+ detail: number;
23
+ format: number;
24
+ mode: TextModeType;
25
+ style: string;
26
+ text: string;
27
+ },
28
+ SerializedLexicalNode
29
+ >;
30
+ export type TextDetailType = 'directionless' | 'unmergable';
31
+ export type TextFormatType =
32
+ | 'bold'
33
+ | 'underline'
34
+ | 'strikethrough'
35
+ | 'italic'
36
+ | 'highlight'
37
+ | 'code'
38
+ | 'subscript'
39
+ | 'superscript'
40
+ | 'lowercase'
41
+ | 'uppercase'
42
+ | 'capitalize';
43
+ export type TextModeType = 'normal' | 'token' | 'segmented';
44
+ export type TextMark = {
45
+ end: null | number;
46
+ id: string;
47
+ start: null | number;
48
+ };
49
+ export type TextMarks = Array<TextMark>;
50
+ export interface TextNode {
51
+ getTopLevelElement(): ElementNode | null;
52
+ getTopLevelElementOrThrow(): ElementNode;
53
+ }
54
+ /** @noInheritDoc */
55
+ export declare class TextNode extends LexicalNode {
56
+ /** @internal */
57
+ ['constructor']: KlassConstructor<typeof TextNode>;
58
+ __text: string;
59
+ /** @internal */
60
+ __format: number;
61
+ /** @internal */
62
+ __style: string;
63
+ /** @internal */
64
+ __mode: 0 | 1 | 2 | 3;
65
+ /** @internal */
66
+ __detail: number;
67
+ static getType(): string;
68
+ static clone(node: TextNode): TextNode;
69
+ afterCloneFrom(prevNode: this): void;
70
+ constructor(text?: string, key?: NodeKey);
71
+ /**
72
+ * Returns a 32-bit integer that represents the TextFormatTypes currently applied to the
73
+ * TextNode. You probably don't want to use this method directly - consider using TextNode.hasFormat instead.
74
+ *
75
+ * @returns a number representing the format of the text node.
76
+ */
77
+ getFormat(): number;
78
+ /**
79
+ * Returns a 32-bit integer that represents the TextDetailTypes currently applied to the
80
+ * TextNode. You probably don't want to use this method directly - consider using TextNode.isDirectionless
81
+ * or TextNode.isUnmergeable instead.
82
+ *
83
+ * @returns a number representing the detail of the text node.
84
+ */
85
+ getDetail(): number;
86
+ /**
87
+ * Returns the mode (TextModeType) of the TextNode, which may be "normal", "token", or "segmented"
88
+ *
89
+ * @returns TextModeType.
90
+ */
91
+ getMode(): TextModeType;
92
+ /**
93
+ * Returns the styles currently applied to the node. This is analogous to CSSText in the DOM.
94
+ *
95
+ * @returns CSSText-like string of styles applied to the underlying DOM node.
96
+ */
97
+ getStyle(): string;
98
+ /**
99
+ * Returns whether or not the node is in "token" mode. TextNodes in token mode can be navigated through character-by-character
100
+ * with a RangeSelection, but are deleted as a single entity (not individually by character).
101
+ *
102
+ * @returns true if the node is in token mode, false otherwise.
103
+ */
104
+ isToken(): boolean;
105
+ /**
106
+ *
107
+ * @returns true if Lexical detects that an IME or other 3rd-party script is attempting to
108
+ * mutate the TextNode, false otherwise.
109
+ */
110
+ isComposing(): boolean;
111
+ /**
112
+ * Returns whether or not the node is in "segmented" mode. TextNodes in segmented mode can be navigated through character-by-character
113
+ * with a RangeSelection, but are deleted in space-delimited "segments".
114
+ *
115
+ * @returns true if the node is in segmented mode, false otherwise.
116
+ */
117
+ isSegmented(): boolean;
118
+ /**
119
+ * Returns whether or not the node is "directionless". Directionless nodes don't respect changes between RTL and LTR modes.
120
+ *
121
+ * @returns true if the node is directionless, false otherwise.
122
+ */
123
+ isDirectionless(): boolean;
124
+ /**
125
+ * Returns whether or not the node is unmergeable. In some scenarios, Lexical tries to merge
126
+ * adjacent TextNodes into a single TextNode. If a TextNode is unmergeable, this won't happen.
127
+ *
128
+ * @returns true if the node is unmergeable, false otherwise.
129
+ */
130
+ isUnmergeable(): boolean;
131
+ /**
132
+ * Returns whether or not the node has the provided format applied. Use this with the human-readable TextFormatType
133
+ * string values to get the format of a TextNode.
134
+ *
135
+ * @param type - the TextFormatType to check for.
136
+ *
137
+ * @returns true if the node has the provided format, false otherwise.
138
+ */
139
+ hasFormat(type: TextFormatType): boolean;
140
+ /**
141
+ * Returns whether or not the node is simple text. Simple text is defined as a TextNode that has the string type "text"
142
+ * (i.e., not a subclass) and has no mode applied to it (i.e., not segmented or token).
143
+ *
144
+ * @returns true if the node is simple text, false otherwise.
145
+ */
146
+ isSimpleText(): boolean;
147
+ /**
148
+ * Returns the text content of the node as a string.
149
+ *
150
+ * @returns a string representing the text content of the node.
151
+ */
152
+ getTextContent(): string;
153
+ /**
154
+ * Returns the format flags applied to the node as a 32-bit integer.
155
+ *
156
+ * @returns a number representing the TextFormatTypes applied to the node.
157
+ */
158
+ getFormatFlags(type: TextFormatType, alignWithFormat: null | number): number;
159
+ /**
160
+ *
161
+ * @returns true if the text node supports font styling, false otherwise.
162
+ */
163
+ canHaveFormat(): boolean;
164
+ /**
165
+ * @returns true if the text node is inline, false otherwise.
166
+ */
167
+ isInline(): true;
168
+ createDOM(config: EditorConfig, editor?: LexicalEditor): HTMLElement;
169
+ updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean;
170
+ static importDOM(): DOMConversionMap | null;
171
+ static importJSON(serializedNode: SerializedTextNode): TextNode;
172
+ updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedTextNode>): this;
173
+ exportDOM(editor: LexicalEditor): DOMExportOutput;
174
+ exportJSON(): SerializedTextNode;
175
+ selectionTransform(prevSelection: null | BaseSelection, nextSelection: RangeSelection): void;
176
+ /**
177
+ * Sets the node format to the provided TextFormatType or 32-bit integer. Note that the TextFormatType
178
+ * version of the argument can only specify one format and doing so will remove all other formats that
179
+ * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleFormat}
180
+ *
181
+ * @param format - TextFormatType or 32-bit integer representing the node format.
182
+ *
183
+ * @returns this TextNode.
184
+ * // TODO 0.12 This should just be a `string`.
185
+ */
186
+ setFormat(format: TextFormatType | number): this;
187
+ /**
188
+ * Sets the node detail to the provided TextDetailType or 32-bit integer. Note that the TextDetailType
189
+ * version of the argument can only specify one detail value and doing so will remove all other detail values that
190
+ * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleDirectionless}
191
+ * or {@link TextNode.toggleUnmergeable}
192
+ *
193
+ * @param detail - TextDetailType or 32-bit integer representing the node detail.
194
+ *
195
+ * @returns this TextNode.
196
+ * // TODO 0.12 This should just be a `string`.
197
+ */
198
+ setDetail(detail: TextDetailType | number): this;
199
+ /**
200
+ * Sets the node style to the provided CSSText-like string. Set this property as you
201
+ * would an HTMLElement style attribute to apply inline styles to the underlying DOM Element.
202
+ *
203
+ * @param style - CSSText to be applied to the underlying HTMLElement.
204
+ *
205
+ * @returns this TextNode.
206
+ */
207
+ setStyle(style: string): this;
208
+ /**
209
+ * Applies the provided format to this TextNode if it's not present. Removes it if it's present.
210
+ * The subscript and superscript formats are mutually exclusive.
211
+ * Prefer using this method to turn specific formats on and off.
212
+ *
213
+ * @param type - TextFormatType to toggle.
214
+ *
215
+ * @returns this TextNode.
216
+ */
217
+ toggleFormat(type: TextFormatType): this;
218
+ /**
219
+ * Toggles the directionless detail value of the node. Prefer using this method over setDetail.
220
+ *
221
+ * @returns this TextNode.
222
+ */
223
+ toggleDirectionless(): this;
224
+ /**
225
+ * Toggles the unmergeable detail value of the node. Prefer using this method over setDetail.
226
+ *
227
+ * @returns this TextNode.
228
+ */
229
+ toggleUnmergeable(): this;
230
+ /**
231
+ * Sets the mode of the node.
232
+ *
233
+ * @returns this TextNode.
234
+ */
235
+ setMode(type: TextModeType): this;
236
+ /**
237
+ * Sets the text content of the node.
238
+ *
239
+ * @param text - the string to set as the text value of the node.
240
+ *
241
+ * @returns this TextNode.
242
+ */
243
+ setTextContent(text: string): this;
244
+ /**
245
+ * Sets the current Lexical selection to be a RangeSelection with anchor and focus on this TextNode at the provided offsets.
246
+ *
247
+ * @param _anchorOffset - the offset at which the Selection anchor will be placed.
248
+ * @param _focusOffset - the offset at which the Selection focus will be placed.
249
+ *
250
+ * @returns the new RangeSelection.
251
+ */
252
+ select(_anchorOffset?: number, _focusOffset?: number): RangeSelection;
253
+ selectStart(): RangeSelection;
254
+ selectEnd(): RangeSelection;
255
+ /**
256
+ * Inserts the provided text into this TextNode at the provided offset, deleting the number of characters
257
+ * specified. Can optionally calculate a new selection after the operation is complete.
258
+ *
259
+ * @param offset - the offset at which the splice operation should begin.
260
+ * @param delCount - the number of characters to delete, starting from the offset.
261
+ * @param newText - the text to insert into the TextNode at the offset.
262
+ * @param moveSelection - optional, whether or not to move selection to the end of the inserted substring.
263
+ *
264
+ * @returns this TextNode.
265
+ */
266
+ spliceText(offset: number, delCount: number, newText: string, moveSelection?: boolean): TextNode;
267
+ /**
268
+ * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
269
+ * when a user event would cause text to be inserted before them in the editor. If true, Lexical will attempt
270
+ * to insert text into this node. If false, it will insert the text in a new sibling node.
271
+ *
272
+ * @returns true if text can be inserted before the node, false otherwise.
273
+ */
274
+ canInsertTextBefore(): boolean;
275
+ /**
276
+ * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
277
+ * when a user event would cause text to be inserted after them in the editor. If true, Lexical will attempt
278
+ * to insert text into this node. If false, it will insert the text in a new sibling node.
279
+ *
280
+ * @returns true if text can be inserted after the node, false otherwise.
281
+ */
282
+ canInsertTextAfter(): boolean;
283
+ /**
284
+ * Splits this TextNode at the provided character offsets, forming new TextNodes from the substrings
285
+ * formed by the split, and inserting those new TextNodes into the editor, replacing the one that was split.
286
+ *
287
+ * @param splitOffsets - rest param of the text content character offsets at which this node should be split.
288
+ *
289
+ * @returns an Array containing the newly-created TextNodes.
290
+ */
291
+ splitText(...splitOffsets: Array<number>): Array<TextNode>;
292
+ /**
293
+ * Merges the target TextNode into this TextNode, removing the target node.
294
+ *
295
+ * @param target - the TextNode to merge into this one.
296
+ *
297
+ * @returns this TextNode.
298
+ */
299
+ mergeWithSibling(target: TextNode): TextNode;
300
+ /**
301
+ * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
302
+ * when used with the registerLexicalTextEntity function. If you're using registerLexicalTextEntity, the
303
+ * node class that you create and replace matched text with should return true from this method.
304
+ *
305
+ * @returns true if the node is to be treated as a "text entity", false otherwise.
306
+ */
307
+ isTextEntity(): boolean;
308
+ }
309
+ export declare function findParentPreDOMNode(node: Node): Node | null;
310
+ export declare function $createTextNode(text?: string): TextNode;
311
+ export declare function $isTextNode(node: LexicalNode | null | undefined): node is TextNode;
@@ -20,11 +20,16 @@ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) ===
20
20
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
21
21
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
22
22
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
23
+ /* eslint-disable import/no-duplicates */
23
24
  /* eslint-disable unicorn/no-for-loop */
24
25
  import { $isTableSelection } from '@lexical/table';
25
26
  import { $getCharacterOffsets, $getNodeByKey, $getSelection, $isElementNode, $isRangeSelection, $isTextNode, IS_CODE } from 'lexical';
27
+ import { $getRoot } from 'lexical';
26
28
  import { DataSource } from "../../../editor-kernel";
29
+ import { INodeHelper } from "../../../editor-kernel/inode/helper";
30
+ import { $parseSerializedNodeImpl } from "../../litexml/utils";
27
31
  import { cursorNodeSerialized } from "../node/cursor";
32
+ import { exportNodeToJSON } from "../utils";
28
33
  var JSONDataSource = /*#__PURE__*/function (_DataSource) {
29
34
  _inherits(JSONDataSource, _DataSource);
30
35
  var _super = _createSuper(JSONDataSource);
@@ -63,7 +68,24 @@ var JSONDataSource = /*#__PURE__*/function (_DataSource) {
63
68
  }
64
69
  };
65
70
  process(dataObj.root);
66
- editor.setEditorState(editor.parseEditorState(dataObj));
71
+ // @ts-expect-error add id option
72
+ if (dataObj.keepId) {
73
+ var state = editor.parseEditorState({
74
+ root: INodeHelper.createRootNode()
75
+ }, function (state) {
76
+ try {
77
+ var root = $parseSerializedNodeImpl(dataObj.root, editor, true, state);
78
+ state._nodeMap.set(root.getKey(), root);
79
+ } catch (error) {
80
+ console.error(error);
81
+ }
82
+ });
83
+ editor.setEditorState(state);
84
+ } else {
85
+ editor.setEditorState(editor.parseEditorState({
86
+ root: dataObj.root
87
+ }));
88
+ }
67
89
  }
68
90
  }, {
69
91
  key: "write",
@@ -173,11 +195,15 @@ var JSONDataSource = /*#__PURE__*/function (_DataSource) {
173
195
  // todo
174
196
  }
175
197
  return selection.getNodes().map(function (node) {
176
- return node.exportJSON();
198
+ return exportNodeToJSON(node);
177
199
  });
178
200
  });
179
201
  }
180
- return editor.getEditorState().toJSON();
202
+ return editor.read(function () {
203
+ return {
204
+ root: exportNodeToJSON($getRoot())
205
+ };
206
+ });
181
207
  }
182
208
  }]);
183
209
  return JSONDataSource;
@@ -146,6 +146,15 @@ var ReactPlainText = /*#__PURE__*/memo(function (_ref) {
146
146
  }
147
147
  });
148
148
  }, [editor, type, content, onChange, onTextChange, isInitialized]);
149
+ useEffect(function () {
150
+ var handleDocumentChange = function handleDocumentChange() {
151
+ onTextChange === null || onTextChange === void 0 || onTextChange(editor);
152
+ };
153
+ editor.on('documentChange', handleDocumentChange);
154
+ return function () {
155
+ editor.off('documentChange', handleDocumentChange);
156
+ };
157
+ }, [editor, onTextChange]);
149
158
  useEffect(function () {
150
159
  if (!isInitialized) return;
151
160
  if (typeof editable === 'boolean') {
@@ -1,4 +1,4 @@
1
- import type { ElementNode } from 'lexical';
1
+ import type { ElementNode, LexicalNode, SerializedLexicalNode } from 'lexical';
2
2
  import type { ElementTransformer } from "../../markdown/service/transformers";
3
3
  export declare const sampleReader: (format: number, xmlElement: Element, children: any[]) => any[];
4
4
  export declare const createBlockNode: (createNode: (match: Array<string>, parentNode: ElementNode) => ElementNode) => ElementTransformer['replace'];
@@ -32,3 +32,4 @@ export declare function $isCursorInTable(selection: any): {
32
32
  inTable: boolean;
33
33
  };
34
34
  export declare function $isCursorInQuote(selection: any): boolean;
35
+ export declare function exportNodeToJSON<SerializedNode extends SerializedLexicalNode>(node: LexicalNode): SerializedNode;
@@ -1,3 +1,4 @@
1
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
1
2
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
3
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
4
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -162,4 +163,36 @@ export function $isCursorInQuote(selection) {
162
163
  currentNode = parent;
163
164
  }
164
165
  return false;
166
+ }
167
+ export function exportNodeToJSON(node) {
168
+ var serializedNode = node.exportJSON();
169
+ var nodeClass = node.constructor;
170
+ // @ts-expect-error not error
171
+ serializedNode.id = node.getKey();
172
+ if (serializedNode.type !== nodeClass.getType()) {
173
+ throw new Error("LexicalNode: Node ".concat(nodeClass.name, " does not match the serialized type. Check if .exportJSON() is implemented and it is returning the correct type."));
174
+ }
175
+ if ($isElementNode(node)) {
176
+ var serializedChildren = serializedNode.children;
177
+ if (!Array.isArray(serializedChildren)) {
178
+ throw new Error("LexicalNode: Node ".concat(nodeClass.name, " is an element but .exportJSON() does not have a children array."));
179
+ }
180
+ var children = node.getChildren();
181
+ var _iterator = _createForOfIteratorHelper(children),
182
+ _step;
183
+ try {
184
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
185
+ var child = _step.value;
186
+ var serializedChildNode = exportNodeToJSON(child);
187
+ serializedChildren.push(serializedChildNode);
188
+ }
189
+ } catch (err) {
190
+ _iterator.e(err);
191
+ } finally {
192
+ _iterator.f();
193
+ }
194
+ }
195
+
196
+ // @ts-expect-error not error
197
+ return serializedNode;
165
198
  }
@@ -128,7 +128,15 @@ export var LITEXML_REMOVE_COMMAND = createCommand('LITEXML_REMOVE_COMMAND');
128
128
  export var LITEXML_INSERT_COMMAND = createCommand('LITEXML_INSERT_COMMAND');
129
129
  export function registerLiteXMLCommand(editor, dataSource) {
130
130
  return mergeRegister(editor.registerCommand(LITEXML_MODIFY_COMMAND, function (payload) {
131
- payload.forEach(function (item) {
131
+ var resultPayload = payload.reduce(function (acc, cur) {
132
+ if (cur.action === 'insert') {
133
+ acc.unshift(cur);
134
+ } else {
135
+ acc.push(cur);
136
+ }
137
+ return acc;
138
+ }, []);
139
+ resultPayload.forEach(function (item) {
132
140
  var action = item.action;
133
141
  switch (action) {
134
142
  case 'modify':
@@ -33,7 +33,7 @@ import { INodeHelper } from "../../../editor-kernel/inode/helper";
33
33
  import { INodeService } from "../../inode";
34
34
  import { createDebugLogger } from "../../../utils/debug";
35
35
  import { LitexmlService } from "../service/litexml-service";
36
- import { charToId, idToChar } from "../utils";
36
+ import { $parseSerializedNodeImpl, charToId, idToChar } from "../utils";
37
37
  var logger = createDebugLogger('plugin', 'litexml');
38
38
  var IXmlWriterContext = /*#__PURE__*/function () {
39
39
  function IXmlWriterContext() {
@@ -97,7 +97,17 @@ var LitexmlDataSource = /*#__PURE__*/function (_DataSource) {
97
97
  value: function read(editor, data) {
98
98
  try {
99
99
  var inode = this.readLiteXMLToInode(data);
100
- editor.setEditorState(editor.parseEditorState(inode));
100
+ var newState = editor.parseEditorState({
101
+ root: INodeHelper.createRootNode()
102
+ }, function (state) {
103
+ try {
104
+ var root = $parseSerializedNodeImpl(inode.root, editor, true, state);
105
+ state._nodeMap.set(root.getKey(), root);
106
+ } catch (error) {
107
+ console.error(error);
108
+ }
109
+ });
110
+ editor.setEditorState(newState);
101
111
  } catch (error) {
102
112
  logger.error('Failed to parse XML:', error);
103
113
  throw error;
@@ -14,6 +14,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
14
14
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
15
15
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
16
16
  import { KernelPlugin } from "../../../editor-kernel/plugin";
17
+ import { IMarkdownShortCutService } from "../../markdown";
17
18
  import { registerLiteXMLCommand } from "../command";
18
19
  import { registerLiteXMLDiffCommand } from "../command/diffCommand";
19
20
  import LitexmlDataSource from "../data-source/litexml-data-source";
@@ -74,11 +75,12 @@ export var LitexmlPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
74
75
  // Plugin initialization logic can be added here if needed
75
76
  this.register(registerLiteXMLCommand(editor, this.datasource));
76
77
  this.register(registerLiteXMLDiffCommand(editor));
77
- this.regiserLiteXml();
78
+ this.registerLiteXml();
79
+ this.registerMarkdown();
78
80
  }
79
81
  }, {
80
- key: "regiserLiteXml",
81
- value: function regiserLiteXml() {
82
+ key: "registerLiteXml",
83
+ value: function registerLiteXml() {
82
84
  this.service.registerXMLWriter(DiffNode.getType(), function (node, ctx, indent, nodeToXML) {
83
85
  var diffNode = node;
84
86
  var lines = [];
@@ -114,6 +116,42 @@ export var LitexmlPlugin = (_class = /*#__PURE__*/function (_KernelPlugin) {
114
116
  };
115
117
  });
116
118
  }
119
+ }, {
120
+ key: "registerMarkdown",
121
+ value: function registerMarkdown() {
122
+ var markdownService = this.kernel.requireService(IMarkdownShortCutService);
123
+ markdownService === null || markdownService === void 0 || markdownService.registerMarkdownWriter(DiffNode.getType(), function (ctx, node) {
124
+ var diffNode = node;
125
+ switch (diffNode.diffType) {
126
+ case 'modify':
127
+ {
128
+ ctx.processChild(ctx, diffNode.getChildAtIndex(1));
129
+ break;
130
+ }
131
+ case 'add':
132
+ {
133
+ ctx.processChild(ctx, diffNode.getChildAtIndex(0));
134
+ break;
135
+ }
136
+ case 'remove':
137
+ {
138
+ break;
139
+ }
140
+ case 'listItemModify':
141
+ {
142
+ diffNode.getChildAtIndex(1).getChildren().forEach(function (child) {
143
+ ctx.processChild(ctx, child);
144
+ });
145
+ break;
146
+ }
147
+ default:
148
+ {
149
+ break;
150
+ }
151
+ }
152
+ return true;
153
+ });
154
+ }
117
155
  }]);
118
156
  return LitexmlPlugin;
119
157
  }(KernelPlugin), _defineProperty(_class, "pluginName", 'LitexmlPlugin'), _class);
@@ -1,5 +1,6 @@
1
+ import type { EditorState } from 'lexical';
1
2
  import { LexicalEditor, LexicalNode } from 'lexical';
2
- export declare function $parseSerializedNodeImpl(serializedNode: any, editor: LexicalEditor): LexicalNode;
3
+ export declare function $parseSerializedNodeImpl(serializedNode: any, editor: LexicalEditor, keepId?: boolean, state?: EditorState | null): LexicalNode;
3
4
  export declare function $cloneNode(node: LexicalNode, editor: LexicalEditor): LexicalNode;
4
5
  export declare function idToChar(id: string | number): string;
5
6
  export declare function charToId(char: string): string;