@37signals/lexxy 0.9.1-beta → 0.9.2-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 +195 -102
- package/package.json +1 -1
package/dist/lexxy.esm.js
CHANGED
|
@@ -10,7 +10,7 @@ import 'prismjs/components/prism-json';
|
|
|
10
10
|
import 'prismjs/components/prism-diff';
|
|
11
11
|
import DOMPurify from 'dompurify';
|
|
12
12
|
import { getStyleObjectFromCSS, getCSSFromStyleObject, $isAtNodeEnd, $getSelectionStyleValueForProperty, $patchStyleText, $setBlocksType } from '@lexical/selection';
|
|
13
|
-
import { SKIP_DOM_SELECTION_TAG, $getSelection, $isRangeSelection, $getNodeByKey, $isTextNode, $createRangeSelection, $setSelection, DecoratorNode, $createTextNode, $createNodeSelection, $isDecoratorNode, $isLineBreakNode, $isElementNode, HISTORY_MERGE_TAG, SKIP_SCROLL_INTO_VIEW_TAG, $createParagraphNode, TextNode, createCommand, createState, defineExtension, COMMAND_PRIORITY_NORMAL, $getState, $setState, $hasUpdateTag, PASTE_TAG, FORMAT_TEXT_COMMAND, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, COMMAND_PRIORITY_LOW, KEY_ARROW_RIGHT_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $getEditor, $getNearestRootOrShadowRoot, $isNodeSelection, $getRoot, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, DELETE_CHARACTER_COMMAND, SELECTION_CHANGE_COMMAND, CLICK_COMMAND, isDOMNode, $getNearestNodeFromDOMNode, $isRootOrShadowRoot, ElementNode, $splitNode, $isParagraphNode, $createLineBreakNode, $isRootNode, ParagraphNode, RootNode, COMMAND_PRIORITY_HIGH, DRAGSTART_COMMAND, DROP_COMMAND, INSERT_PARAGRAPH_COMMAND, CLEAR_HISTORY_COMMAND, $addUpdateTag, KEY_ENTER_COMMAND, COMMAND_PRIORITY_CRITICAL, KEY_SPACE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND } from 'lexical';
|
|
13
|
+
import { SKIP_DOM_SELECTION_TAG, $getSelection, $isRangeSelection, $getNodeByKey, $isTextNode, $createRangeSelection, $setSelection, DecoratorNode, $createTextNode, $createNodeSelection, $isDecoratorNode, $isLineBreakNode, $isElementNode, HISTORY_MERGE_TAG, SKIP_SCROLL_INTO_VIEW_TAG, $createParagraphNode, TextNode, createCommand, createState, defineExtension, COMMAND_PRIORITY_NORMAL, $getState, $setState, $hasUpdateTag, PASTE_TAG, FORMAT_TEXT_COMMAND, UNDO_COMMAND, REDO_COMMAND, PASTE_COMMAND, COMMAND_PRIORITY_LOW, KEY_ARROW_RIGHT_COMMAND, KEY_TAB_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $getEditor, $getNearestRootOrShadowRoot, $isNodeSelection, $getRoot, mergeRegister as mergeRegister$1, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_DOWN_COMMAND, DELETE_CHARACTER_COMMAND, SELECTION_CHANGE_COMMAND, CLICK_COMMAND, isDOMNode, $getNearestNodeFromDOMNode, $isRootOrShadowRoot, ElementNode, $splitNode, $isParagraphNode, $createLineBreakNode, $isRootNode, ParagraphNode, RootNode, COMMAND_PRIORITY_HIGH, DRAGSTART_COMMAND, DROP_COMMAND, INSERT_PARAGRAPH_COMMAND, CLEAR_HISTORY_COMMAND, $addUpdateTag, KEY_ENTER_COMMAND, COMMAND_PRIORITY_CRITICAL, KEY_SPACE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DOWN_COMMAND } from 'lexical';
|
|
14
14
|
import { buildEditorFromExtensions } from '@lexical/extension';
|
|
15
15
|
import { ListNode, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, ListItemNode, $getListDepth, $isListItemNode, $isListNode, registerList } from '@lexical/list';
|
|
16
16
|
import { $createAutoLinkNode, $toggleLink, LinkNode, $createLinkNode, AutoLinkNode, $isLinkNode } from '@lexical/link';
|
|
@@ -22,7 +22,7 @@ import { registerMarkdownShortcuts, TRANSFORMERS } from '@lexical/markdown';
|
|
|
22
22
|
import { createEmptyHistoryState, registerHistory } from '@lexical/history';
|
|
23
23
|
import { createElement, extractPlainTextFromHtml, createAttachmentFigure, isPreviewableImage, dispatch, parseHtml, addBlockSpacing, generateDomId } from './lexxy_helpers.esm.js';
|
|
24
24
|
export { highlightCode as highlightAll, highlightCode } from './lexxy_helpers.esm.js';
|
|
25
|
-
import { INSERT_TABLE_COMMAND, $getTableCellNodeFromLexicalNode, TableCellNode, TableNode, TableRowNode, registerTablePlugin, registerTableSelectionObserver,
|
|
25
|
+
import { INSERT_TABLE_COMMAND, $getTableCellNodeFromLexicalNode, TableCellNode, TableNode, TableRowNode, setScrollableTablesActive, registerTablePlugin, registerTableSelectionObserver, TableCellHeaderStates, $insertTableRowAtSelection, $insertTableColumnAtSelection, $deleteTableRowAtSelection, $deleteTableColumnAtSelection, $findTableNode, $getTableRowIndexFromTableCellNode, $getTableColumnIndexFromTableCellNode, $findCellNode, $getElementForTableNode } from '@lexical/table';
|
|
26
26
|
import { $getNearestNodeOfType, $wrapNodeInElement, $lastToFirstIterator, mergeRegister, $insertFirst, $unwrapAndFilterDescendants, $firstToLastIterator, $descendantsMatching } from '@lexical/utils';
|
|
27
27
|
import { marked } from 'marked';
|
|
28
28
|
import { $insertDataTransferForRichText } from '@lexical/clipboard';
|
|
@@ -382,9 +382,22 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
disconnectedCallback() {
|
|
385
|
+
this.dispose();
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
dispose() {
|
|
385
389
|
this.#uninstallResizeObserver();
|
|
390
|
+
this.#unbindButtons();
|
|
386
391
|
this.#unbindHotkeys();
|
|
387
392
|
this.#unbindFocusListeners();
|
|
393
|
+
this.unregisterSelectionListener?.();
|
|
394
|
+
this.unregisterHistoryListener?.();
|
|
395
|
+
|
|
396
|
+
this.editorElement = null;
|
|
397
|
+
this.editor = null;
|
|
398
|
+
this.selection = null;
|
|
399
|
+
|
|
400
|
+
this.#createEditorPromise();
|
|
388
401
|
}
|
|
389
402
|
|
|
390
403
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -428,10 +441,12 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
428
441
|
this.connectedCallback();
|
|
429
442
|
}
|
|
430
443
|
|
|
431
|
-
#createEditorPromise() {
|
|
444
|
+
async #createEditorPromise() {
|
|
432
445
|
this.editorPromise = new Promise((resolve) => {
|
|
433
446
|
this.resolveEditorPromise = resolve;
|
|
434
447
|
});
|
|
448
|
+
|
|
449
|
+
this.editorElement = await this.editorPromise;
|
|
435
450
|
}
|
|
436
451
|
|
|
437
452
|
#installResizeObserver() {
|
|
@@ -447,10 +462,14 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
447
462
|
}
|
|
448
463
|
|
|
449
464
|
#bindButtons() {
|
|
450
|
-
this.addEventListener("click", this.#handleButtonClicked
|
|
465
|
+
this.addEventListener("click", this.#handleButtonClicked);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
#unbindButtons() {
|
|
469
|
+
this.removeEventListener("click", this.#handleButtonClicked);
|
|
451
470
|
}
|
|
452
471
|
|
|
453
|
-
#handleButtonClicked(event) {
|
|
472
|
+
#handleButtonClicked = (event) => {
|
|
454
473
|
this.#handleTargetClicked(event, "[data-command]", this.#dispatchButtonCommand.bind(this));
|
|
455
474
|
}
|
|
456
475
|
|
|
@@ -510,8 +529,8 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
510
529
|
}
|
|
511
530
|
|
|
512
531
|
#unbindFocusListeners() {
|
|
513
|
-
this.editorElement
|
|
514
|
-
this.editorElement
|
|
532
|
+
this.editorElement?.removeEventListener("lexxy:focus", this.#handleEditorFocus);
|
|
533
|
+
this.editorElement?.removeEventListener("lexxy:blur", this.#handleEditorBlur);
|
|
515
534
|
this.removeEventListener("keydown", this.#handleKeydown);
|
|
516
535
|
}
|
|
517
536
|
|
|
@@ -535,7 +554,7 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
535
554
|
}
|
|
536
555
|
|
|
537
556
|
#monitorSelectionChanges() {
|
|
538
|
-
this.editor.registerUpdateListener(() => {
|
|
557
|
+
this.unregisterSelectionListener = this.editor.registerUpdateListener(() => {
|
|
539
558
|
this.editor.getEditorState().read(() => {
|
|
540
559
|
this.#updateButtonStates();
|
|
541
560
|
this.#closeDropdowns();
|
|
@@ -544,7 +563,7 @@ class LexicalToolbarElement extends HTMLElement {
|
|
|
544
563
|
}
|
|
545
564
|
|
|
546
565
|
#monitorHistoryChanges() {
|
|
547
|
-
this.editor.registerUpdateListener(() => {
|
|
566
|
+
this.unregisterHistoryListener = this.editor.registerUpdateListener(() => {
|
|
548
567
|
this.#updateUndoRedoButtonStates();
|
|
549
568
|
});
|
|
550
569
|
}
|
|
@@ -1964,9 +1983,10 @@ const COMMANDS = [
|
|
|
1964
1983
|
|
|
1965
1984
|
class CommandDispatcher {
|
|
1966
1985
|
#selectionBeforeDrag = null
|
|
1986
|
+
#unregister = []
|
|
1967
1987
|
|
|
1968
1988
|
static configureFor(editorElement) {
|
|
1969
|
-
new CommandDispatcher(editorElement)
|
|
1989
|
+
return new CommandDispatcher(editorElement)
|
|
1970
1990
|
}
|
|
1971
1991
|
|
|
1972
1992
|
constructor(editorElement) {
|
|
@@ -2178,6 +2198,13 @@ class CommandDispatcher {
|
|
|
2178
2198
|
this.editor.dispatchCommand(REDO_COMMAND, undefined);
|
|
2179
2199
|
}
|
|
2180
2200
|
|
|
2201
|
+
dispose() {
|
|
2202
|
+
while (this.#unregister.length) {
|
|
2203
|
+
const unregister = this.#unregister.pop();
|
|
2204
|
+
unregister();
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2181
2208
|
#registerCommands() {
|
|
2182
2209
|
for (const command of COMMANDS) {
|
|
2183
2210
|
const methodName = `dispatch${capitalize(command)}`;
|
|
@@ -2188,12 +2215,12 @@ class CommandDispatcher {
|
|
|
2188
2215
|
}
|
|
2189
2216
|
|
|
2190
2217
|
#registerCommandHandler(command, priority, handler) {
|
|
2191
|
-
this.editor.registerCommand(command, handler, priority);
|
|
2218
|
+
this.#unregister.push(this.editor.registerCommand(command, handler, priority));
|
|
2192
2219
|
}
|
|
2193
2220
|
|
|
2194
2221
|
#registerKeyboardCommands() {
|
|
2195
|
-
this
|
|
2196
|
-
this
|
|
2222
|
+
this.#registerCommandHandler(KEY_ARROW_RIGHT_COMMAND, COMMAND_PRIORITY_NORMAL, this.#handleArrowRightKey.bind(this));
|
|
2223
|
+
this.#registerCommandHandler(KEY_TAB_COMMAND, COMMAND_PRIORITY_NORMAL, this.#handleTabKey.bind(this));
|
|
2197
2224
|
}
|
|
2198
2225
|
|
|
2199
2226
|
#handleArrowRightKey(event) {
|
|
@@ -2679,6 +2706,8 @@ function $isActionTextAttachmentNode(node) {
|
|
|
2679
2706
|
}
|
|
2680
2707
|
|
|
2681
2708
|
class Selection {
|
|
2709
|
+
#unregister = []
|
|
2710
|
+
|
|
2682
2711
|
constructor(editorElement) {
|
|
2683
2712
|
this.editorElement = editorElement;
|
|
2684
2713
|
this.editorContentElement = editorElement.editorContentElement;
|
|
@@ -2935,6 +2964,18 @@ class Selection {
|
|
|
2935
2964
|
return this.#findPreviousSiblingUp(anchorNode)
|
|
2936
2965
|
}
|
|
2937
2966
|
|
|
2967
|
+
dispose() {
|
|
2968
|
+
this.editorElement = null;
|
|
2969
|
+
this.editorContentElement = null;
|
|
2970
|
+
this.editor = null;
|
|
2971
|
+
this.previouslySelectedKeys = null;
|
|
2972
|
+
|
|
2973
|
+
while (this.#unregister.length) {
|
|
2974
|
+
const unregister = this.#unregister.pop();
|
|
2975
|
+
unregister();
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2938
2979
|
// When all inline code text is deleted, Lexical's selection retains the stale
|
|
2939
2980
|
// code format flag. Verify the flag is backed by actual code-formatted content:
|
|
2940
2981
|
// a code block ancestor or a text node that carries the code format.
|
|
@@ -2950,7 +2991,7 @@ class Selection {
|
|
|
2950
2991
|
// detects that stale state and clears it so newly typed text won't be
|
|
2951
2992
|
// code-formatted.
|
|
2952
2993
|
#clearStaleInlineCodeFormat() {
|
|
2953
|
-
this.editor.registerUpdateListener(({ editorState, tags }) => {
|
|
2994
|
+
this.#unregister.push(this.editor.registerUpdateListener(({ editorState, tags }) => {
|
|
2954
2995
|
if (tags.has("history-merge") || tags.has("skip-dom-selection")) return
|
|
2955
2996
|
|
|
2956
2997
|
let isStale = false;
|
|
@@ -2979,7 +3020,7 @@ class Selection {
|
|
|
2979
3020
|
});
|
|
2980
3021
|
}, 0);
|
|
2981
3022
|
}
|
|
2982
|
-
});
|
|
3023
|
+
}));
|
|
2983
3024
|
}
|
|
2984
3025
|
|
|
2985
3026
|
get #currentlySelectedKeys() {
|
|
@@ -2998,29 +3039,32 @@ class Selection {
|
|
|
2998
3039
|
}
|
|
2999
3040
|
|
|
3000
3041
|
#processSelectionChangeCommands() {
|
|
3001
|
-
this
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3042
|
+
this.#unregister.push(mergeRegister$1(
|
|
3043
|
+
this.editor.registerCommand(KEY_ARROW_LEFT_COMMAND, this.#selectPreviousNode.bind(this), COMMAND_PRIORITY_LOW),
|
|
3044
|
+
this.editor.registerCommand(KEY_ARROW_RIGHT_COMMAND, this.#selectNextNode.bind(this), COMMAND_PRIORITY_LOW),
|
|
3045
|
+
this.editor.registerCommand(KEY_ARROW_UP_COMMAND, this.#selectPreviousTopLevelNode.bind(this), COMMAND_PRIORITY_LOW),
|
|
3046
|
+
this.editor.registerCommand(KEY_ARROW_DOWN_COMMAND, this.#selectNextTopLevelNode.bind(this), COMMAND_PRIORITY_LOW),
|
|
3005
3047
|
|
|
3006
|
-
|
|
3048
|
+
this.editor.registerCommand(DELETE_CHARACTER_COMMAND, this.#selectDecoratorNodeBeforeDeletion.bind(this), COMMAND_PRIORITY_LOW),
|
|
3007
3049
|
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3050
|
+
this.editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
|
3051
|
+
this.current = $getSelection();
|
|
3052
|
+
}, COMMAND_PRIORITY_LOW)
|
|
3053
|
+
));
|
|
3011
3054
|
}
|
|
3012
3055
|
|
|
3013
3056
|
#listenForNodeSelections() {
|
|
3014
|
-
this.editor.registerCommand(CLICK_COMMAND, ({ target }) => {
|
|
3057
|
+
this.#unregister.push(this.editor.registerCommand(CLICK_COMMAND, ({ target }) => {
|
|
3015
3058
|
if (!isDOMNode(target)) return false
|
|
3016
3059
|
|
|
3017
3060
|
const targetNode = $getNearestNodeFromDOMNode(target);
|
|
3018
3061
|
return $isDecoratorNode(targetNode) && this.#selectInLexical(targetNode)
|
|
3019
|
-
}, COMMAND_PRIORITY_LOW);
|
|
3062
|
+
}, COMMAND_PRIORITY_LOW));
|
|
3020
3063
|
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3064
|
+
const moveNextLineHandler = () => this.#selectOrAppendNextLine();
|
|
3065
|
+
const rootElement = this.editor.getRootElement();
|
|
3066
|
+
rootElement.addEventListener("lexxy:internal:move-to-next-line", moveNextLineHandler);
|
|
3067
|
+
this.#unregister.push(() => rootElement.removeEventListener("lexxy:internal:move-to-next-line", moveNextLineHandler));
|
|
3024
3068
|
}
|
|
3025
3069
|
|
|
3026
3070
|
#containEditorFocus() {
|
|
@@ -4155,7 +4199,11 @@ class Contents {
|
|
|
4155
4199
|
constructor(editorElement) {
|
|
4156
4200
|
this.editorElement = editorElement;
|
|
4157
4201
|
this.editor = editorElement.editor;
|
|
4202
|
+
}
|
|
4158
4203
|
|
|
4204
|
+
dispose() {
|
|
4205
|
+
this.editorElement = null;
|
|
4206
|
+
this.editor = null;
|
|
4159
4207
|
}
|
|
4160
4208
|
|
|
4161
4209
|
insertHtml(html, { tag } = {}) {
|
|
@@ -5186,11 +5234,12 @@ class TablesExtension extends LexxyExtension {
|
|
|
5186
5234
|
TableRowNode
|
|
5187
5235
|
],
|
|
5188
5236
|
register(editor) {
|
|
5237
|
+
setScrollableTablesActive(editor, true);
|
|
5238
|
+
|
|
5189
5239
|
return mergeRegister(
|
|
5190
5240
|
// Register Lexical table plugins
|
|
5191
5241
|
registerTablePlugin(editor),
|
|
5192
5242
|
registerTableSelectionObserver(editor, true),
|
|
5193
|
-
setScrollableTablesActive(editor, true),
|
|
5194
5243
|
|
|
5195
5244
|
// Bug fix: Prevent hardcoded background color (Lexical #8089)
|
|
5196
5245
|
editor.registerNodeTransform(TableCellNode, (node) => {
|
|
@@ -5917,6 +5966,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
5917
5966
|
|
|
5918
5967
|
#initialValue = ""
|
|
5919
5968
|
#validationTextArea = document.createElement("textarea")
|
|
5969
|
+
#disposables = []
|
|
5920
5970
|
|
|
5921
5971
|
constructor() {
|
|
5922
5972
|
super();
|
|
@@ -5930,12 +5980,19 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
5930
5980
|
this.extensions = new Extensions(this);
|
|
5931
5981
|
|
|
5932
5982
|
this.editor = this.#createEditor();
|
|
5983
|
+
this.#disposables.push(this.editor);
|
|
5933
5984
|
|
|
5934
5985
|
this.contents = new Contents(this);
|
|
5986
|
+
this.#disposables.push(this.contents);
|
|
5987
|
+
|
|
5935
5988
|
this.selection = new Selection(this);
|
|
5989
|
+
this.#disposables.push(this.selection);
|
|
5990
|
+
|
|
5936
5991
|
this.clipboard = new Clipboard(this);
|
|
5937
5992
|
|
|
5938
|
-
CommandDispatcher.configureFor(this);
|
|
5993
|
+
const commandDispatcher = CommandDispatcher.configureFor(this);
|
|
5994
|
+
this.#disposables.push(commandDispatcher);
|
|
5995
|
+
|
|
5939
5996
|
this.#initialize();
|
|
5940
5997
|
|
|
5941
5998
|
requestAnimationFrame(() => dispatch(this, "lexxy:initialize"));
|
|
@@ -5988,7 +6045,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
5988
6045
|
get toolbarElement() {
|
|
5989
6046
|
if (!this.#hasToolbar) return null
|
|
5990
6047
|
|
|
5991
|
-
this.toolbar
|
|
6048
|
+
this.toolbar ??= this.#findOrCreateDefaultToolbar();
|
|
5992
6049
|
return this.toolbar
|
|
5993
6050
|
}
|
|
5994
6051
|
|
|
@@ -6124,6 +6181,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6124
6181
|
|
|
6125
6182
|
#createEditor() {
|
|
6126
6183
|
this.editorContentElement ||= this.#createEditorContentElement();
|
|
6184
|
+
this.appendChild(this.editorContentElement);
|
|
6127
6185
|
|
|
6128
6186
|
const editor = buildEditorFromExtensions({
|
|
6129
6187
|
name: "lexxy/core",
|
|
@@ -6173,7 +6231,6 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6173
6231
|
});
|
|
6174
6232
|
editorContentElement.id = `${this.id}-content`;
|
|
6175
6233
|
this.#ariaAttributes.forEach(attribute => editorContentElement.setAttribute(attribute.name, attribute.value));
|
|
6176
|
-
this.appendChild(editorContentElement);
|
|
6177
6234
|
|
|
6178
6235
|
if (this.getAttribute("tabindex")) {
|
|
6179
6236
|
editorContentElement.setAttribute("tabindex", this.getAttribute("tabindex"));
|
|
@@ -6249,36 +6306,48 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6249
6306
|
}
|
|
6250
6307
|
|
|
6251
6308
|
#registerComponents() {
|
|
6309
|
+
const registered = [];
|
|
6310
|
+
|
|
6252
6311
|
if (this.supportsRichText) {
|
|
6253
|
-
|
|
6254
|
-
|
|
6312
|
+
registered.push(
|
|
6313
|
+
registerRichText(this.editor),
|
|
6314
|
+
registerList(this.editor)
|
|
6315
|
+
);
|
|
6255
6316
|
this.#registerTableComponents();
|
|
6256
6317
|
this.#registerCodeHiglightingComponents();
|
|
6257
6318
|
if (this.supportsMarkdown) {
|
|
6258
|
-
|
|
6259
|
-
|
|
6319
|
+
registered.push(
|
|
6320
|
+
registerMarkdownShortcuts(this.editor, TRANSFORMERS),
|
|
6321
|
+
registerMarkdownLeadingTagHandler(this.editor, TRANSFORMERS)
|
|
6322
|
+
);
|
|
6260
6323
|
}
|
|
6261
6324
|
} else {
|
|
6262
|
-
registerPlainText(this.editor);
|
|
6325
|
+
registered.push(registerPlainText(this.editor));
|
|
6263
6326
|
}
|
|
6264
6327
|
this.historyState = createEmptyHistoryState();
|
|
6265
|
-
registerHistory(this.editor, this.historyState, 20);
|
|
6328
|
+
registered.push(registerHistory(this.editor, this.historyState, 20));
|
|
6329
|
+
|
|
6330
|
+
this.#addUnregisterHandler(mergeRegister$1(...registered));
|
|
6266
6331
|
}
|
|
6267
6332
|
|
|
6268
6333
|
#registerTableComponents() {
|
|
6269
|
-
|
|
6270
|
-
|
|
6334
|
+
let tableTools = this.querySelector("lexxy-table-tools");
|
|
6335
|
+
tableTools ??= createElement("lexxy-table-tools");
|
|
6336
|
+
this.append(tableTools);
|
|
6337
|
+
this.#disposables.push(tableTools);
|
|
6271
6338
|
}
|
|
6272
6339
|
|
|
6273
6340
|
#registerCodeHiglightingComponents() {
|
|
6274
6341
|
registerCodeHighlighting(this.editor);
|
|
6275
|
-
|
|
6276
|
-
|
|
6342
|
+
let codeLanguagePicker = this.querySelector("lexxy-code-language-picker");
|
|
6343
|
+
codeLanguagePicker ??= createElement("lexxy-code-language-picker");
|
|
6344
|
+
this.append(codeLanguagePicker);
|
|
6345
|
+
this.#disposables.push(codeLanguagePicker);
|
|
6277
6346
|
}
|
|
6278
6347
|
|
|
6279
6348
|
#handleEnter() {
|
|
6280
6349
|
// We can't prevent these externally using regular keydown because Lexical handles it first.
|
|
6281
|
-
this.editor.registerCommand(
|
|
6350
|
+
this.#addUnregisterHandler(this.editor.registerCommand(
|
|
6282
6351
|
KEY_ENTER_COMMAND,
|
|
6283
6352
|
(event) => {
|
|
6284
6353
|
// Prevent CTRL+ENTER
|
|
@@ -6296,12 +6365,17 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6296
6365
|
return false
|
|
6297
6366
|
},
|
|
6298
6367
|
COMMAND_PRIORITY_NORMAL
|
|
6299
|
-
);
|
|
6368
|
+
));
|
|
6300
6369
|
}
|
|
6301
6370
|
|
|
6302
6371
|
#registerFocusEvents() {
|
|
6303
6372
|
this.addEventListener("focusin", this.#handleFocusIn);
|
|
6304
6373
|
this.addEventListener("focusout", this.#handleFocusOut);
|
|
6374
|
+
|
|
6375
|
+
this.#addUnregisterHandler(() => {
|
|
6376
|
+
this.removeEventListener("focusin", this.#handleFocusIn);
|
|
6377
|
+
this.removeEventListener("focusout", this.#handleFocusOut);
|
|
6378
|
+
});
|
|
6305
6379
|
}
|
|
6306
6380
|
|
|
6307
6381
|
#handleFocusIn(event) {
|
|
@@ -6344,6 +6418,10 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6344
6418
|
#attachToolbar() {
|
|
6345
6419
|
if (this.#hasToolbar) {
|
|
6346
6420
|
this.toolbarElement.setEditor(this);
|
|
6421
|
+
if (typeof this.toolbarElement.dispose === "function") {
|
|
6422
|
+
this.#disposables.push(this.toolbarElement);
|
|
6423
|
+
}
|
|
6424
|
+
|
|
6347
6425
|
this.extensions.initializeToolbars();
|
|
6348
6426
|
}
|
|
6349
6427
|
}
|
|
@@ -6353,7 +6431,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6353
6431
|
if (typeof toolbarConfig === "string") {
|
|
6354
6432
|
return document.getElementById(toolbarConfig)
|
|
6355
6433
|
} else {
|
|
6356
|
-
return this.#createDefaultToolbar()
|
|
6434
|
+
return this.querySelector("lexxy-toolbar") ?? this.#createDefaultToolbar()
|
|
6357
6435
|
}
|
|
6358
6436
|
}
|
|
6359
6437
|
|
|
@@ -6383,34 +6461,22 @@ class LexicalEditorElement extends HTMLElement {
|
|
|
6383
6461
|
}
|
|
6384
6462
|
|
|
6385
6463
|
#reset() {
|
|
6386
|
-
this.#
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
this.editorContentElement.remove();
|
|
6390
|
-
this.editorContentElement = null;
|
|
6391
|
-
}
|
|
6392
|
-
|
|
6393
|
-
this.contents = null;
|
|
6394
|
-
this.editor = null;
|
|
6464
|
+
this.#dispose();
|
|
6465
|
+
this.editorContentElement?.remove();
|
|
6466
|
+
this.editorContentElement = null;
|
|
6395
6467
|
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6468
|
+
// Prevents issues with turbo morphing receiving an empty <lexxy-editor> which wipes
|
|
6469
|
+
// out the DOM for the tools, and the old toolbar reference will cause issues
|
|
6470
|
+
this.toolbar = null;
|
|
6471
|
+
}
|
|
6400
6472
|
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
}
|
|
6473
|
+
#dispose() {
|
|
6474
|
+
this.#unregisterHandlers();
|
|
6475
|
+
document.removeEventListener("turbo:before-cache", this.#handleTurboBeforeCache);
|
|
6405
6476
|
|
|
6406
|
-
|
|
6407
|
-
this.
|
|
6408
|
-
this.tableHandler = null;
|
|
6477
|
+
while (this.#disposables.length) {
|
|
6478
|
+
this.#disposables.pop().dispose();
|
|
6409
6479
|
}
|
|
6410
|
-
|
|
6411
|
-
this.selection = null;
|
|
6412
|
-
|
|
6413
|
-
document.removeEventListener("turbo:before-cache", this.#handleTurboBeforeCache);
|
|
6414
6480
|
}
|
|
6415
6481
|
|
|
6416
6482
|
#reconnect() {
|
|
@@ -6451,14 +6517,15 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
6451
6517
|
connectedCallback() {
|
|
6452
6518
|
this.container = this.closest("details");
|
|
6453
6519
|
|
|
6454
|
-
this.container.addEventListener("toggle", this.#handleToggle
|
|
6455
|
-
this.container.addEventListener("keydown", this.#handleKeyDown
|
|
6520
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
6521
|
+
this.container.addEventListener("keydown", this.#handleKeyDown);
|
|
6456
6522
|
|
|
6457
6523
|
this.#onToolbarEditor(this.initialize.bind(this));
|
|
6458
6524
|
}
|
|
6459
6525
|
|
|
6460
6526
|
disconnectedCallback() {
|
|
6461
|
-
this.container
|
|
6527
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
6528
|
+
this.container?.removeEventListener("keydown", this.#handleKeyDown);
|
|
6462
6529
|
}
|
|
6463
6530
|
|
|
6464
6531
|
get toolbar() {
|
|
@@ -6483,11 +6550,11 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
6483
6550
|
}
|
|
6484
6551
|
|
|
6485
6552
|
async #onToolbarEditor(callback) {
|
|
6486
|
-
await this.toolbar.
|
|
6553
|
+
await this.toolbar.editorElement;
|
|
6487
6554
|
callback();
|
|
6488
6555
|
}
|
|
6489
6556
|
|
|
6490
|
-
#handleToggle() {
|
|
6557
|
+
#handleToggle = () => {
|
|
6491
6558
|
if (this.container.open) {
|
|
6492
6559
|
this.#handleOpen();
|
|
6493
6560
|
}
|
|
@@ -6498,7 +6565,7 @@ class ToolbarDropdown extends HTMLElement {
|
|
|
6498
6565
|
this.#resetTabIndexValues();
|
|
6499
6566
|
}
|
|
6500
6567
|
|
|
6501
|
-
#handleKeyDown(event) {
|
|
6568
|
+
#handleKeyDown = (event) => {
|
|
6502
6569
|
if (event.key === "Escape") {
|
|
6503
6570
|
event.stopPropagation();
|
|
6504
6571
|
this.close();
|
|
@@ -6526,27 +6593,30 @@ class LinkDropdown extends ToolbarDropdown {
|
|
|
6526
6593
|
super.connectedCallback();
|
|
6527
6594
|
this.input = this.querySelector("input");
|
|
6528
6595
|
|
|
6529
|
-
this.#
|
|
6596
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
6597
|
+
this.addEventListener("submit", this.#handleSubmit);
|
|
6598
|
+
this.querySelector("[value='unlink']").addEventListener("click", this.#handleUnlink);
|
|
6530
6599
|
}
|
|
6531
6600
|
|
|
6532
|
-
|
|
6533
|
-
this.container
|
|
6534
|
-
this.
|
|
6535
|
-
this.querySelector("[value='unlink']")
|
|
6601
|
+
disconnectedCallback() {
|
|
6602
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
6603
|
+
this.removeEventListener("submit", this.#handleSubmit);
|
|
6604
|
+
this.querySelector("[value='unlink']")?.removeEventListener("click", this.#handleUnlink);
|
|
6605
|
+
super.disconnectedCallback();
|
|
6536
6606
|
}
|
|
6537
6607
|
|
|
6538
|
-
#handleToggle({ newState }) {
|
|
6608
|
+
#handleToggle = ({ newState }) => {
|
|
6539
6609
|
this.input.value = this.#selectedLinkUrl;
|
|
6540
6610
|
this.input.required = newState === "open";
|
|
6541
6611
|
}
|
|
6542
6612
|
|
|
6543
|
-
#handleSubmit(event) {
|
|
6613
|
+
#handleSubmit = (event) => {
|
|
6544
6614
|
const command = event.submitter?.value;
|
|
6545
6615
|
this.editor.dispatchCommand(command, this.input.value);
|
|
6546
6616
|
this.close();
|
|
6547
6617
|
}
|
|
6548
6618
|
|
|
6549
|
-
#handleUnlink() {
|
|
6619
|
+
#handleUnlink = () => {
|
|
6550
6620
|
this.editor.dispatchCommand("unlink");
|
|
6551
6621
|
this.close();
|
|
6552
6622
|
}
|
|
@@ -6581,26 +6651,35 @@ const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
|
|
|
6581
6651
|
const NO_STYLE = Symbol("no_style");
|
|
6582
6652
|
|
|
6583
6653
|
class HighlightDropdown extends ToolbarDropdown {
|
|
6584
|
-
connectedCallback() {
|
|
6585
|
-
super.connectedCallback();
|
|
6586
|
-
this.#registerToggleHandler();
|
|
6587
|
-
}
|
|
6588
|
-
|
|
6589
6654
|
initialize() {
|
|
6590
6655
|
this.#setUpButtons();
|
|
6591
6656
|
this.#registerButtonHandlers();
|
|
6592
6657
|
}
|
|
6593
6658
|
|
|
6594
|
-
|
|
6595
|
-
|
|
6659
|
+
connectedCallback() {
|
|
6660
|
+
super.connectedCallback();
|
|
6661
|
+
this.container.addEventListener("toggle", this.#handleToggle);
|
|
6662
|
+
}
|
|
6663
|
+
|
|
6664
|
+
disconnectedCallback() {
|
|
6665
|
+
this.container?.removeEventListener("toggle", this.#handleToggle);
|
|
6666
|
+
this.#removeButtonHandlers();
|
|
6667
|
+
super.disconnectedCallback();
|
|
6596
6668
|
}
|
|
6597
6669
|
|
|
6598
6670
|
#registerButtonHandlers() {
|
|
6599
|
-
this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick
|
|
6600
|
-
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick
|
|
6671
|
+
this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick));
|
|
6672
|
+
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick);
|
|
6673
|
+
}
|
|
6674
|
+
|
|
6675
|
+
#removeButtonHandlers() {
|
|
6676
|
+
this.#colorButtons.forEach(button => button.removeEventListener("click", this.#handleColorButtonClick));
|
|
6677
|
+
this.querySelector(REMOVE_HIGHLIGHT_SELECTOR)?.removeEventListener("click", this.#handleRemoveHighlightClick);
|
|
6601
6678
|
}
|
|
6602
6679
|
|
|
6603
6680
|
#setUpButtons() {
|
|
6681
|
+
this.#buttonContainer.innerHTML = "";
|
|
6682
|
+
|
|
6604
6683
|
const colorGroups = this.editorElement.config.get("highlight.buttons");
|
|
6605
6684
|
|
|
6606
6685
|
this.#populateButtonGroup("color", colorGroups.color);
|
|
@@ -6626,7 +6705,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
6626
6705
|
return button
|
|
6627
6706
|
}
|
|
6628
6707
|
|
|
6629
|
-
#handleToggle({ newState }) {
|
|
6708
|
+
#handleToggle = ({ newState }) => {
|
|
6630
6709
|
if (newState === "open") {
|
|
6631
6710
|
this.editor.getEditorState().read(() => {
|
|
6632
6711
|
this.#updateColorButtonStates($getSelection());
|
|
@@ -6634,7 +6713,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
6634
6713
|
}
|
|
6635
6714
|
}
|
|
6636
6715
|
|
|
6637
|
-
#handleColorButtonClick(event) {
|
|
6716
|
+
#handleColorButtonClick = (event) => {
|
|
6638
6717
|
event.preventDefault();
|
|
6639
6718
|
|
|
6640
6719
|
const button = event.target.closest(APPLY_HIGHLIGHT_SELECTOR);
|
|
@@ -6647,7 +6726,7 @@ class HighlightDropdown extends ToolbarDropdown {
|
|
|
6647
6726
|
this.close();
|
|
6648
6727
|
}
|
|
6649
6728
|
|
|
6650
|
-
#handleRemoveHighlightClick(event) {
|
|
6729
|
+
#handleRemoveHighlightClick = (event) => {
|
|
6651
6730
|
event.preventDefault();
|
|
6652
6731
|
|
|
6653
6732
|
this.editor.dispatchCommand("removeHighlight");
|
|
@@ -7309,19 +7388,21 @@ class CodeLanguagePicker extends HTMLElement {
|
|
|
7309
7388
|
}
|
|
7310
7389
|
|
|
7311
7390
|
disconnectedCallback() {
|
|
7391
|
+
this.dispose();
|
|
7392
|
+
}
|
|
7393
|
+
|
|
7394
|
+
dispose() {
|
|
7312
7395
|
this.unregisterUpdateListener?.();
|
|
7313
7396
|
this.unregisterUpdateListener = null;
|
|
7314
7397
|
}
|
|
7315
7398
|
|
|
7316
7399
|
#attachLanguagePicker() {
|
|
7317
|
-
this.languagePickerElement = this.#createLanguagePicker();
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
this.#updateCodeBlockLanguage(this.languagePickerElement.value);
|
|
7321
|
-
});
|
|
7400
|
+
this.languagePickerElement = this.#findLanguagePicker() ?? this.#createLanguagePicker();
|
|
7401
|
+
this.append(this.languagePickerElement);
|
|
7402
|
+
}
|
|
7322
7403
|
|
|
7323
|
-
|
|
7324
|
-
this.
|
|
7404
|
+
#findLanguagePicker() {
|
|
7405
|
+
return this.querySelector("select")
|
|
7325
7406
|
}
|
|
7326
7407
|
|
|
7327
7408
|
#createLanguagePicker() {
|
|
@@ -7334,6 +7415,12 @@ class CodeLanguagePicker extends HTMLElement {
|
|
|
7334
7415
|
selectElement.appendChild(option);
|
|
7335
7416
|
}
|
|
7336
7417
|
|
|
7418
|
+
selectElement.addEventListener("change", () => {
|
|
7419
|
+
this.#updateCodeBlockLanguage(this.languagePickerElement.value);
|
|
7420
|
+
});
|
|
7421
|
+
|
|
7422
|
+
selectElement.setAttribute("nonce", getNonce());
|
|
7423
|
+
|
|
7337
7424
|
return selectElement
|
|
7338
7425
|
}
|
|
7339
7426
|
|
|
@@ -7894,6 +7981,10 @@ class TableTools extends HTMLElement {
|
|
|
7894
7981
|
}
|
|
7895
7982
|
|
|
7896
7983
|
disconnectedCallback() {
|
|
7984
|
+
this.dispose();
|
|
7985
|
+
}
|
|
7986
|
+
|
|
7987
|
+
dispose() {
|
|
7897
7988
|
this.#unregisterKeyboardShortcuts();
|
|
7898
7989
|
|
|
7899
7990
|
this.unregisterUpdateListener?.();
|
|
@@ -7918,6 +8009,8 @@ class TableTools extends HTMLElement {
|
|
|
7918
8009
|
}
|
|
7919
8010
|
|
|
7920
8011
|
#setUpButtons() {
|
|
8012
|
+
this.innerHTML = "";
|
|
8013
|
+
|
|
7921
8014
|
this.appendChild(this.#createRowButtonsContainer());
|
|
7922
8015
|
this.appendChild(this.#createColumnButtonsContainer());
|
|
7923
8016
|
|