@lobehub/editor 4.24.1 → 4.25.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/es/codemirror/style.js +42 -0
- package/es/editor-kernel/kernel.js +3 -0
- package/es/editor-kernel/react/useDecorators.js +2 -4
- package/es/headless/collapsible-plugin.js +74 -0
- package/es/headless/index.js +2 -0
- package/es/headless.d.ts +18 -0
- package/es/headless.js +2479 -71
- package/es/index.d.ts +26 -3
- package/es/index.js +17 -2
- package/es/locale/index.d.ts +14 -0
- package/es/locale/index.js +14 -0
- package/es/plugins/block/command/index.js +24 -0
- package/es/plugins/block/plugin/index.js +7 -5
- package/es/plugins/block/react/ReactBlockPlugin.js +43 -1
- package/es/plugins/block/react/core/menu-position.js +20 -0
- package/es/plugins/block/react/drag/drag-session.js +3 -2
- package/es/plugins/block/react/drag/drag-utils.js +13 -1
- package/es/plugins/codemirror-block/index.d.ts +2 -1
- package/es/plugins/codemirror-block/plugin/index.js +2 -0
- package/es/plugins/codemirror-block/react/CodemirrorNode.js +95 -5
- package/es/plugins/codemirror-block/react/useCodemirrorEditLock.js +33 -0
- package/es/plugins/codemirror-block/service/index.d.ts +40 -0
- package/es/plugins/codemirror-block/service/index.js +59 -0
- package/es/plugins/collapsible/command/index.d.ts +17 -0
- package/es/plugins/collapsible/command/index.js +72 -0
- package/es/plugins/collapsible/index.d.ts +7 -0
- package/es/plugins/collapsible/node/CollapsibleNode.d.ts +30 -0
- package/es/plugins/collapsible/node/CollapsibleNode.js +138 -0
- package/es/plugins/collapsible/plugin/index.d.ts +11 -0
- package/es/plugins/collapsible/plugin/index.js +535 -0
- package/es/plugins/collapsible/react/ReactCollapsiblePlugin.d.ts +6 -0
- package/es/plugins/collapsible/react/ReactCollapsiblePlugin.js +19 -0
- package/es/plugins/collapsible/react/index.d.ts +3 -0
- package/es/plugins/collapsible/react/style.js +67 -0
- package/es/plugins/collapsible/react/type.d.ts +6 -0
- package/es/plugins/common/plugin/index.js +3 -2
- package/es/plugins/common/plugin/progressive-select-all.js +81 -0
- package/es/plugins/common/plugin/register.js +73 -4
- package/es/plugins/link/command/index.js +26 -3
- package/es/plugins/link/conversion/index.js +237 -0
- package/es/plugins/link/index.d.ts +5 -3
- package/es/plugins/link/node/LinkBlockCardNode.d.ts +16 -0
- package/es/plugins/link/node/LinkBlockCardNode.js +66 -0
- package/es/plugins/link/node/LinkCardNode.d.ts +42 -0
- package/es/plugins/link/node/LinkCardNode.js +161 -0
- package/es/plugins/link/node/LinkIframeNode.d.ts +33 -0
- package/es/plugins/link/node/LinkIframeNode.js +131 -0
- package/es/plugins/link/node/LinkNode.d.ts +48 -2
- package/es/plugins/link/node/LinkNode.js +14 -6
- package/es/plugins/link/node/SchemaNode.d.ts +36 -0
- package/es/plugins/link/node/SchemaNode.js +149 -0
- package/es/plugins/link/normalization/index.d.ts +7 -0
- package/es/plugins/link/normalization/index.js +38 -0
- package/es/plugins/link/plugin/index.d.ts +26 -1
- package/es/plugins/link/plugin/index.js +124 -4
- package/es/plugins/link/react/ReactLinkPlugin.js +165 -7
- package/es/plugins/link/react/components/LinkCard.js +235 -0
- package/es/plugins/link/react/components/LinkEdit.js +93 -14
- package/es/plugins/link/react/components/LinkIframe.js +128 -0
- package/es/plugins/link/react/components/LinkToolbar.js +440 -111
- package/es/plugins/link/react/components/SchemaLink.js +49 -0
- package/es/plugins/link/react/index.d.ts +2 -2
- package/es/plugins/link/react/renderer-registry.d.ts +81 -0
- package/es/plugins/link/react/renderer-registry.js +80 -0
- package/es/plugins/link/react/style.js +63 -1
- package/es/plugins/link/react/type.d.ts +24 -1
- package/es/plugins/link/service/i-link-service.d.ts +156 -1
- package/es/plugins/link/service/i-link-service.js +258 -5
- package/es/plugins/list/plugin/index.js +9 -2
- package/es/plugins/litexml/command/diffCommand.js +94 -14
- package/es/plugins/litexml/command/index.js +187 -6
- package/es/plugins/litexml/diff-validation.js +237 -0
- package/es/plugins/litexml/node/DiffContentNode.js +67 -0
- package/es/plugins/litexml/node/DiffNode.d.ts +1 -1
- package/es/plugins/litexml/node/DiffNode.js +5 -2
- package/es/plugins/litexml/node/TableCellDiffNode.js +77 -0
- package/es/plugins/litexml/node/TableRowDiffNode.js +73 -0
- package/es/plugins/litexml/plugin/index.d.ts +2 -0
- package/es/plugins/litexml/plugin/index.js +62 -9
- package/es/plugins/litexml/react/DiffNodeToolbar/index.js +10 -12
- package/es/plugins/litexml/react/TableRowDiffToolbar.js +123 -0
- package/es/plugins/litexml/react/hooks/useHasDiffNode.js +5 -2
- package/es/plugins/litexml/react/index.js +6 -2
- package/es/plugins/litexml/react/style.js +18 -5
- package/es/plugins/litexml/table-cell-diff.js +153 -0
- package/es/plugins/litexml/table-row-diff.js +82 -0
- package/es/plugins/markdown/data-source/markdown/parse.js +25 -1
- package/es/plugins/markdown/plugin/index.js +5 -3
- package/es/plugins/slash/react/ReactSlashPlugin.js +22 -43
- package/es/plugins/slash/react/components/DefaultSlashMenu.js +76 -16
- package/es/plugins/slash/react/menu-utils.js +84 -0
- package/es/plugins/slash/service/i-slash-service.d.ts +3 -0
- package/es/plugins/table/plugin/index.js +4 -1
- package/es/plugins/table/plugin/single-cell-paste.js +79 -0
- package/es/plugins/table/react/TableController/hooks.js +7 -4
- package/es/plugins/table/react/hooks.js +2 -2
- package/es/plugins/table/react/index.js +2 -0
- package/es/plugins/table/react/style.js +15 -5
- package/es/plugins/table/react/useScrollFocusedTableCellIntoView.js +46 -0
- package/es/plugins/toc/index.d.ts +10 -0
- package/es/plugins/toc/plugin/index.d.ts +8 -0
- package/es/plugins/toc/plugin/index.js +56 -0
- package/es/plugins/toc/react/ReactTocPlugin.d.ts +6 -0
- package/es/plugins/toc/react/ReactTocPlugin.js +36 -0
- package/es/plugins/toc/react/getNearestScrollContainer.d.ts +6 -0
- package/es/plugins/toc/react/getNearestScrollContainer.js +18 -0
- package/es/plugins/toc/react/hooks/useActiveHeading.js +59 -0
- package/es/plugins/toc/react/hooks/useTocItems.js +50 -0
- package/es/plugins/toc/react/index.d.ts +5 -0
- package/es/plugins/toc/react/type.d.ts +30 -0
- package/es/plugins/toc/react/useToc.d.ts +5 -0
- package/es/plugins/toc/react/useToc.js +41 -0
- package/es/plugins/toc/service/i-toc-service.d.ts +39 -0
- package/es/plugins/toc/service/i-toc-service.js +125 -0
- package/es/plugins/toc/service/index.d.ts +3 -0
- package/es/plugins/toc/types.d.ts +23 -0
- package/es/plugins/toc/utils/index.d.ts +6 -0
- package/es/plugins/toc/utils/index.js +30 -0
- package/es/plugins/toolbar/react/index.js +26 -12
- package/es/plugins/toolbar/react/style.js +3 -2
- package/es/plugins/virtual-block/plugin/register.js +34 -12
- package/es/plugins/yjs/index.d.ts +6 -0
- package/es/plugins/yjs/plugin/index.d.ts +7 -0
- package/es/plugins/yjs/plugin/index.js +191 -0
- package/es/plugins/yjs/plugin/types.d.ts +16 -0
- package/es/plugins/yjs/plugin/utils/awareness.js +9 -0
- package/es/plugins/yjs/plugin/utils/editor-state.js +47 -0
- package/es/plugins/yjs/plugin/utils/history.js +31 -0
- package/es/plugins/yjs/plugin/utils/node-properties.js +39 -0
- package/es/plugins/yjs/plugin/utils/sync.js +24 -0
- package/es/plugins/yjs/react/codemirrorEditLockProvider.js +59 -0
- package/es/plugins/yjs/react/index.d.ts +23 -0
- package/es/plugins/yjs/react/index.js +200 -0
- package/es/plugins/yjs/service/index.d.ts +47 -0
- package/es/plugins/yjs/service/index.js +84 -0
- package/es/plugins/yjs/websocket-provider.d.ts +78 -0
- package/es/plugins/yjs/websocket-provider.js +263 -0
- package/es/renderer/LexicalRenderer.js +9 -2
- package/es/types/kernel.d.ts +4 -0
- package/es/utils/updatePosition.js +5 -2
- package/package.json +3 -1
- package/patches/@lexical__yjs@0.42.0.patch +42 -0
- package/scripts/postinstall-lexical-patch.cjs +62 -36
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { $computeTableMapSkipCellCheck, $createTableSelection, $isTableCellNode, $isTableNode, $isTableSelection } from "@lexical/table";
|
|
2
|
+
import { $getNodeByKey, $getRoot, $getSelection, $isElementNode, $isRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, SELECT_ALL_COMMAND } from "lexical";
|
|
3
|
+
//#region src/plugins/common/plugin/progressive-select-all.ts
|
|
4
|
+
const COLLAPSIBLE_NODE_TYPE = "collapsible";
|
|
5
|
+
function registerProgressiveSelectAll(editor) {
|
|
6
|
+
return editor.registerCommand(SELECT_ALL_COMMAND, () => {
|
|
7
|
+
const selection = $getSelection();
|
|
8
|
+
if ($isTableSelection(selection)) return $expandTableSelection(selection);
|
|
9
|
+
if (!$isRangeSelection(selection)) return false;
|
|
10
|
+
const anchorCell = $findNearestNode(selection.anchor.getNode(), $isTableCellNode);
|
|
11
|
+
const focusCell = $findNearestNode(selection.focus.getNode(), $isTableCellNode);
|
|
12
|
+
if (anchorCell && focusCell && anchorCell.is(focusCell)) {
|
|
13
|
+
const table = $findNearestNode(anchorCell, $isTableNode);
|
|
14
|
+
if (table) {
|
|
15
|
+
const tableSelection = $createTableSelection();
|
|
16
|
+
tableSelection.set(table.getKey(), anchorCell.getKey(), anchorCell.getKey());
|
|
17
|
+
$setSelection(tableSelection);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const anchorCollapsible = $findCollapsibleAncestor(selection.anchor.getNode());
|
|
22
|
+
const focusCollapsible = $findCollapsibleAncestor(selection.focus.getNode());
|
|
23
|
+
if (!anchorCollapsible || !focusCollapsible || !anchorCollapsible.is(focusCollapsible)) return false;
|
|
24
|
+
if ($isEntireElementSelected(selection, anchorCollapsible)) $selectDocument();
|
|
25
|
+
else anchorCollapsible.select(0, anchorCollapsible.getChildrenSize());
|
|
26
|
+
return true;
|
|
27
|
+
}, COMMAND_PRIORITY_HIGH);
|
|
28
|
+
}
|
|
29
|
+
function $expandTableSelection(selection) {
|
|
30
|
+
const table = $getNodeByKey(selection.tableKey);
|
|
31
|
+
if (!$isTableNode(table)) return false;
|
|
32
|
+
const cells = $getTableCells(table);
|
|
33
|
+
if (!cells) return false;
|
|
34
|
+
const selectedCellKeys = new Set(selection.getNodes().filter($isTableCellNode).map((cell) => cell.getKey()));
|
|
35
|
+
if (cells.keys.every((key) => selectedCellKeys.has(key))) {
|
|
36
|
+
$selectDocument();
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
const tableSelection = $createTableSelection();
|
|
40
|
+
tableSelection.set(table.getKey(), cells.first.getKey(), cells.last.getKey());
|
|
41
|
+
$setSelection(tableSelection);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function $getTableCells(table) {
|
|
45
|
+
if (!$isTableNode(table)) return null;
|
|
46
|
+
const [tableMap] = $computeTableMapSkipCellCheck(table, null, null);
|
|
47
|
+
const entries = tableMap.flat().filter(Boolean);
|
|
48
|
+
const first = entries[0]?.cell;
|
|
49
|
+
const last = entries.at(-1)?.cell;
|
|
50
|
+
if (!first || !last) return null;
|
|
51
|
+
return {
|
|
52
|
+
first,
|
|
53
|
+
keys: Array.from(new Set(entries.map(({ cell }) => cell.getKey()))),
|
|
54
|
+
last
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function $findNearestNode(node, predicate) {
|
|
58
|
+
let current = node;
|
|
59
|
+
while (current) {
|
|
60
|
+
if (predicate(current)) return current;
|
|
61
|
+
current = current.getParent();
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function $findCollapsibleAncestor(node) {
|
|
66
|
+
return $findNearestNode(node, (candidate) => $isElementNode(candidate) && candidate.getType() === COLLAPSIBLE_NODE_TYPE);
|
|
67
|
+
}
|
|
68
|
+
function $isEntireElementSelected(selection, element) {
|
|
69
|
+
const startOffset = 0;
|
|
70
|
+
const endOffset = element.getChildrenSize();
|
|
71
|
+
return $isPointAt(selection.anchor, element, startOffset) && $isPointAt(selection.focus, element, endOffset) || $isPointAt(selection.focus, element, startOffset) && $isPointAt(selection.anchor, element, endOffset);
|
|
72
|
+
}
|
|
73
|
+
function $isPointAt(point, element, offset) {
|
|
74
|
+
return point.key === element.getKey() && point.offset === offset && point.type === "element";
|
|
75
|
+
}
|
|
76
|
+
function $selectDocument() {
|
|
77
|
+
const root = $getRoot();
|
|
78
|
+
root.select(0, root.getChildrenSize());
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { registerProgressiveSelectAll };
|
|
@@ -2,8 +2,9 @@ import { createDebugLogger, init_debug } from "../../../utils/debug.js";
|
|
|
2
2
|
import { HotkeyEnum, init_hotkey } from "../../../types/hotkey.js";
|
|
3
3
|
import { $closest, init_utils } from "../../../editor-kernel/utils.js";
|
|
4
4
|
import { $createNodeSelection, $createParagraphNode, $getRoot, $getSelection, $isDecoratorNode, $isElementNode, $isLineBreakNode, $isNodeSelection, $isRangeSelection, $isRootOrShadowRoot, $isTextNode, $setSelection, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, FORMAT_TEXT_COMMAND, HISTORIC_TAG, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, REDO_COMMAND, UNDO_COMMAND } from "lexical";
|
|
5
|
-
import { $isHeadingNode, QuoteNode } from "@lexical/rich-text";
|
|
5
|
+
import { $isHeadingNode, $isQuoteNode, QuoteNode } from "@lexical/rich-text";
|
|
6
6
|
import { mergeRegister } from "@lexical/utils";
|
|
7
|
+
import { $isListItemNode, $isListNode } from "@lexical/list";
|
|
7
8
|
import { $isCodeHighlightNode, $isCodeNode } from "@lexical/code-core";
|
|
8
9
|
//#region src/plugins/common/plugin/register.ts
|
|
9
10
|
init_utils();
|
|
@@ -23,7 +24,9 @@ function resolveElement(element, isBackward, focusOffset) {
|
|
|
23
24
|
block = parent;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
+
const childIndex = isBackward ? offset - 1 : offset;
|
|
28
|
+
if (childIndex < 0 || childIndex >= block.getChildrenSize()) return null;
|
|
29
|
+
return block.getChildAtIndex(childIndex);
|
|
27
30
|
}
|
|
28
31
|
function isCodeNodeLastLine(focusNode) {
|
|
29
32
|
if (!$isCodeHighlightNode(focusNode)) return false;
|
|
@@ -68,7 +71,55 @@ function $isSelectionAtEndOfRoot(selection) {
|
|
|
68
71
|
const focus = selection.focus;
|
|
69
72
|
return focus.key === "root" && focus.offset === $getRoot().getChildrenSize();
|
|
70
73
|
}
|
|
71
|
-
function
|
|
74
|
+
function $isSelectionInList(selection) {
|
|
75
|
+
return Boolean($closest(selection.focus.getNode(), (node) => $isListNode(node) || $isListItemNode(node)));
|
|
76
|
+
}
|
|
77
|
+
function $getLeadingQuoteNode(selection) {
|
|
78
|
+
const anchor = selection.anchor;
|
|
79
|
+
if (anchor.offset !== 0) return false;
|
|
80
|
+
let node = anchor.getNode();
|
|
81
|
+
let current = node;
|
|
82
|
+
let quoteNode = null;
|
|
83
|
+
while (current) {
|
|
84
|
+
if ($isQuoteNode(current)) {
|
|
85
|
+
quoteNode = current;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
current = current.getParent();
|
|
89
|
+
}
|
|
90
|
+
if (!quoteNode) return false;
|
|
91
|
+
while (node !== quoteNode) {
|
|
92
|
+
if (node.getIndexWithinParent() !== 0) return false;
|
|
93
|
+
const parent = node.getParent();
|
|
94
|
+
if (!parent) return false;
|
|
95
|
+
node = parent;
|
|
96
|
+
}
|
|
97
|
+
return quoteNode;
|
|
98
|
+
}
|
|
99
|
+
function $unwrapQuoteNode(quoteNode) {
|
|
100
|
+
const children = quoteNode.getChildren();
|
|
101
|
+
if (children.length === 0) {
|
|
102
|
+
const paragraphNode = $createParagraphNode();
|
|
103
|
+
quoteNode.replace(paragraphNode);
|
|
104
|
+
paragraphNode.select(0, 0);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
let firstNode = null;
|
|
108
|
+
for (const child of children) {
|
|
109
|
+
if ($isElementNode(child)) {
|
|
110
|
+
quoteNode.insertBefore(child);
|
|
111
|
+
firstNode ||= child;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const paragraphNode = $createParagraphNode();
|
|
115
|
+
paragraphNode.append(child);
|
|
116
|
+
quoteNode.insertBefore(paragraphNode);
|
|
117
|
+
firstNode ||= paragraphNode;
|
|
118
|
+
}
|
|
119
|
+
quoteNode.remove();
|
|
120
|
+
if ($isElementNode(firstNode)) firstNode.select(0, 0);
|
|
121
|
+
}
|
|
122
|
+
function registerBlockBackspace(editor) {
|
|
72
123
|
return editor.registerCommand(KEY_BACKSPACE_COMMAND, (payload) => {
|
|
73
124
|
const headingNode = editor.getEditorState().read(() => {
|
|
74
125
|
const selection = $getSelection();
|
|
@@ -96,6 +147,22 @@ function registerHeaderBackspace(editor) {
|
|
|
96
147
|
});
|
|
97
148
|
return true;
|
|
98
149
|
}
|
|
150
|
+
if (editor.getEditorState().read(() => {
|
|
151
|
+
const selection = $getSelection();
|
|
152
|
+
if (!$isRangeSelection(selection) || !selection.isCollapsed()) return false;
|
|
153
|
+
return $getLeadingQuoteNode(selection);
|
|
154
|
+
})) {
|
|
155
|
+
payload.stopImmediatePropagation();
|
|
156
|
+
payload.preventDefault();
|
|
157
|
+
payload.stopPropagation();
|
|
158
|
+
editor.update(() => {
|
|
159
|
+
const selection = $getSelection();
|
|
160
|
+
if (!$isRangeSelection(selection) || !selection.isCollapsed()) return;
|
|
161
|
+
const leadingQuoteNode = $getLeadingQuoteNode(selection);
|
|
162
|
+
if (leadingQuoteNode) $unwrapQuoteNode(leadingQuoteNode);
|
|
163
|
+
});
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
99
166
|
return false;
|
|
100
167
|
}, COMMAND_PRIORITY_NORMAL);
|
|
101
168
|
}
|
|
@@ -150,6 +217,7 @@ function registerRichKeydown(editor, kernel, options) {
|
|
|
150
217
|
return true;
|
|
151
218
|
}
|
|
152
219
|
} else if ($isRangeSelection(selection)) {
|
|
220
|
+
if ($isSelectionInList(selection)) return false;
|
|
153
221
|
const possibleNode = $getAdjacentNode(selection.focus, true);
|
|
154
222
|
const upblock = possibleNode || $getDownUpNode(selection.focus, true);
|
|
155
223
|
if (!event.shiftKey && $isDecoratorNode(possibleNode)) {
|
|
@@ -219,6 +287,7 @@ function registerRichKeydown(editor, kernel, options) {
|
|
|
219
287
|
event.preventDefault();
|
|
220
288
|
return true;
|
|
221
289
|
}
|
|
290
|
+
if ($isSelectionInList(selection)) return false;
|
|
222
291
|
const possibleNode = $getAdjacentNode(selection.focus, false);
|
|
223
292
|
const upblock = possibleNode || $getDownUpNode(selection.focus, false);
|
|
224
293
|
if (!event.shiftKey && $isDecoratorNode(possibleNode)) {
|
|
@@ -304,4 +373,4 @@ function registerLastElement(editor) {
|
|
|
304
373
|
});
|
|
305
374
|
}
|
|
306
375
|
//#endregion
|
|
307
|
-
export { $getAdjacentNode, $getDownUpNode,
|
|
376
|
+
export { $getAdjacentNode, $getDownUpNode, registerBlockBackspace, registerLastElement, registerRichKeydown };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { $createLinkNode } from "../node/LinkNode.js";
|
|
2
|
-
import { $createTextNode, $getNodeByKey, $insertNodes, COMMAND_PRIORITY_EDITOR, createCommand } from "lexical";
|
|
1
|
+
import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from "../node/LinkNode.js";
|
|
2
|
+
import { $createRangeSelection, $createTextNode, $getNodeByKey, $getSelection, $insertNodes, $isRangeSelection, $isTextNode, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from "lexical";
|
|
3
3
|
import { mergeRegister } from "@lexical/utils";
|
|
4
4
|
//#region src/plugins/link/command/index.ts
|
|
5
5
|
const INSERT_LINK_COMMAND = createCommand("INSERT_LINK_COMMAND");
|
|
6
6
|
const UPDATE_LINK_TEXT_COMMAND = createCommand("UPDATE_LINK_TEXT_COMMAND");
|
|
7
|
+
const UNLINK_LINK_COMMAND = createCommand("UNLINK_LINK_COMMAND");
|
|
7
8
|
function registerLinkCommand(editor) {
|
|
8
9
|
return mergeRegister(editor.registerCommand(INSERT_LINK_COMMAND, (payload) => {
|
|
9
10
|
const { url, title = url } = payload;
|
|
@@ -27,7 +28,29 @@ function registerLinkCommand(editor) {
|
|
|
27
28
|
}
|
|
28
29
|
});
|
|
29
30
|
return false;
|
|
31
|
+
}, COMMAND_PRIORITY_EDITOR), editor.registerCommand(UNLINK_LINK_COMMAND, ({ key }) => {
|
|
32
|
+
editor.update(() => {
|
|
33
|
+
const node = $getNodeByKey(key);
|
|
34
|
+
if (!$isLinkNode(node)) return;
|
|
35
|
+
let selection = $getSelection();
|
|
36
|
+
if (!selection || !$isRangeSelection(selection)) {
|
|
37
|
+
$setSelection($createRangeSelection());
|
|
38
|
+
selection = $getSelection();
|
|
39
|
+
}
|
|
40
|
+
const first = node.getFirstDescendant();
|
|
41
|
+
const last = node.getLastDescendant();
|
|
42
|
+
if (selection && $isRangeSelection(selection) && $isTextNode(first) && $isTextNode(last)) {
|
|
43
|
+
selection.anchor.set(first.getKey(), 0, "text");
|
|
44
|
+
selection.focus.set(last.getKey(), last.getTextContentSize(), "text");
|
|
45
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const children = node.getChildren();
|
|
49
|
+
for (const child of children) node.insertBefore(child);
|
|
50
|
+
node.remove();
|
|
51
|
+
});
|
|
52
|
+
return true;
|
|
30
53
|
}, COMMAND_PRIORITY_EDITOR));
|
|
31
54
|
}
|
|
32
55
|
//#endregion
|
|
33
|
-
export { INSERT_LINK_COMMAND, UPDATE_LINK_TEXT_COMMAND, registerLinkCommand };
|
|
56
|
+
export { INSERT_LINK_COMMAND, UNLINK_LINK_COMMAND, UPDATE_LINK_TEXT_COMMAND, registerLinkCommand };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { getNodeTitle, getNodeUrl } from "../service/i-link-service.js";
|
|
2
|
+
import { $createLinkNode, $isLinkNode } from "../node/LinkNode.js";
|
|
3
|
+
import { $createLinkCardNode, $isLinkCardNode } from "../node/LinkCardNode.js";
|
|
4
|
+
import { $createLinkBlockCardNode, $isLinkBlockCardNode } from "../node/LinkBlockCardNode.js";
|
|
5
|
+
import { $createLinkIframeNode, $isLinkIframeNode } from "../node/LinkIframeNode.js";
|
|
6
|
+
import { $createSchemaNode, $isSchemaNode } from "../node/SchemaNode.js";
|
|
7
|
+
import { $createParagraphNode, $createTextNode, $getNodeByKey, $isParagraphNode, $isRootNode } from "lexical";
|
|
8
|
+
//#region src/plugins/link/conversion/index.ts
|
|
9
|
+
function getLinkToolbarCapabilities(node, editor, linkService) {
|
|
10
|
+
const url = getNodeUrl(node);
|
|
11
|
+
const title = getNodeTitle(node);
|
|
12
|
+
const context = createRuleContext(editor, title, title);
|
|
13
|
+
const embedRule = linkService?.getEmbedRule(url, context);
|
|
14
|
+
const schemaRule = $isLinkNode(node) && linkService?.getSchemaRule(url, {
|
|
15
|
+
...context,
|
|
16
|
+
schema: linkService.parseSchemaUrl(url)
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
canConvertToBlockCard: $isLinkNode(node) && Boolean(embedRule?.allowBlockCard) || $isLinkCardNode(node) && !$isLinkBlockCardNode(node) || $isLinkIframeNode(node),
|
|
20
|
+
canConvertToCard: $isLinkNode(node) && Boolean(embedRule?.allowCard) || $isLinkIframeNode(node) || $isLinkBlockCardNode(node),
|
|
21
|
+
canConvertToIframe: $isLinkNode(node) && Boolean(embedRule?.allowIframe) || $isLinkCardNode(node),
|
|
22
|
+
canConvertToLink: !$isLinkNode(node),
|
|
23
|
+
canConvertToSchema: $isLinkNode(node) && Boolean(schemaRule)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function convertLinkToolbarNodeToLink(node) {
|
|
27
|
+
const url = getNodeUrl(node);
|
|
28
|
+
const title = getNodeTitle(node);
|
|
29
|
+
const linkNode = $createLinkNode(url, {
|
|
30
|
+
target: $isLinkCardNode(node) ? node.getOpenTarget() : null,
|
|
31
|
+
title
|
|
32
|
+
});
|
|
33
|
+
linkNode.append($createTextNode(title));
|
|
34
|
+
replaceWithInlineNode(node, linkNode);
|
|
35
|
+
return linkNode;
|
|
36
|
+
}
|
|
37
|
+
function convertLinkToolbarNodeByKeyToLink(editor, key) {
|
|
38
|
+
let replacementKey = null;
|
|
39
|
+
editor.update(() => {
|
|
40
|
+
const node = $getNodeByKey(key);
|
|
41
|
+
if (!$isLinkToolbarNode(node)) return;
|
|
42
|
+
const linkNode = convertLinkToolbarNodeToLink(node);
|
|
43
|
+
replacementKey = linkNode.getKey();
|
|
44
|
+
linkNode.selectEnd();
|
|
45
|
+
}, { discrete: true });
|
|
46
|
+
return replacementKey;
|
|
47
|
+
}
|
|
48
|
+
function convertLinkNodeToSchema(node, editor, linkService) {
|
|
49
|
+
const url = node.getURL();
|
|
50
|
+
const title = node.getTitle() || node.getTextContent() || url;
|
|
51
|
+
const schema = linkService.parseSchemaUrl(url);
|
|
52
|
+
const rule = linkService.getSchemaRule(url, {
|
|
53
|
+
...createRuleContext(editor, node.getTextContent(), title),
|
|
54
|
+
schema
|
|
55
|
+
});
|
|
56
|
+
if (!rule) return null;
|
|
57
|
+
const parsed = rule.parse?.(url, schema);
|
|
58
|
+
const payload = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? normalizeSchemaPayload(parsed) : { payload: parsed };
|
|
59
|
+
const schemaNode = $createSchemaNode({
|
|
60
|
+
payload: payload.payload,
|
|
61
|
+
schemaType: payload.schemaType || rule.id,
|
|
62
|
+
title: payload.title || title,
|
|
63
|
+
url: payload.url || url
|
|
64
|
+
});
|
|
65
|
+
node.replace(schemaNode);
|
|
66
|
+
return schemaNode;
|
|
67
|
+
}
|
|
68
|
+
function convertLinkNodeByKeyToSchema(editor, key, linkService) {
|
|
69
|
+
editor.update(() => {
|
|
70
|
+
const node = $getNodeByKey(key);
|
|
71
|
+
if (!$isLinkNode(node)) return;
|
|
72
|
+
convertLinkNodeToSchema(node, editor, linkService)?.selectNext();
|
|
73
|
+
}, { discrete: true });
|
|
74
|
+
}
|
|
75
|
+
function replaceWithResolvedCardNode(node, payload, fallback, layout) {
|
|
76
|
+
const cardPayload = {
|
|
77
|
+
description: payload?.description,
|
|
78
|
+
icon: payload?.icon,
|
|
79
|
+
openTarget: payload?.openTarget || ($isLinkNode(node) ? node.getTarget() : $isLinkCardNode(node) ? node.getOpenTarget() : null) || "_blank",
|
|
80
|
+
title: payload?.title || fallback.title,
|
|
81
|
+
url: payload?.url || fallback.url
|
|
82
|
+
};
|
|
83
|
+
const cardNode = layout === "block" ? $createLinkBlockCardNode(cardPayload) : $createLinkCardNode(cardPayload);
|
|
84
|
+
if (layout === "block") replaceWithBlockNode(node, cardNode);
|
|
85
|
+
else replaceWithInlineNode(node, cardNode);
|
|
86
|
+
return cardNode;
|
|
87
|
+
}
|
|
88
|
+
async function replaceNodeByKeyWithCardNode(editor, key, linkService, layout = "inline") {
|
|
89
|
+
let request;
|
|
90
|
+
editor.getEditorState().read(() => {
|
|
91
|
+
const node = $getNodeByKey(key);
|
|
92
|
+
if (!$isLinkNode(node) && !$isLinkCardNode(node) && !$isLinkIframeNode(node)) return;
|
|
93
|
+
const url = getNodeUrl(node);
|
|
94
|
+
const title = getNodeTitle(node);
|
|
95
|
+
const context = createRuleContext(editor, title, title);
|
|
96
|
+
const rule = linkService.getEmbedRule(url, context);
|
|
97
|
+
let payload;
|
|
98
|
+
try {
|
|
99
|
+
payload = $isLinkCardNode(node) ? getExistingCardPayload(node) : rule?.getCardPayload?.(url, context);
|
|
100
|
+
} catch {
|
|
101
|
+
payload = void 0;
|
|
102
|
+
}
|
|
103
|
+
request = {
|
|
104
|
+
payload,
|
|
105
|
+
title,
|
|
106
|
+
url
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
if (!request) return;
|
|
110
|
+
const resolvedRequest = request;
|
|
111
|
+
let replacementKey = null;
|
|
112
|
+
const replaceCurrentNode = (payload) => {
|
|
113
|
+
const node = $getNodeByKey(key);
|
|
114
|
+
if (!$isLinkNode(node) && !$isLinkCardNode(node) && !$isLinkIframeNode(node)) return;
|
|
115
|
+
if (getNodeUrl(node) !== resolvedRequest.url) return;
|
|
116
|
+
const replacement = replaceWithResolvedCardNode(node, payload, resolvedRequest, layout);
|
|
117
|
+
replacementKey = replacement.getKey();
|
|
118
|
+
replacement.selectNext();
|
|
119
|
+
};
|
|
120
|
+
const initialPayload = resolvedRequest.payload;
|
|
121
|
+
if (!isPromiseLike(initialPayload)) {
|
|
122
|
+
editor.update(() => replaceCurrentNode(initialPayload), { discrete: true });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
editor.update(() => replaceCurrentNode(void 0), { discrete: true });
|
|
126
|
+
if (!replacementKey) return;
|
|
127
|
+
const cardKey = replacementKey;
|
|
128
|
+
linkService.setCardMetadataLoading(cardKey, true);
|
|
129
|
+
try {
|
|
130
|
+
const resolvedPayload = await initialPayload;
|
|
131
|
+
if (!resolvedPayload) return;
|
|
132
|
+
editor.update(() => {
|
|
133
|
+
const cardNode = $getNodeByKey(cardKey);
|
|
134
|
+
if (!$isLinkCardNode(cardNode) || getNodeUrl(cardNode) !== resolvedRequest.url) return;
|
|
135
|
+
cardNode.setURL(resolvedPayload.url || resolvedRequest.url).setTitle(resolvedPayload.title || resolvedRequest.title).setIcon(resolvedPayload.icon).setDescription(resolvedPayload.description).setOpenTarget(resolvedPayload.openTarget || cardNode.getOpenTarget() || "_blank");
|
|
136
|
+
}, { discrete: true });
|
|
137
|
+
} catch {
|
|
138
|
+
return;
|
|
139
|
+
} finally {
|
|
140
|
+
linkService.setCardMetadataLoading(cardKey, false);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function replaceNodeByKeyWithBlockCardNode(editor, key, linkService) {
|
|
144
|
+
return replaceNodeByKeyWithCardNode(editor, key, linkService, "block");
|
|
145
|
+
}
|
|
146
|
+
function replaceWithIframeNode(node, editor, linkService) {
|
|
147
|
+
const url = getNodeUrl(node);
|
|
148
|
+
const title = getNodeTitle(node);
|
|
149
|
+
const context = createRuleContext(editor, title, title);
|
|
150
|
+
const payload = linkService.getEmbedRule(url, context)?.getIframePayload?.(url, context);
|
|
151
|
+
const iframeNode = $createLinkIframeNode({
|
|
152
|
+
src: payload?.src || url,
|
|
153
|
+
title: payload?.title || title,
|
|
154
|
+
url: payload?.url || url
|
|
155
|
+
});
|
|
156
|
+
replaceWithBlockIframeNode(node, iframeNode);
|
|
157
|
+
return iframeNode;
|
|
158
|
+
}
|
|
159
|
+
function replaceNodeByKeyWithIframeNode(editor, key, linkService) {
|
|
160
|
+
editor.update(() => {
|
|
161
|
+
const node = $getNodeByKey(key);
|
|
162
|
+
if (!$isLinkNode(node) && !$isLinkCardNode(node)) return;
|
|
163
|
+
replaceWithIframeNode(node, editor, linkService).selectNext();
|
|
164
|
+
}, { discrete: true });
|
|
165
|
+
}
|
|
166
|
+
function replaceWithInlineNode(node, inlineNode) {
|
|
167
|
+
if (node.isInline()) {
|
|
168
|
+
node.replace(inlineNode);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const paragraph = $createParagraphNode();
|
|
172
|
+
paragraph.append(inlineNode);
|
|
173
|
+
node.replace(paragraph);
|
|
174
|
+
}
|
|
175
|
+
function replaceWithBlockIframeNode(node, iframeNode) {
|
|
176
|
+
replaceWithBlockNode(node, iframeNode);
|
|
177
|
+
}
|
|
178
|
+
function replaceWithBlockNode(node, blockNode) {
|
|
179
|
+
const parent = node.getParent();
|
|
180
|
+
if (parent && !$isRootNode(parent) && !parent.isInline() && parent.getChildrenSize() === 1) {
|
|
181
|
+
parent.replace(blockNode);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (parent && $isParagraphNode(parent)) {
|
|
185
|
+
const previousSiblings = node.getPreviousSiblings();
|
|
186
|
+
const nextSiblings = node.getNextSiblings();
|
|
187
|
+
if (previousSiblings.length === 0) {
|
|
188
|
+
parent.insertBefore(blockNode);
|
|
189
|
+
node.remove();
|
|
190
|
+
if (parent.getChildrenSize() === 0) parent.remove();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (nextSiblings.length === 0) {
|
|
194
|
+
parent.insertAfter(blockNode);
|
|
195
|
+
node.remove();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const nextParagraph = $createParagraphNode();
|
|
199
|
+
nextParagraph.setFormat(parent.getFormatType());
|
|
200
|
+
nextParagraph.setIndent(parent.getIndent());
|
|
201
|
+
nextParagraph.setDirection(parent.getDirection());
|
|
202
|
+
nextParagraph.append(...nextSiblings);
|
|
203
|
+
parent.insertAfter(blockNode);
|
|
204
|
+
blockNode.insertAfter(nextParagraph);
|
|
205
|
+
node.remove();
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
node.replace(blockNode);
|
|
209
|
+
}
|
|
210
|
+
function $isLinkToolbarNode(node) {
|
|
211
|
+
return $isLinkNode(node) || $isLinkCardNode(node) || $isLinkIframeNode(node) || $isSchemaNode(node);
|
|
212
|
+
}
|
|
213
|
+
function createRuleContext(editor, text, title) {
|
|
214
|
+
return {
|
|
215
|
+
editor,
|
|
216
|
+
text,
|
|
217
|
+
title
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function isPromiseLike(value) {
|
|
221
|
+
return Boolean(value && typeof value.then === "function");
|
|
222
|
+
}
|
|
223
|
+
function getExistingCardPayload(node) {
|
|
224
|
+
return {
|
|
225
|
+
description: node.getDescription(),
|
|
226
|
+
icon: node.getIcon(),
|
|
227
|
+
openTarget: node.getOpenTarget(),
|
|
228
|
+
title: node.getTitle(),
|
|
229
|
+
url: node.getURL()
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function normalizeSchemaPayload(payload) {
|
|
233
|
+
if ("payload" in payload || "schemaType" in payload || "title" in payload || "url" in payload) return payload;
|
|
234
|
+
return { payload };
|
|
235
|
+
}
|
|
236
|
+
//#endregion
|
|
237
|
+
export { $isLinkToolbarNode, convertLinkNodeByKeyToSchema, convertLinkNodeToSchema, convertLinkToolbarNodeByKeyToLink, convertLinkToolbarNodeToLink, getLinkToolbarCapabilities, replaceNodeByKeyWithBlockCardNode, replaceNodeByKeyWithCardNode, replaceNodeByKeyWithIframeNode, replaceWithBlockIframeNode, replaceWithBlockNode, replaceWithIframeNode, replaceWithInlineNode };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { INSERT_LINK_COMMAND } from "./command/index.js";
|
|
2
|
+
import { ILinkService, LinkEmbedRule, LinkLabels, LinkToolbarAction, LinkToolbarItem, LinkToolbarItemIcon, LinkToolbarRenderContext, ParsedSchemaUrl, SchemaRule, getNodeTitle, getNodeUrl, normalizeProtocol } from "./service/i-link-service.js";
|
|
3
|
+
import { normalizeSchemaLinkNode } from "./normalization/index.js";
|
|
2
4
|
import { LinkPlugin, LinkPluginOptions } from "./plugin/index.js";
|
|
3
|
-
import {
|
|
5
|
+
import { LinkCardRenderer, LinkCardRendererProps, LinkIframeRenderer, LinkIframeRendererProps, ReactSchemaRule, SchemaLinkRenderer, SchemaLinkRendererConfig, SchemaLinkRendererProps, SchemaRenderer, SchemaRendererProps } from "./react/renderer-registry.js";
|
|
6
|
+
import { ReactLinkDefaultToolbarItemKey, ReactLinkDefaultToolbarItems, ReactLinkPluginProps } from "./react/type.js";
|
|
4
7
|
import { ReactLinkPlugin } from "./react/ReactLinkPlugin.js";
|
|
5
8
|
import "./react/index.js";
|
|
6
|
-
|
|
7
|
-
export { ILinkService, INSERT_LINK_COMMAND, LinkPlugin, LinkPluginOptions, ReactLinkPlugin, type ReactLinkPluginProps };
|
|
9
|
+
export { ILinkService, INSERT_LINK_COMMAND, type LinkCardRenderer, type LinkCardRendererProps, type LinkEmbedRule, type LinkIframeRenderer, type LinkIframeRendererProps, type LinkLabels, LinkPlugin, LinkPluginOptions, type LinkToolbarAction, type LinkToolbarItem, type LinkToolbarItemIcon, type LinkToolbarRenderContext, type ParsedSchemaUrl, type ReactLinkDefaultToolbarItemKey, type ReactLinkDefaultToolbarItems, ReactLinkPlugin, type ReactLinkPluginProps, type ReactSchemaRule, type SchemaLinkRenderer, type SchemaLinkRendererConfig, type SchemaLinkRendererProps, type SchemaRenderer, type SchemaRendererProps, type SchemaRule, getNodeTitle, getNodeUrl, normalizeProtocol, normalizeSchemaLinkNode };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LinkCardNode, SerializedLinkCardNode } from "./LinkCardNode.js";
|
|
2
|
+
import { DOMConversionMap, DOMExportOutput, EditorConfig, LexicalEditor, LexicalNode, LexicalUpdateJSON, NodeKey } from "lexical";
|
|
3
|
+
//#region src/plugins/link/node/LinkBlockCardNode.d.ts
|
|
4
|
+
declare class LinkBlockCardNode extends LinkCardNode {
|
|
5
|
+
static getType(): string;
|
|
6
|
+
static clone(node: LinkBlockCardNode): LinkBlockCardNode;
|
|
7
|
+
static importJSON(serializedNode: SerializedLinkCardNode): LinkBlockCardNode;
|
|
8
|
+
static importDOM(): DOMConversionMap | null;
|
|
9
|
+
constructor(url: string, title?: string, icon?: string, description?: string, openTarget?: null | string, key?: NodeKey);
|
|
10
|
+
createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement;
|
|
11
|
+
exportDOM(): DOMExportOutput;
|
|
12
|
+
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedLinkCardNode>): this;
|
|
13
|
+
isInline(): false;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { LinkBlockCardNode };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { LinkCardNode } from "./LinkCardNode.js";
|
|
2
|
+
import { $applyNodeReplacement } from "lexical";
|
|
3
|
+
//#region src/plugins/link/node/LinkBlockCardNode.ts
|
|
4
|
+
var LinkBlockCardNode = class LinkBlockCardNode extends LinkCardNode {
|
|
5
|
+
static getType() {
|
|
6
|
+
return "link-block-card";
|
|
7
|
+
}
|
|
8
|
+
static clone(node) {
|
|
9
|
+
return new LinkBlockCardNode(node.__url, node.__title, node.__icon, node.__description, node.__openTarget, node.__key);
|
|
10
|
+
}
|
|
11
|
+
static importJSON(serializedNode) {
|
|
12
|
+
return $createLinkBlockCardNode({
|
|
13
|
+
description: serializedNode.description,
|
|
14
|
+
icon: serializedNode.icon,
|
|
15
|
+
openTarget: serializedNode.openTarget,
|
|
16
|
+
title: serializedNode.title,
|
|
17
|
+
url: serializedNode.url
|
|
18
|
+
}).updateFromJSON(serializedNode);
|
|
19
|
+
}
|
|
20
|
+
static importDOM() {
|
|
21
|
+
return { a: (node) => {
|
|
22
|
+
if (node instanceof HTMLAnchorElement && node.dataset.linkCard === "true" && node.dataset.linkCardLayout === "block") return {
|
|
23
|
+
conversion: $convertLinkBlockCardElement,
|
|
24
|
+
priority: 3
|
|
25
|
+
};
|
|
26
|
+
return null;
|
|
27
|
+
} };
|
|
28
|
+
}
|
|
29
|
+
constructor(url, title, icon, description, openTarget, key) {
|
|
30
|
+
super(url, title, icon, description, openTarget, key);
|
|
31
|
+
}
|
|
32
|
+
createDOM(config, editor) {
|
|
33
|
+
const element = super.createDOM(config, editor);
|
|
34
|
+
element.dataset.linkCardLayout = "block";
|
|
35
|
+
return element;
|
|
36
|
+
}
|
|
37
|
+
exportDOM() {
|
|
38
|
+
const output = super.exportDOM();
|
|
39
|
+
if (output.element instanceof HTMLElement) output.element.dataset.linkCardLayout = "block";
|
|
40
|
+
return output;
|
|
41
|
+
}
|
|
42
|
+
updateFromJSON(serializedNode) {
|
|
43
|
+
return super.updateFromJSON(serializedNode);
|
|
44
|
+
}
|
|
45
|
+
isInline() {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function $createLinkBlockCardNode(payload) {
|
|
50
|
+
return $applyNodeReplacement(new LinkBlockCardNode(payload.url, payload.title, payload.icon, payload.description, payload.openTarget));
|
|
51
|
+
}
|
|
52
|
+
function $convertLinkBlockCardElement(domNode) {
|
|
53
|
+
const element = domNode;
|
|
54
|
+
return { node: $createLinkBlockCardNode({
|
|
55
|
+
description: element.dataset.description,
|
|
56
|
+
icon: element.dataset.icon,
|
|
57
|
+
openTarget: element.getAttribute("target"),
|
|
58
|
+
title: element.textContent || element.href,
|
|
59
|
+
url: element.getAttribute("href") || ""
|
|
60
|
+
}) };
|
|
61
|
+
}
|
|
62
|
+
function $isLinkBlockCardNode(node) {
|
|
63
|
+
return node instanceof LinkBlockCardNode || node?.getType?.() === LinkBlockCardNode.getType();
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { $createLinkBlockCardNode, $isLinkBlockCardNode, LinkBlockCardNode };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DOMConversionMap, DOMExportOutput, DecoratorNode, EditorConfig, LexicalEditor, LexicalNode, LexicalUpdateJSON, NodeKey, SerializedLexicalNode, Spread } from "lexical";
|
|
2
|
+
//#region src/plugins/link/node/LinkCardNode.d.ts
|
|
3
|
+
type SerializedLinkCardNode = Spread<{
|
|
4
|
+
description: string;
|
|
5
|
+
icon: string;
|
|
6
|
+
openTarget: null | string;
|
|
7
|
+
title: string;
|
|
8
|
+
url: string;
|
|
9
|
+
}, SerializedLexicalNode>;
|
|
10
|
+
declare class LinkCardNode extends DecoratorNode<unknown> {
|
|
11
|
+
__url: string;
|
|
12
|
+
__title: string;
|
|
13
|
+
__icon: string;
|
|
14
|
+
__description: string;
|
|
15
|
+
__openTarget: null | string;
|
|
16
|
+
static getType(): string;
|
|
17
|
+
static clone(node: LinkCardNode): LinkCardNode;
|
|
18
|
+
static importJSON(serializedNode: SerializedLinkCardNode): LinkCardNode;
|
|
19
|
+
static importDOM(): DOMConversionMap | null;
|
|
20
|
+
constructor(url: string, title?: string, icon?: string, description?: string, openTarget?: null | string, key?: NodeKey);
|
|
21
|
+
createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement;
|
|
22
|
+
updateDOM(): false;
|
|
23
|
+
isInline(): boolean;
|
|
24
|
+
isKeyboardSelectable(): true;
|
|
25
|
+
exportDOM(): DOMExportOutput;
|
|
26
|
+
exportJSON(): SerializedLinkCardNode;
|
|
27
|
+
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedLinkCardNode>): this;
|
|
28
|
+
getTextContent(): string;
|
|
29
|
+
getURL(): string;
|
|
30
|
+
setURL(url: string): this;
|
|
31
|
+
getTitle(): string;
|
|
32
|
+
setTitle(title?: string): this;
|
|
33
|
+
getIcon(): string;
|
|
34
|
+
setIcon(icon?: string): this;
|
|
35
|
+
getDescription(): string;
|
|
36
|
+
setDescription(description?: string): this;
|
|
37
|
+
getOpenTarget(): null | string;
|
|
38
|
+
setOpenTarget(openTarget?: null | string): this;
|
|
39
|
+
decorate(editor: LexicalEditor): unknown;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { LinkCardNode, SerializedLinkCardNode };
|