@mx-space/cli 0.7.8 → 0.8.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/dist/{Lexical.dev-rcxzwpir.mjs → Lexical.dev-By5dOKBN.mjs} +1486 -356
  2. package/dist/{Lexical.node-BUsI9gWr.mjs → Lexical.node-fXM8Jp7p.mjs} +39 -17
  3. package/dist/{Lexical.prod-C8HtkSD6.mjs → Lexical.prod-BlCvXPGa.mjs} +2279 -1768
  4. package/dist/LexicalClipboard.dev--HxGoSkO.mjs +915 -0
  5. package/dist/{LexicalClipboard.node-CO-MCKx5.mjs → LexicalClipboard.node-C3mRbrmW.mjs} +10 -3
  6. package/dist/LexicalClipboard.prod-DNJzFMcT.mjs +371 -0
  7. package/dist/LexicalCodeCore.dev-DjSrd4A4.mjs +1109 -0
  8. package/dist/LexicalCodeCore.prod-DTDShkR3.mjs +642 -0
  9. package/dist/{LexicalDragon.dev-gBP8WSRS.mjs → LexicalDragon.dev-DwprRH0z.mjs} +3 -3
  10. package/dist/{LexicalDragon.node-OG6G55nl.mjs → LexicalDragon.node-BVhw4C7s.mjs} +2 -2
  11. package/dist/{LexicalDragon.prod-DP-_Q8cv.mjs → LexicalDragon.prod-nh4J-8vn.mjs} +3 -3
  12. package/dist/{LexicalExtension.dev-DVbjljrm.mjs → LexicalExtension.dev-BPNyvGqe.mjs} +335 -6
  13. package/dist/{LexicalExtension.node-CF3EAPN7.mjs → LexicalExtension.node-BVlcrgOx.mjs} +15 -8
  14. package/dist/{LexicalExtension.prod-DklHHErZ.mjs → LexicalExtension.prod-DFKbiNt-.mjs} +375 -265
  15. package/dist/{LexicalHeadless.dev-DdWLM7Nl.mjs → LexicalHeadless.dev-B-cj7Pr5.mjs} +2 -2
  16. package/dist/{LexicalHeadless.prod-CoiiTDzR.mjs → LexicalHeadless.prod-Byp1vNzT.mjs} +2 -2
  17. package/dist/LexicalHtml.dev-prBAwszN.mjs +2424 -0
  18. package/dist/LexicalHtml.node-BvNF96jZ.mjs +56 -0
  19. package/dist/LexicalHtml.prod-Sz3CW1ht.mjs +1207 -0
  20. package/dist/{LexicalLink.dev-BS1Bf-yD.mjs → LexicalLink.dev-NySTYhVR.mjs} +42 -8
  21. package/dist/{LexicalLink.prod-B_crkoHP.mjs → LexicalLink.prod-BuCM8gts.mjs} +209 -191
  22. package/dist/{LexicalList.dev-OMqmcnQ-.mjs → LexicalList.dev-DIMOvSFD.mjs} +252 -80
  23. package/dist/{LexicalList.prod-CpL1s8vS.mjs → LexicalList.prod-MVqfA6Vo.mjs} +364 -278
  24. package/dist/{LexicalMarkdown.dev-BHSdx_Gr.mjs → LexicalMarkdown.dev-C7aylvCG.mjs} +729 -552
  25. package/dist/LexicalMarkdown.prod-CfQSM406.mjs +868 -0
  26. package/dist/{LexicalRichText.dev-Bz9A_WbM.mjs → LexicalRichText.dev-DfICq6lU.mjs} +272 -77
  27. package/dist/{LexicalRichText.node-DDpwfE-P.mjs → LexicalRichText.node-Bg9jND3Q.mjs} +21 -8
  28. package/dist/LexicalRichText.prod-GsFzCK-o.mjs +550 -0
  29. package/dist/{LexicalSelection.dev-CQ380fnD.mjs → LexicalSelection.dev-DGjj12wW.mjs} +50 -38
  30. package/dist/{LexicalSelection.node-DesBMjIE.mjs → LexicalSelection.node-BU5L4193.mjs} +4 -4
  31. package/dist/{LexicalSelection.prod-D2jivCDB.mjs → LexicalSelection.prod-D-PwRbyK.mjs} +158 -140
  32. package/dist/{LexicalTable.dev-Ca7mQ7Jk.mjs → LexicalTable.dev-ChP7cugd.mjs} +215 -53
  33. package/dist/{LexicalTable.prod-DyPAcC7y.mjs → LexicalTable.prod-Bpr9YRXp.mjs} +668 -573
  34. package/dist/{LexicalUtils.dev-HxM8F0g6.mjs → LexicalUtils.dev-BiFU3789.mjs} +10 -47
  35. package/dist/{LexicalUtils.node-lCWjRjoG.mjs → LexicalUtils.node-j3Llm7Y3.mjs} +2 -2
  36. package/dist/{LexicalUtils.prod-Bti5w4ki.mjs → LexicalUtils.prod-DCvrA78p.mjs} +103 -105
  37. package/dist/bin/mxs.d.mts +1 -1
  38. package/dist/bin/mxs.mjs +1 -1
  39. package/dist/esm-By7trG9K.mjs +2 -0
  40. package/dist/{esm-CK9m5JKX.mjs → esm-Dg-WhPCe.mjs} +989 -989
  41. package/dist/index.d.mts +1 -1
  42. package/dist/index.mjs +1 -1
  43. package/dist/{mxs-BZt1cLW9.mjs → mxs-DT0oYk6U.mjs} +11935 -11866
  44. package/package.json +15 -14
  45. package/dist/LexicalClipboard.dev-BpqRwTLP.mjs +0 -494
  46. package/dist/LexicalClipboard.prod-B_xdeiAC.mjs +0 -291
  47. package/dist/LexicalCodeCore.dev-7_cexm39.mjs +0 -537
  48. package/dist/LexicalCodeCore.prod-Bd6WFHcO.mjs +0 -381
  49. package/dist/LexicalHtml.dev-C3ZSWBFZ.mjs +0 -684
  50. package/dist/LexicalHtml.node-D0TD152E.mjs +0 -24
  51. package/dist/LexicalHtml.prod-CX47X0zl.mjs +0 -430
  52. package/dist/LexicalMarkdown.prod-C-S7Ii6-.mjs +0 -754
  53. package/dist/LexicalRichText.prod-C8qXACDL.mjs +0 -427
  54. package/dist/esm-DRbkkY3r.mjs +0 -2
  55. /package/dist/{mxs-CM8-6uAr.d.mts → mxs-iqJBopvE.d.mts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mx-space/cli",
3
- "version": "0.7.8",
3
+ "version": "0.8.0",
4
4
  "description": "Command line interface for mx-space (mx-core) — auth, content, configuration",
5
5
  "keywords": [
6
6
  "mx-space",
@@ -48,32 +48,33 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@clack/prompts": "^1.5.0",
52
- "@effect/cli": "0.75.1",
51
+ "@clack/prompts": "^1.5.1",
52
+ "@effect/cli": "0.75.2",
53
53
  "@effect/platform": "0.96.1",
54
- "@effect/platform-node": "0.106.0",
55
- "@haklex/rich-headless": "0.18.0",
56
- "@haklex/rich-litexml": "0.18.0",
57
- "@haklex/rich-litexml-cli": "0.18.0",
58
- "@lexical/headless": "^0.44.0",
59
- "better-auth": "^1.6.13",
54
+ "@effect/platform-node": "0.107.0",
55
+ "@haklex/rich-headless": "0.20.0",
56
+ "@haklex/rich-litexml": "0.21.0",
57
+ "@haklex/rich-litexml-cli": "0.20.0",
58
+ "@lexical/headless": "^0.45.0",
59
+ "better-auth": "^1.6.14",
60
60
  "effect": "3.21.2",
61
61
  "fast-xml-parser": "5.8.0",
62
62
  "get-east-asian-width": "^1.6.0",
63
- "lexical": "^0.44.0",
63
+ "lexical": "^0.45.0",
64
64
  "minisearch": "^7.2.0",
65
65
  "open": "^11.0.0",
66
- "semver": "7.8.1",
67
- "@mx-space/api-client": "5.3.0"
66
+ "semver": "7.8.2",
67
+ "@mx-space/api-client": "5.3.1",
68
+ "@mx-space/editor": "0.1.0"
68
69
  },
69
70
  "devDependencies": {
70
71
  "@effect/vitest": "0.29.0",
71
72
  "@types/node": "25.9.1",
72
73
  "@types/semver": "7.7.1",
73
- "tsdown": "0.22.0",
74
+ "tsdown": "0.22.2",
74
75
  "tsx": "^4.22.4",
75
76
  "typescript": "6.0.3",
76
- "vitest": "4.1.7"
77
+ "vitest": "4.1.8"
77
78
  },
78
79
  "scripts": {
79
80
  "package": "rm -rf dist && tsdown",
@@ -1,494 +0,0 @@
1
- import { i as getExtensionDependencyFromEditor, n as LexicalBuilder } from "./LexicalExtension.node-CF3EAPN7.mjs";
2
- import { $n as safeCast, A as $getCollapsedCaretRange, D as $getChildCaret, Dt as COMMAND_PRIORITY_CRITICAL, H as $getTextPointCaret, Jn as isSelectionWithinEditor, Mn as defineExtension, Mt as COPY_COMMAND, N as $getNearestNodeFromDOMNode, Nn as getDOMSelection, O as $getChildCaretAtIndex, R as $getRoot, T as $getCaretRangeInDirection, Y as $isElementNode, ct as $isTextNode, g as $createTabNode, i as $caretRangeFromSelection, j as $getEditor, lt as $isTextPointCaret, pt as $parseSerializedNode, r as $caretFromPoint, rr as shallowMergeConfig, rt as $isRangeSelection, s as $comparePointCaretNext, vn as SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, w as $getCaretRange, xt as $splitAtPointCaretNext, yt as $setSelectionFromCaretRange, z as $getSelection } from "./Lexical.node-BUsI9gWr.mjs";
3
- import { n as $generateNodesFromDOM, t as $generateHtmlFromNodes } from "./LexicalHtml.node-D0TD152E.mjs";
4
- import { a as $sliceSelectedTextNodeContent, t as $addNodeStyle } from "./LexicalSelection.node-DesBMjIE.mjs";
5
- import { g as objectKlassEquals } from "./LexicalUtils.node-lCWjRjoG.mjs";
6
- //#region ../../node_modules/.pnpm/@lexical+clipboard@0.44.0/node_modules/@lexical/clipboard/LexicalClipboard.dev.mjs
7
- /**
8
- * Copyright (c) Meta Platforms, Inc. and affiliates.
9
- *
10
- * This source code is licensed under the MIT license found in the
11
- * LICENSE file in the root directory of this source tree.
12
- *
13
- */
14
- /**
15
- * Copyright (c) Meta Platforms, Inc. and affiliates.
16
- *
17
- * This source code is licensed under the MIT license found in the
18
- * LICENSE file in the root directory of this source tree.
19
- *
20
- */
21
- function formatDevErrorMessage(message) {
22
- throw new Error(message);
23
- }
24
- /**
25
- * Copyright (c) Meta Platforms, Inc. and affiliates.
26
- *
27
- * This source code is licensed under the MIT license found in the
28
- * LICENSE file in the root directory of this source tree.
29
- *
30
- */
31
- function caretFromPoint(x, y) {
32
- if (typeof document.caretRangeFromPoint !== "undefined") {
33
- const range = document.caretRangeFromPoint(x, y);
34
- if (range === null) return null;
35
- return {
36
- node: range.startContainer,
37
- offset: range.startOffset
38
- };
39
- } else if (document.caretPositionFromPoint !== "undefined") {
40
- const range = document.caretPositionFromPoint(x, y);
41
- if (range === null) return null;
42
- return {
43
- node: range.offsetNode,
44
- offset: range.offset
45
- };
46
- } else return null;
47
- }
48
- /**
49
- * Returns the *currently selected* Lexical content as an HTML string, relying on the
50
- * logic defined in the exportDOM methods on the LexicalNode classes. Note that
51
- * this will not return the HTML content of the entire editor (unless all the content is included
52
- * in the current selection).
53
- *
54
- * @param editor - LexicalEditor instance to get HTML content from
55
- * @param selection - The selection to use (default is $getSelection())
56
- * @returns a string of HTML content
57
- */
58
- function $getHtmlContent(editor, selection = $getSelection()) {
59
- if (selection == null) formatDevErrorMessage(`Expected valid LexicalSelection`);
60
- if ($isRangeSelection(selection) && selection.isCollapsed() || selection.getNodes().length === 0) return "";
61
- return $generateHtmlFromNodes(editor, selection);
62
- }
63
- /**
64
- * Returns the *currently selected* Lexical content as a JSON string, relying on the
65
- * logic defined in the exportJSON methods on the LexicalNode classes. Note that
66
- * this will not return the JSON content of the entire editor (unless all the content is included
67
- * in the current selection).
68
- *
69
- * @param editor - LexicalEditor instance to get the JSON content from
70
- * @param selection - The selection to use (default is $getSelection())
71
- * @returns
72
- */
73
- function $getLexicalContent(editor, selection = $getSelection()) {
74
- if (selection == null) formatDevErrorMessage(`Expected valid LexicalSelection`);
75
- if ($isRangeSelection(selection) && selection.isCollapsed() || selection.getNodes().length === 0) return null;
76
- return JSON.stringify($generateJSONFromSelectedNodes(editor, selection));
77
- }
78
- /**
79
- * Attempts to insert content of the mime-types text/plain or text/uri-list from
80
- * the provided DataTransfer object into the editor at the provided selection.
81
- * text/uri-list is only used if text/plain is not also provided.
82
- *
83
- * @param dataTransfer an object conforming to the [DataTransfer interface] (https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface)
84
- * @param selection the selection to use as the insertion point for the content in the DataTransfer object
85
- */
86
- function $insertDataTransferForPlainText(dataTransfer, selection) {
87
- const text = dataTransfer.getData("text/plain") || dataTransfer.getData("text/uri-list");
88
- if (text != null) selection.insertRawText(text);
89
- }
90
- /**
91
- * Attempts to insert content of the mime-types application/x-lexical-editor, text/html,
92
- * text/plain, or text/uri-list (in descending order of priority) from the provided DataTransfer
93
- * object into the editor at the provided selection.
94
- *
95
- * @param dataTransfer an object conforming to the [DataTransfer interface] (https://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface)
96
- * @param selection the selection to use as the insertion point for the content in the DataTransfer object
97
- * @param editor the LexicalEditor the content is being inserted into.
98
- */
99
- function $insertDataTransferForRichText(dataTransfer, selection, editor) {
100
- const lexicalString = dataTransfer.getData("application/x-lexical-editor");
101
- if (lexicalString) try {
102
- const payload = JSON.parse(lexicalString);
103
- if (payload.namespace === editor._config.namespace && Array.isArray(payload.nodes)) return $insertGeneratedNodes(editor, $generateNodesFromSerializedNodes(payload.nodes), selection);
104
- } catch (error) {
105
- console.error(error);
106
- }
107
- const htmlString = dataTransfer.getData("text/html");
108
- const plainString = dataTransfer.getData("text/plain");
109
- if (htmlString && plainString !== htmlString) try {
110
- return $insertGeneratedNodes(editor, $generateNodesFromDOM(editor, new DOMParser().parseFromString(trustHTML(htmlString), "text/html")), selection);
111
- } catch (error) {
112
- console.error(error);
113
- }
114
- const text = plainString || dataTransfer.getData("text/uri-list");
115
- if (text != null) if ($isRangeSelection(selection)) {
116
- const parts = text.split(/(\r?\n|\t)/);
117
- if (parts[parts.length - 1] === "") parts.pop();
118
- for (let i = 0; i < parts.length; i++) {
119
- const currentSelection = $getSelection();
120
- if ($isRangeSelection(currentSelection)) {
121
- const part = parts[i];
122
- if (part === "\n" || part === "\r\n") currentSelection.insertParagraph();
123
- else if (part === " ") currentSelection.insertNodes([$createTabNode()]);
124
- else currentSelection.insertText(part);
125
- }
126
- }
127
- } else selection.insertRawText(text);
128
- }
129
- const LEXICAL_DRAG_MIME_TYPE = "application/x-lexical-drag";
130
- /**
131
- * Populate `dataTransfer` with a marker identifying the current editor as a
132
- * drag source. Pair this with {@link $handleRichTextDrop} or
133
- * {@link $handlePlainTextDrop} on the drop side to get cut-and-paste semantics
134
- * for drags that end in a different editor.
135
- *
136
- * Only the source editor's key needs to round-trip — the source's
137
- * RangeSelection itself is preserved on the source editor between drag start
138
- * and drop (Lexical suppresses selectionchange during drag), so the drop
139
- * handler reads it directly via `$getSelection()` on the resolved source
140
- * editor.
141
- *
142
- * Callers typically invoke this from a DRAGSTART_COMMAND handler alongside
143
- * {@link setLexicalClipboardDataTransfer} (so that the dragged content itself
144
- * round-trips with full node fidelity).
145
- */
146
- function $writeDragSourceToDataTransfer(dataTransfer, editor) {
147
- const marker = { editorKey: editor.getKey() };
148
- dataTransfer.setData(LEXICAL_DRAG_MIME_TYPE, JSON.stringify(marker));
149
- }
150
- function isLexicalDragMarker(value) {
151
- return value !== null && typeof value === "object" && "editorKey" in value && typeof value.editorKey === "string";
152
- }
153
- function readDragMarker(dataTransfer) {
154
- const raw = dataTransfer.getData(LEXICAL_DRAG_MIME_TYPE);
155
- if (!raw) return null;
156
- let parsed;
157
- try {
158
- parsed = JSON.parse(raw);
159
- } catch (_unused) {
160
- return null;
161
- }
162
- return isLexicalDragMarker(parsed) ? parsed : null;
163
- }
164
- function findEditorRootByKey(key, doc) {
165
- const elements = doc.querySelectorAll("[data-lexical-editor=\"true\"]");
166
- for (const el of Array.from(elements)) {
167
- const editor = el.__lexicalEditor;
168
- if (editor && editor.getKey() === key) return el;
169
- }
170
- return null;
171
- }
172
- function $resolveDropPointCaret(event) {
173
- const hit = caretFromPoint(event.clientX, event.clientY);
174
- if (hit === null) return null;
175
- const node = $getNearestNodeFromDOMNode(hit.node);
176
- if (node === null) return null;
177
- if ($isTextNode(node)) return $getTextPointCaret(node, "next", hit.offset);
178
- if ($isElementNode(node)) return $getChildCaretAtIndex(node, hit.offset, "next");
179
- const parent = node.getParent();
180
- if (parent === null) return null;
181
- return $getChildCaretAtIndex(parent, node.getIndexWithinParent() + 1, "next");
182
- }
183
- function $isDropCaretInsideSelection(dropCaret, selection) {
184
- const { anchor: start, focus: end } = $getCaretRangeInDirection($caretRangeFromSelection(selection), "next");
185
- return $comparePointCaretNext(start, dropCaret) < 0 && $comparePointCaretNext(dropCaret, end) < 0;
186
- }
187
- function $doDrop(event, editor, $insertDataTransfer) {
188
- const dataTransfer = event.dataTransfer;
189
- if (dataTransfer === null) return false;
190
- const marker = readDragMarker(dataTransfer);
191
- if (marker === null) return false;
192
- const dropCaret = $resolveDropPointCaret(event);
193
- if (dropCaret === null) return false;
194
- const stableDropCaret = $splitAtPointCaretNext(dropCaret);
195
- if (stableDropCaret === null) return false;
196
- const isSameEditorDrag = marker.editorKey === editor.getKey();
197
- const currentSelection = $getSelection();
198
- if (isSameEditorDrag) {
199
- if (!$isRangeSelection(currentSelection) || currentSelection.isCollapsed()) return false;
200
- if ($isDropCaretInsideSelection(dropCaret, currentSelection)) {
201
- event.preventDefault();
202
- return true;
203
- }
204
- currentSelection.removeText();
205
- }
206
- if (!stableDropCaret.origin.isAttached()) {
207
- event.preventDefault();
208
- return true;
209
- }
210
- $insertDataTransfer(dataTransfer, $setSelectionFromCaretRange($getCollapsedCaretRange(stableDropCaret)), editor);
211
- if (!isSameEditorDrag) {
212
- const rootElement = editor.getRootElement();
213
- const doc = rootElement ? rootElement.ownerDocument : null;
214
- const sourceRoot = doc ? findEditorRootByKey(marker.editorKey, doc) : null;
215
- if (sourceRoot !== null) sourceRoot.dispatchEvent(new InputEvent("beforeinput", {
216
- bubbles: true,
217
- cancelable: true,
218
- inputType: "deleteByDrag"
219
- }));
220
- }
221
- event.preventDefault();
222
- return true;
223
- }
224
- /**
225
- * Drop handler for rich-text editors. Inserts the DataTransfer payload via
226
- * {@link $insertDataTransferForRichText} at the drop caret and, when the drag
227
- * originated from a Lexical editor (marked via
228
- * {@link $writeDragSourceToDataTransfer} on DRAGSTART), removes the source
229
- * range — producing cut-and-paste semantics whether the drop is in the same
230
- * editor or a different one on the same page.
231
- */
232
- function $handleRichTextDrop(event, editor) {
233
- return $doDrop(event, editor, $insertDataTransferForRichText);
234
- }
235
- /**
236
- * Drop handler for plain-text editors. Same semantics as
237
- * {@link $handleRichTextDrop} but inserts via
238
- * {@link $insertDataTransferForPlainText}.
239
- */
240
- function $handlePlainTextDrop(event, editor) {
241
- return $doDrop(event, editor, (dataTransfer, selection) => $insertDataTransferForPlainText(dataTransfer, selection));
242
- }
243
- function trustHTML(html) {
244
- if (window.trustedTypes && window.trustedTypes.createPolicy) return window.trustedTypes.createPolicy("lexical", { createHTML: (input) => input }).createHTML(html);
245
- return html;
246
- }
247
- /**
248
- * Inserts Lexical nodes into the editor using different strategies depending on
249
- * some simple selection-based heuristics. If you're looking for a generic way to
250
- * to insert nodes into the editor at a specific selection point, you probably want
251
- * {@link lexical.$insertNodes}
252
- *
253
- * @param editor LexicalEditor instance to insert the nodes into.
254
- * @param nodes The nodes to insert.
255
- * @param selection The selection to insert the nodes into.
256
- */
257
- function $insertGeneratedNodes(editor, nodes, selection) {
258
- if (!editor.dispatchCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, {
259
- nodes,
260
- selection
261
- })) {
262
- selection.insertNodes(nodes);
263
- $updateSelectionOnInsert(selection);
264
- }
265
- }
266
- function $updateSelectionOnInsert(selection) {
267
- if ($isRangeSelection(selection) && selection.isCollapsed()) {
268
- const anchor = selection.anchor;
269
- let nodeToInspect = null;
270
- const anchorCaret = $caretFromPoint(anchor, "previous");
271
- if (anchorCaret) if ($isTextPointCaret(anchorCaret)) nodeToInspect = anchorCaret.origin;
272
- else {
273
- const range = $getCaretRange(anchorCaret, $getChildCaret($getRoot(), "next").getFlipped());
274
- for (const caret of range) if ($isTextNode(caret.origin)) {
275
- nodeToInspect = caret.origin;
276
- break;
277
- } else if ($isElementNode(caret.origin) && !caret.origin.isInline()) break;
278
- }
279
- if (nodeToInspect && $isTextNode(nodeToInspect)) {
280
- const newFormat = nodeToInspect.getFormat();
281
- const newStyle = nodeToInspect.getStyle();
282
- if (selection.format !== newFormat || selection.style !== newStyle) {
283
- selection.format = newFormat;
284
- selection.style = newStyle;
285
- selection.dirty = true;
286
- }
287
- }
288
- }
289
- }
290
- function exportNodeToJSON(node) {
291
- const serializedNode = node.exportJSON();
292
- const nodeClass = node.constructor;
293
- if (serializedNode.type !== nodeClass.getType()) formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} does not implement .exportJSON().`);
294
- if ($isElementNode(node)) {
295
- const serializedChildren = serializedNode.children;
296
- if (!Array.isArray(serializedChildren)) formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} is an element but .exportJSON() does not have a children array.`);
297
- }
298
- return serializedNode;
299
- }
300
- function $appendNodesToJSON(editor, selection, currentNode, targetArray = []) {
301
- let shouldInclude = selection !== null ? currentNode.isSelected(selection) : true;
302
- const shouldExclude = $isElementNode(currentNode) && currentNode.excludeFromCopy("html");
303
- let target = currentNode;
304
- if (selection !== null && $isTextNode(target)) target = $sliceSelectedTextNodeContent(selection, target, "clone");
305
- const children = $isElementNode(target) ? target.getChildren() : [];
306
- const serializedNode = exportNodeToJSON(target);
307
- if ($isTextNode(target) && target.getTextContentSize() === 0) shouldInclude = false;
308
- for (let i = 0; i < children.length; i++) {
309
- const childNode = children[i];
310
- const shouldIncludeChild = $appendNodesToJSON(editor, selection, childNode, serializedNode.children);
311
- if (!shouldInclude && $isElementNode(currentNode) && shouldIncludeChild && currentNode.extractWithChild(childNode, selection, "clone")) shouldInclude = true;
312
- }
313
- if (shouldInclude && !shouldExclude) targetArray.push(serializedNode);
314
- else if (Array.isArray(serializedNode.children)) for (let i = 0; i < serializedNode.children.length; i++) {
315
- const serializedChildNode = serializedNode.children[i];
316
- targetArray.push(serializedChildNode);
317
- }
318
- return shouldInclude;
319
- }
320
- /**
321
- * Gets the Lexical JSON of the nodes inside the provided Selection.
322
- *
323
- * @param editor LexicalEditor to get the JSON content from.
324
- * @param selection Selection to get the JSON content from.
325
- * @returns an object with the editor namespace and a list of serializable nodes as JavaScript objects.
326
- */
327
- function $generateJSONFromSelectedNodes(editor, selection) {
328
- const nodes = [];
329
- const topLevelChildren = $getRoot().getChildren();
330
- for (let i = 0; i < topLevelChildren.length; i++) {
331
- const topLevelNode = topLevelChildren[i];
332
- $appendNodesToJSON(editor, selection, topLevelNode, nodes);
333
- }
334
- return {
335
- namespace: editor._config.namespace,
336
- nodes
337
- };
338
- }
339
- /**
340
- * This method takes an array of objects conforming to the BaseSerializedNode interface and returns
341
- * an Array containing instances of the corresponding LexicalNode classes registered on the editor.
342
- * Normally, you'd get an Array of BaseSerialized nodes from {@link $generateJSONFromSelectedNodes}
343
- *
344
- * @param serializedNodes an Array of objects conforming to the BaseSerializedNode interface.
345
- * @returns an Array of Lexical Node objects.
346
- */
347
- function $generateNodesFromSerializedNodes(serializedNodes) {
348
- const nodes = [];
349
- for (let i = 0; i < serializedNodes.length; i++) {
350
- const serializedNode = serializedNodes[i];
351
- const node = $parseSerializedNode(serializedNode);
352
- if ($isTextNode(node)) $addNodeStyle(node);
353
- nodes.push(node);
354
- }
355
- return nodes;
356
- }
357
- const EVENT_LATENCY = 50;
358
- let clipboardEventTimeout = null;
359
- /**
360
- * Copies the content of the current selection to the clipboard in
361
- * text/plain, text/html, and application/x-lexical-editor (Lexical JSON)
362
- * formats.
363
- *
364
- * @param editor the LexicalEditor instance to copy content from
365
- * @param event the native browser ClipboardEvent to add the content to.
366
- * @returns
367
- */
368
- async function copyToClipboard(editor, event, data) {
369
- if (clipboardEventTimeout !== null) return false;
370
- if (event !== null) return new Promise((resolve, reject) => {
371
- editor.update(() => {
372
- resolve($copyToClipboardEvent(editor, event, data));
373
- });
374
- });
375
- const rootElement = editor.getRootElement();
376
- const editorWindow = editor._window || window;
377
- const windowDocument = editorWindow.document;
378
- const domSelection = getDOMSelection(editorWindow);
379
- if (rootElement === null || domSelection === null) return false;
380
- const element = windowDocument.createElement("span");
381
- element.style.position = "fixed";
382
- element.style.top = "-1000px";
383
- element.append(windowDocument.createTextNode("#"));
384
- rootElement.append(element);
385
- const range = new Range();
386
- range.setStart(element, 0);
387
- range.setEnd(element, 1);
388
- domSelection.removeAllRanges();
389
- domSelection.addRange(range);
390
- return new Promise((resolve, reject) => {
391
- const removeListener = editor.registerCommand(COPY_COMMAND, (secondEvent) => {
392
- if (objectKlassEquals(secondEvent, ClipboardEvent)) {
393
- removeListener();
394
- if (clipboardEventTimeout !== null) {
395
- editorWindow.clearTimeout(clipboardEventTimeout);
396
- clipboardEventTimeout = null;
397
- }
398
- resolve($copyToClipboardEvent(editor, secondEvent, data));
399
- }
400
- return true;
401
- }, COMMAND_PRIORITY_CRITICAL);
402
- clipboardEventTimeout = editorWindow.setTimeout(() => {
403
- removeListener();
404
- clipboardEventTimeout = null;
405
- resolve(false);
406
- }, EVENT_LATENCY);
407
- windowDocument.execCommand("copy");
408
- element.remove();
409
- });
410
- }
411
- function $copyToClipboardEvent(editor, event, data) {
412
- if (data === void 0) {
413
- const domSelection = getDOMSelection(editor._window);
414
- const selection = $getSelection();
415
- if (!selection || selection.isCollapsed()) return false;
416
- if (!domSelection) return false;
417
- const anchorDOM = domSelection.anchorNode;
418
- const focusDOM = domSelection.focusNode;
419
- if (anchorDOM !== null && focusDOM !== null && !isSelectionWithinEditor(editor, anchorDOM, focusDOM)) return false;
420
- data = $getClipboardDataFromSelection(selection);
421
- }
422
- event.preventDefault();
423
- const clipboardData = event.clipboardData;
424
- if (clipboardData === null) return false;
425
- setLexicalClipboardDataTransfer(clipboardData, data);
426
- return true;
427
- }
428
- const clipboardDataFunctions = [["text/html", $getHtmlContent], ["application/x-lexical-editor", $getLexicalContent]];
429
- /**
430
- * Serialize the content of the current selection to strings in
431
- * text/plain, text/html, and application/x-lexical-editor (Lexical JSON)
432
- * formats (as available).
433
- *
434
- * @param selection the selection to serialize (defaults to $getSelection())
435
- * @returns LexicalClipboardData
436
- */
437
- function $getClipboardDataFromSelection(selection = $getSelection()) {
438
- return $getClipboardDataWithConfigFromSelection($getExportConfig(), selection);
439
- }
440
- /**
441
- * Call setData on the given clipboardData for each MIME type present
442
- * in the given data (from {@link $getClipboardDataFromSelection})
443
- *
444
- * @param clipboardData the event.clipboardData to populate from data
445
- * @param data The lexical data
446
- */
447
- function setLexicalClipboardDataTransfer(clipboardData, data) {
448
- for (const [k] of clipboardDataFunctions) if (data[k] === void 0) clipboardData.setData(k, "");
449
- for (const k in data) {
450
- const v = data[k];
451
- if (v !== void 0) clipboardData.setData(k, v);
452
- }
453
- }
454
- function $getExportConfig() {
455
- const editor = $getEditor();
456
- const builder = LexicalBuilder.maybeFromEditor(editor);
457
- if (builder && builder.hasExtensionByName(GetClipboardDataExtension.name)) return getExtensionDependencyFromEditor(editor, GetClipboardDataExtension).output;
458
- return DEFAULT_EXPORT_MIME_TYPE;
459
- }
460
- const DEFAULT_EXPORT_MIME_TYPE = {
461
- "application/x-lexical-editor": [(sel, next) => sel ? $getLexicalContent($getEditor(), sel) : next()],
462
- "text/html": [(sel, next) => sel ? $getHtmlContent($getEditor(), sel) : next()],
463
- "text/plain": [(sel, next) => sel ? sel.getTextContent() : next()]
464
- };
465
- function $getClipboardDataWithConfigFromSelection($exportMimeType, selection) {
466
- const clipboardData = { "text/plain": "" };
467
- for (const [k, fns] of Object.entries($exportMimeType)) {
468
- const v = callExportMimeTypeFunctionStack(fns, selection);
469
- if (v !== null) clipboardData[k] = v;
470
- }
471
- return clipboardData;
472
- }
473
- function callExportMimeTypeFunctionStack(fns, selection) {
474
- const callAt = (i) => fns[i] ? fns[i](selection, callAt.bind(null, i - 1)) : null;
475
- return callAt(fns.length - 1);
476
- }
477
- const GetClipboardDataExtension = defineExtension({
478
- build(editor, config, state) {
479
- return config.$exportMimeType;
480
- },
481
- config: safeCast({ $exportMimeType: DEFAULT_EXPORT_MIME_TYPE }),
482
- mergeConfig(config, partial) {
483
- const merged = shallowMergeConfig(config, partial);
484
- if (partial.$exportMimeType) {
485
- const $exportMimeType = { ...config.$exportMimeType };
486
- for (const [k, v] of Object.entries(partial.$exportMimeType)) $exportMimeType[k] = [...$exportMimeType[k], ...v];
487
- merged.$exportMimeType = $exportMimeType;
488
- }
489
- return merged;
490
- },
491
- name: "@lexical/clipboard/GetClipboardData"
492
- });
493
- //#endregion
494
- export { $generateJSONFromSelectedNodes, $generateNodesFromSerializedNodes, $getClipboardDataFromSelection, $getHtmlContent, $getLexicalContent, $handlePlainTextDrop, $handleRichTextDrop, $insertDataTransferForPlainText, $insertDataTransferForRichText, $insertGeneratedNodes, $writeDragSourceToDataTransfer, copyToClipboard, setLexicalClipboardDataTransfer };