@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.
- package/dist/{Lexical.dev-rcxzwpir.mjs → Lexical.dev-By5dOKBN.mjs} +1486 -356
- package/dist/{Lexical.node-BUsI9gWr.mjs → Lexical.node-fXM8Jp7p.mjs} +39 -17
- package/dist/{Lexical.prod-C8HtkSD6.mjs → Lexical.prod-BlCvXPGa.mjs} +2279 -1768
- package/dist/LexicalClipboard.dev--HxGoSkO.mjs +915 -0
- package/dist/{LexicalClipboard.node-CO-MCKx5.mjs → LexicalClipboard.node-C3mRbrmW.mjs} +10 -3
- package/dist/LexicalClipboard.prod-DNJzFMcT.mjs +371 -0
- package/dist/LexicalCodeCore.dev-DjSrd4A4.mjs +1109 -0
- package/dist/LexicalCodeCore.prod-DTDShkR3.mjs +642 -0
- package/dist/{LexicalDragon.dev-gBP8WSRS.mjs → LexicalDragon.dev-DwprRH0z.mjs} +3 -3
- package/dist/{LexicalDragon.node-OG6G55nl.mjs → LexicalDragon.node-BVhw4C7s.mjs} +2 -2
- package/dist/{LexicalDragon.prod-DP-_Q8cv.mjs → LexicalDragon.prod-nh4J-8vn.mjs} +3 -3
- package/dist/{LexicalExtension.dev-DVbjljrm.mjs → LexicalExtension.dev-BPNyvGqe.mjs} +335 -6
- package/dist/{LexicalExtension.node-CF3EAPN7.mjs → LexicalExtension.node-BVlcrgOx.mjs} +15 -8
- package/dist/{LexicalExtension.prod-DklHHErZ.mjs → LexicalExtension.prod-DFKbiNt-.mjs} +375 -265
- package/dist/{LexicalHeadless.dev-DdWLM7Nl.mjs → LexicalHeadless.dev-B-cj7Pr5.mjs} +2 -2
- package/dist/{LexicalHeadless.prod-CoiiTDzR.mjs → LexicalHeadless.prod-Byp1vNzT.mjs} +2 -2
- package/dist/LexicalHtml.dev-prBAwszN.mjs +2424 -0
- package/dist/LexicalHtml.node-BvNF96jZ.mjs +56 -0
- package/dist/LexicalHtml.prod-Sz3CW1ht.mjs +1207 -0
- package/dist/{LexicalLink.dev-BS1Bf-yD.mjs → LexicalLink.dev-NySTYhVR.mjs} +42 -8
- package/dist/{LexicalLink.prod-B_crkoHP.mjs → LexicalLink.prod-BuCM8gts.mjs} +209 -191
- package/dist/{LexicalList.dev-OMqmcnQ-.mjs → LexicalList.dev-DIMOvSFD.mjs} +252 -80
- package/dist/{LexicalList.prod-CpL1s8vS.mjs → LexicalList.prod-MVqfA6Vo.mjs} +364 -278
- package/dist/{LexicalMarkdown.dev-BHSdx_Gr.mjs → LexicalMarkdown.dev-C7aylvCG.mjs} +729 -552
- package/dist/LexicalMarkdown.prod-CfQSM406.mjs +868 -0
- package/dist/{LexicalRichText.dev-Bz9A_WbM.mjs → LexicalRichText.dev-DfICq6lU.mjs} +272 -77
- package/dist/{LexicalRichText.node-DDpwfE-P.mjs → LexicalRichText.node-Bg9jND3Q.mjs} +21 -8
- package/dist/LexicalRichText.prod-GsFzCK-o.mjs +550 -0
- package/dist/{LexicalSelection.dev-CQ380fnD.mjs → LexicalSelection.dev-DGjj12wW.mjs} +50 -38
- package/dist/{LexicalSelection.node-DesBMjIE.mjs → LexicalSelection.node-BU5L4193.mjs} +4 -4
- package/dist/{LexicalSelection.prod-D2jivCDB.mjs → LexicalSelection.prod-D-PwRbyK.mjs} +158 -140
- package/dist/{LexicalTable.dev-Ca7mQ7Jk.mjs → LexicalTable.dev-ChP7cugd.mjs} +215 -53
- package/dist/{LexicalTable.prod-DyPAcC7y.mjs → LexicalTable.prod-Bpr9YRXp.mjs} +668 -573
- package/dist/{LexicalUtils.dev-HxM8F0g6.mjs → LexicalUtils.dev-BiFU3789.mjs} +10 -47
- package/dist/{LexicalUtils.node-lCWjRjoG.mjs → LexicalUtils.node-j3Llm7Y3.mjs} +2 -2
- package/dist/{LexicalUtils.prod-Bti5w4ki.mjs → LexicalUtils.prod-DCvrA78p.mjs} +103 -105
- package/dist/bin/mxs.d.mts +1 -1
- package/dist/bin/mxs.mjs +1 -1
- package/dist/esm-By7trG9K.mjs +2 -0
- package/dist/{esm-CK9m5JKX.mjs → esm-Dg-WhPCe.mjs} +989 -989
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{mxs-BZt1cLW9.mjs → mxs-DT0oYk6U.mjs} +11935 -11866
- package/package.json +15 -14
- package/dist/LexicalClipboard.dev-BpqRwTLP.mjs +0 -494
- package/dist/LexicalClipboard.prod-B_xdeiAC.mjs +0 -291
- package/dist/LexicalCodeCore.dev-7_cexm39.mjs +0 -537
- package/dist/LexicalCodeCore.prod-Bd6WFHcO.mjs +0 -381
- package/dist/LexicalHtml.dev-C3ZSWBFZ.mjs +0 -684
- package/dist/LexicalHtml.node-D0TD152E.mjs +0 -24
- package/dist/LexicalHtml.prod-CX47X0zl.mjs +0 -430
- package/dist/LexicalMarkdown.prod-C-S7Ii6-.mjs +0 -754
- package/dist/LexicalRichText.prod-C8qXACDL.mjs +0 -427
- package/dist/esm-DRbkkY3r.mjs +0 -2
- /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.
|
|
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.
|
|
52
|
-
"@effect/cli": "0.75.
|
|
51
|
+
"@clack/prompts": "^1.5.1",
|
|
52
|
+
"@effect/cli": "0.75.2",
|
|
53
53
|
"@effect/platform": "0.96.1",
|
|
54
|
-
"@effect/platform-node": "0.
|
|
55
|
-
"@haklex/rich-headless": "0.
|
|
56
|
-
"@haklex/rich-litexml": "0.
|
|
57
|
-
"@haklex/rich-litexml-cli": "0.
|
|
58
|
-
"@lexical/headless": "^0.
|
|
59
|
-
"better-auth": "^1.6.
|
|
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.
|
|
63
|
+
"lexical": "^0.45.0",
|
|
64
64
|
"minisearch": "^7.2.0",
|
|
65
65
|
"open": "^11.0.0",
|
|
66
|
-
"semver": "7.8.
|
|
67
|
-
"@mx-space/api-client": "5.3.
|
|
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.
|
|
74
|
+
"tsdown": "0.22.2",
|
|
74
75
|
"tsx": "^4.22.4",
|
|
75
76
|
"typescript": "6.0.3",
|
|
76
|
-
"vitest": "4.1.
|
|
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 };
|