@37signals/lexxy 0.1.16-beta → 0.1.18-beta
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/lexxy.esm.js +53 -14
- package/package.json +1 -1
package/dist/lexxy.esm.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import DOMPurify from 'dompurify';
|
|
2
|
-
import { $getSelection, $isRangeSelection, DecoratorNode, $getNodeByKey, HISTORY_MERGE_TAG, FORMAT_TEXT_COMMAND, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, COMMAND_PRIORITY_LOW, $isNodeSelection, $getRoot, $isLineBreakNode, $isTextNode, $isElementNode, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, SELECTION_CHANGE_COMMAND, $createNodeSelection, $setSelection, $createParagraphNode,
|
|
2
|
+
import { $getSelection, $isRangeSelection, DecoratorNode, $getNodeByKey, HISTORY_MERGE_TAG, FORMAT_TEXT_COMMAND, $createTextNode, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, COMMAND_PRIORITY_LOW, $isNodeSelection, $getRoot, $isLineBreakNode, $isTextNode, $isElementNode, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, SELECTION_CHANGE_COMMAND, $createNodeSelection, $setSelection, $createParagraphNode, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH, $isParagraphNode, $insertNodes, $createLineBreakNode, CLEAR_HISTORY_COMMAND, $addUpdateTag, SKIP_DOM_SELECTION_TAG, createEditor, COMMAND_PRIORITY_NORMAL, KEY_TAB_COMMAND, KEY_SPACE_COMMAND } from 'lexical';
|
|
3
3
|
import { $isListNode, $isListItemNode, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $createListNode, ListNode, ListItemNode, registerList } from '@lexical/list';
|
|
4
4
|
import { $isQuoteNode, $isHeadingNode, $createQuoteNode, $createHeadingNode, QuoteNode, HeadingNode, registerRichText } from '@lexical/rich-text';
|
|
5
5
|
import { $isCodeNode, CodeNode, CodeHighlightNode, registerCodeHighlighting, CODE_LANGUAGE_FRIENDLY_NAME_MAP, normalizeCodeLang } from '@lexical/code';
|
|
6
|
-
import { $isLinkNode, $toggleLink, $createLinkNode, LinkNode, AutoLinkNode } from '@lexical/link';
|
|
6
|
+
import { $isLinkNode, $createAutoLinkNode, $toggleLink, $createLinkNode, LinkNode, AutoLinkNode } from '@lexical/link';
|
|
7
7
|
import { $generateNodesFromDOM, $generateHtmlFromNodes } from '@lexical/html';
|
|
8
8
|
import { registerMarkdownShortcuts, TRANSFORMERS } from '@lexical/markdown';
|
|
9
9
|
import { createEmptyHistoryState, registerHistory } from '@lexical/history';
|
|
@@ -1019,7 +1019,19 @@ class CommandDispatcher {
|
|
|
1019
1019
|
}
|
|
1020
1020
|
|
|
1021
1021
|
dispatchLink(url) {
|
|
1022
|
-
this
|
|
1022
|
+
this.editor.update(() => {
|
|
1023
|
+
const selection = $getSelection();
|
|
1024
|
+
if (!$isRangeSelection(selection)) return
|
|
1025
|
+
|
|
1026
|
+
if (selection.isCollapsed()) {
|
|
1027
|
+
const autoLinkNode = $createAutoLinkNode(url);
|
|
1028
|
+
const textNode = $createTextNode(url);
|
|
1029
|
+
autoLinkNode.append(textNode);
|
|
1030
|
+
selection.insertNodes([ autoLinkNode ]);
|
|
1031
|
+
} else {
|
|
1032
|
+
$toggleLink(url);
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1023
1035
|
}
|
|
1024
1036
|
|
|
1025
1037
|
dispatchUnlink() {
|
|
@@ -1940,6 +1952,8 @@ class FormatEscaper {
|
|
|
1940
1952
|
|
|
1941
1953
|
const anchorNode = selection.anchor.getNode();
|
|
1942
1954
|
|
|
1955
|
+
if (!this.#isInsideBlockquote(anchorNode)) return false
|
|
1956
|
+
|
|
1943
1957
|
return this.#handleLists(event, anchorNode)
|
|
1944
1958
|
|| this.#handleBlockquotes(event, anchorNode)
|
|
1945
1959
|
}
|
|
@@ -1964,6 +1978,19 @@ class FormatEscaper {
|
|
|
1964
1978
|
return false
|
|
1965
1979
|
}
|
|
1966
1980
|
|
|
1981
|
+
#isInsideBlockquote(node) {
|
|
1982
|
+
let currentNode = node;
|
|
1983
|
+
|
|
1984
|
+
while (currentNode) {
|
|
1985
|
+
if ($isQuoteNode(currentNode)) {
|
|
1986
|
+
return true
|
|
1987
|
+
}
|
|
1988
|
+
currentNode = currentNode.getParent();
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
return false
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1967
1994
|
#shouldEscapeFromEmptyListItem(node) {
|
|
1968
1995
|
const listItem = this.#getListItemNode(node);
|
|
1969
1996
|
if (!listItem) return false
|
|
@@ -2261,10 +2288,10 @@ class Contents {
|
|
|
2261
2288
|
const selection = $getSelection();
|
|
2262
2289
|
if (!$isRangeSelection(selection)) return
|
|
2263
2290
|
|
|
2264
|
-
const topLevelElement = selection.anchor.getNode().
|
|
2291
|
+
const topLevelElement = selection.anchor.getNode().getTopLevelElement();
|
|
2265
2292
|
|
|
2266
2293
|
// Check if format is already applied
|
|
2267
|
-
if (isFormatAppliedFn(topLevelElement)) {
|
|
2294
|
+
if (topLevelElement && isFormatAppliedFn(topLevelElement)) {
|
|
2268
2295
|
this.#unwrap(topLevelElement);
|
|
2269
2296
|
} else {
|
|
2270
2297
|
this.#insertNodeWrappingAllSelectedNodes(newNodeFn);
|
|
@@ -2494,10 +2521,7 @@ class Contents {
|
|
|
2494
2521
|
const node = $getNodeByKey(nodeKey);
|
|
2495
2522
|
if (!node) return
|
|
2496
2523
|
|
|
2497
|
-
|
|
2498
|
-
try {
|
|
2499
|
-
previousNode = node.getTopLevelElementOrThrow();
|
|
2500
|
-
} catch {}
|
|
2524
|
+
const previousNode = node.getTopLevelElement() || node;
|
|
2501
2525
|
|
|
2502
2526
|
const newNode = options.attachment ? this.#createCustomAttachmentNodeWithHtml(html, options.attachment) : this.#createHtmlNodeWith(html);
|
|
2503
2527
|
previousNode.insertAfter(newNode);
|
|
@@ -2524,16 +2548,21 @@ class Contents {
|
|
|
2524
2548
|
if (!$isRangeSelection(selection)) return
|
|
2525
2549
|
|
|
2526
2550
|
const selectedNodes = selection.extract();
|
|
2527
|
-
if (selectedNodes.length === 0)
|
|
2528
|
-
|
|
2551
|
+
if (selectedNodes.length === 0) {
|
|
2552
|
+
return
|
|
2553
|
+
}
|
|
2529
2554
|
const topLevelElements = new Set();
|
|
2530
2555
|
selectedNodes.forEach((node) => {
|
|
2531
2556
|
const topLevel = node.getTopLevelElementOrThrow();
|
|
2532
2557
|
topLevelElements.add(topLevel);
|
|
2533
2558
|
});
|
|
2534
2559
|
|
|
2535
|
-
const elements = this.#
|
|
2536
|
-
if (elements.length === 0)
|
|
2560
|
+
const elements = this.#withoutTrailingEmptyParagraphs(Array.from(topLevelElements));
|
|
2561
|
+
if (elements.length === 0) {
|
|
2562
|
+
this.#removeStandaloneEmptyParagraph();
|
|
2563
|
+
this.insertAtCursor(newNodeFn());
|
|
2564
|
+
return
|
|
2565
|
+
}
|
|
2537
2566
|
|
|
2538
2567
|
const wrappingNode = newNodeFn();
|
|
2539
2568
|
elements[0].insertBefore(wrappingNode);
|
|
@@ -2545,7 +2574,7 @@ class Contents {
|
|
|
2545
2574
|
});
|
|
2546
2575
|
}
|
|
2547
2576
|
|
|
2548
|
-
#
|
|
2577
|
+
#withoutTrailingEmptyParagraphs(elements) {
|
|
2549
2578
|
let lastNonEmptyIndex = elements.length - 1;
|
|
2550
2579
|
|
|
2551
2580
|
// Find the last non-empty paragraph
|
|
@@ -2569,6 +2598,16 @@ class Contents {
|
|
|
2569
2598
|
return children.length === 0 || children.every(child => $isLineBreakNode(child))
|
|
2570
2599
|
}
|
|
2571
2600
|
|
|
2601
|
+
#removeStandaloneEmptyParagraph() {
|
|
2602
|
+
const root = $getRoot();
|
|
2603
|
+
if (root.getChildrenSize() === 1) {
|
|
2604
|
+
const firstChild = root.getFirstChild();
|
|
2605
|
+
if (firstChild && $isParagraphNode(firstChild) && this.#isElementEmpty(firstChild)) {
|
|
2606
|
+
firstChild.remove();
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2572
2611
|
#insertNodeWrappingAllSelectedLines(newNodeFn) {
|
|
2573
2612
|
this.editor.update(() => {
|
|
2574
2613
|
const selection = $getSelection();
|