onchain-lexical-instance 0.0.13 → 0.0.15
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/OnchainLexicalInstance.js +121 -21
- package/dist/OnchainLexicalInstance.mjs +121 -24
- package/package.json +5 -5
- package/src/code/codeHighlighter.ts +44 -38
- package/src/collapsible/index.ts +1 -1
- package/src/equation/index.tsx +3 -2
- package/src/index.ts +1 -1
- package/src/instancePlugin.ts +44 -1
- package/src/internalLink/index.tsx +30 -1
- package/src/list/index.ts +1 -0
- package/src/parameters/index.tsx +48 -1
- package/src/parameters/parametersComponent.tsx +54 -34
- package/src/parameters/types.d.ts +3 -0
- package/src/utils.ts +39 -0
- /package/src/collapsible/{titleNode.ts → title.ts} +0 -0
|
@@ -21,6 +21,7 @@ var onchainLexicalMarkdown = require('onchain-lexical-markdown');
|
|
|
21
21
|
var traversal = require('onchain-utility/traversal');
|
|
22
22
|
var selection = require('@lexical/selection');
|
|
23
23
|
var useLexicalNodeSelection = require('@lexical/react/useLexicalNodeSelection');
|
|
24
|
+
var base64 = require('onchain-utility/base64');
|
|
24
25
|
var hooks = require('onchain-utility/hooks');
|
|
25
26
|
var richText = require('@lexical/rich-text');
|
|
26
27
|
var useLexicalEditable = require('@lexical/react/useLexicalEditable');
|
|
@@ -1143,6 +1144,26 @@ function $addInstancesNode({
|
|
|
1143
1144
|
}
|
|
1144
1145
|
}
|
|
1145
1146
|
}
|
|
1147
|
+
function $selectDecoratorNode(node) {
|
|
1148
|
+
if (node) {
|
|
1149
|
+
const [previous, next] = [node.getPreviousSibling(), node.getNextSibling()];
|
|
1150
|
+
const rangeSelection = lexical.$createRangeSelection();
|
|
1151
|
+
if (previous) {
|
|
1152
|
+
const isText = lexical.$isTextNode(previous);
|
|
1153
|
+
rangeSelection.anchor.set(isText ? previous.getKey() : node.getParent().getKey(), isText ? previous.getTextContentSize() : node.getPreviousSiblings().length, isText ? 'text' : 'element');
|
|
1154
|
+
} else {
|
|
1155
|
+
const parent = node.getParent();
|
|
1156
|
+
rangeSelection.anchor.set(parent.getKey(), 0, 'element');
|
|
1157
|
+
}
|
|
1158
|
+
if (next) {
|
|
1159
|
+
rangeSelection.focus.set(next.getKey(), 0, lexical.$isTextNode(next) ? 'text' : 'element');
|
|
1160
|
+
} else {
|
|
1161
|
+
const parent = node.getParent();
|
|
1162
|
+
rangeSelection.focus.set(parent.getKey(), node.getPreviousSiblings().length + 1, 'element');
|
|
1163
|
+
}
|
|
1164
|
+
lexical.$setSelection(rangeSelection);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1146
1167
|
|
|
1147
1168
|
/**
|
|
1148
1169
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -2671,7 +2692,7 @@ function $textNodeTransform(node, editor, tokenizer) {
|
|
|
2671
2692
|
// if node's parent is a code node and run highlighting if so
|
|
2672
2693
|
const parentNode = node.getParent();
|
|
2673
2694
|
if ($isInstanceCodeNode(parentNode)) {
|
|
2674
|
-
codeNodeTransform(parentNode,
|
|
2695
|
+
codeNodeTransform(parentNode, null, tokenizer);
|
|
2675
2696
|
} else if ($isInstanceCodeHighlightNode(node)) {
|
|
2676
2697
|
// When code block converted into paragraph or other element
|
|
2677
2698
|
// code highlight nodes converted back to normal text
|
|
@@ -2711,9 +2732,9 @@ function updateCodeGutter(node, editor) {
|
|
|
2711
2732
|
// Especially when pasting code into CodeBlock.
|
|
2712
2733
|
|
|
2713
2734
|
const nodesCurrentlyHighlighting = new Set();
|
|
2714
|
-
function codeNodeTransform(node, editor, tokenizer) {
|
|
2735
|
+
function codeNodeTransform(node, editor, tokenizer, isEnforcement) {
|
|
2715
2736
|
const nodeKey = node.getKey();
|
|
2716
|
-
if (nodesCurrentlyHighlighting.has(nodeKey)) {
|
|
2737
|
+
if (nodesCurrentlyHighlighting.has(nodeKey) && !isEnforcement) {
|
|
2717
2738
|
return;
|
|
2718
2739
|
}
|
|
2719
2740
|
nodesCurrentlyHighlighting.add(nodeKey);
|
|
@@ -2726,7 +2747,8 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
2726
2747
|
// Using nested update call to pass `skipTransforms` since we don't want
|
|
2727
2748
|
// each individual InstanceCodeHighlightNode to be transformed again as it's already
|
|
2728
2749
|
// in its final state
|
|
2729
|
-
|
|
2750
|
+
// eslint-disable-next-line @lexical/rules-of-lexical
|
|
2751
|
+
const transform = () => {
|
|
2730
2752
|
$updateAndRetainSelection(nodeKey, () => {
|
|
2731
2753
|
const currentNode = lexical.$getNodeByKey(nodeKey);
|
|
2732
2754
|
if (!$isInstanceCodeNode(currentNode) || !currentNode.isAttached()) {
|
|
@@ -2747,12 +2769,17 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
2747
2769
|
}
|
|
2748
2770
|
return false;
|
|
2749
2771
|
});
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2772
|
+
};
|
|
2773
|
+
if (editor) {
|
|
2774
|
+
editor.update(transform, {
|
|
2775
|
+
onUpdate: () => {
|
|
2776
|
+
nodesCurrentlyHighlighting.delete(nodeKey);
|
|
2777
|
+
},
|
|
2778
|
+
skipTransforms: true
|
|
2779
|
+
});
|
|
2780
|
+
} else {
|
|
2781
|
+
transform();
|
|
2782
|
+
}
|
|
2756
2783
|
}
|
|
2757
2784
|
function $getHighlightNodes(tokens, type) {
|
|
2758
2785
|
const nodes = [];
|
|
@@ -3159,7 +3186,7 @@ function registerCodeHighlighting(editor, tokenizer) {
|
|
|
3159
3186
|
});
|
|
3160
3187
|
}, {
|
|
3161
3188
|
skipInitialization: false
|
|
3162
|
-
}), editor.registerNodeTransform(InstanceCodeNode, node => codeNodeTransform(node,
|
|
3189
|
+
}), editor.registerNodeTransform(InstanceCodeNode, node => codeNodeTransform(node, null, tokenizer)), editor.registerNodeTransform(lexical.TextNode, node => $textNodeTransform(node, editor, tokenizer)), editor.registerNodeTransform(InstanceCodeHighlightNode, node => $textNodeTransform(node, editor, tokenizer)), editor.registerCommand(lexical.KEY_TAB_COMMAND, event => {
|
|
3163
3190
|
const command = $handleTab(event.shiftKey);
|
|
3164
3191
|
if (command === null) {
|
|
3165
3192
|
return false;
|
|
@@ -22154,9 +22181,9 @@ class InstanceEquationNode extends lexical.DecoratorNode {
|
|
|
22154
22181
|
return element;
|
|
22155
22182
|
}
|
|
22156
22183
|
exportDOM() {
|
|
22157
|
-
const element = document.createElement('
|
|
22184
|
+
const element = document.createElement('equation');
|
|
22158
22185
|
// Encode the equation as base64 to avoid issues with special characters
|
|
22159
|
-
const equation =
|
|
22186
|
+
const equation = base64.toBase64UTF8(this.__equation);
|
|
22160
22187
|
element.setAttribute('data-lexical-equation', equation);
|
|
22161
22188
|
element.setAttribute('data-lexical-inline', `${this.__inline}`);
|
|
22162
22189
|
katex.render(this.__equation, element, {
|
|
@@ -23550,6 +23577,7 @@ class InstanceListNode extends list.ListNode {
|
|
|
23550
23577
|
createDOM(config) {
|
|
23551
23578
|
const element = super.createDOM(config);
|
|
23552
23579
|
setDisable(this, element);
|
|
23580
|
+
element.setAttribute('list-type', this.getListType());
|
|
23553
23581
|
return element;
|
|
23554
23582
|
}
|
|
23555
23583
|
updateFromJSON(serializedNode) {
|
|
@@ -23810,7 +23838,28 @@ const InstancePlugin = props => {
|
|
|
23810
23838
|
placeholder
|
|
23811
23839
|
}), $registerInstanceHeadingNodeTransform(editor), $registerInstanceListItemInsertParagraph(editor), $registerNumberDecoratorNodeUpdate(editor), $registerNumberDecoratorDomUpdate(editor), $registerTableCommand(editor),
|
|
23812
23840
|
// $selectionChange(editor, setSelectedInstance),
|
|
23813
|
-
editor.registerCommand(lexical.
|
|
23841
|
+
editor.registerCommand(lexical.SELECTION_CHANGE_COMMAND, () => {
|
|
23842
|
+
const selection = lexical.$getSelection();
|
|
23843
|
+
if (lexical.$isNodeSelection(selection)) {
|
|
23844
|
+
const [node] = selection.getNodes();
|
|
23845
|
+
if (lexical.$isDecoratorNode(node)) {
|
|
23846
|
+
$selectDecoratorNode(node);
|
|
23847
|
+
}
|
|
23848
|
+
}
|
|
23849
|
+
return false;
|
|
23850
|
+
}, lexical.COMMAND_PRIORITY_CRITICAL), editor.registerCommand(lexical.CLICK_COMMAND, event => {
|
|
23851
|
+
if (event.target instanceof HTMLElement) {
|
|
23852
|
+
const decoratorRootEle = event.target.closest('[data-lexical-decorator="true"]');
|
|
23853
|
+
if (decoratorRootEle) {
|
|
23854
|
+
const key = decoratorRootEle.getAttribute('key');
|
|
23855
|
+
if (key) {
|
|
23856
|
+
const node = lexical.$getNodeByKey(key);
|
|
23857
|
+
$selectDecoratorNode(node);
|
|
23858
|
+
}
|
|
23859
|
+
}
|
|
23860
|
+
}
|
|
23861
|
+
return false;
|
|
23862
|
+
}, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.DELETE_CHARACTER_COMMAND, event => {
|
|
23814
23863
|
const selection = lexical.$getSelection();
|
|
23815
23864
|
if (selection) {
|
|
23816
23865
|
return selection.getNodes().some(node => {
|
|
@@ -24173,15 +24222,30 @@ class InternalLinkNode extends lexical.TextDecoratorNode {
|
|
|
24173
24222
|
super(key);
|
|
24174
24223
|
this.__number = number;
|
|
24175
24224
|
}
|
|
24225
|
+
|
|
24226
|
+
// get contentEditable() {
|
|
24227
|
+
// return 'true'
|
|
24228
|
+
// }
|
|
24229
|
+
|
|
24176
24230
|
exportJSON() {
|
|
24177
24231
|
return {
|
|
24178
24232
|
...super.exportJSON(),
|
|
24179
24233
|
number: this.__number
|
|
24180
24234
|
};
|
|
24181
24235
|
}
|
|
24236
|
+
exportDOM(editor) {
|
|
24237
|
+
const element = document.createElement('section');
|
|
24238
|
+
element.setAttribute('internal-link', '');
|
|
24239
|
+
element.setAttribute('data-internal-link-number', this.__number);
|
|
24240
|
+
element.textContent = this.getTextContent();
|
|
24241
|
+
return {
|
|
24242
|
+
element
|
|
24243
|
+
};
|
|
24244
|
+
}
|
|
24182
24245
|
createDOM(config, editor) {
|
|
24183
24246
|
const span = super.createDOM(config, editor);
|
|
24184
24247
|
span.setAttribute('ignoreusable', '');
|
|
24248
|
+
span.setAttribute('decorator', 'text');
|
|
24185
24249
|
return span;
|
|
24186
24250
|
}
|
|
24187
24251
|
updateDOM(prevNode, dom, config) {
|
|
@@ -24193,6 +24257,16 @@ class InternalLinkNode extends lexical.TextDecoratorNode {
|
|
|
24193
24257
|
isInline() {
|
|
24194
24258
|
return true;
|
|
24195
24259
|
}
|
|
24260
|
+
isSelected(selection) {
|
|
24261
|
+
return true;
|
|
24262
|
+
}
|
|
24263
|
+
getTextContent() {
|
|
24264
|
+
const insNode = $getInstanceNodeByNumber(this.__number);
|
|
24265
|
+
if (insNode) {
|
|
24266
|
+
return getLatestValue(insNode.__instance.value, 'insDesc') || '';
|
|
24267
|
+
}
|
|
24268
|
+
return '';
|
|
24269
|
+
}
|
|
24196
24270
|
decorate(editor, config) {
|
|
24197
24271
|
return /*#__PURE__*/jsxRuntime.jsx(InternalLinkComponent, {
|
|
24198
24272
|
editor: editor,
|
|
@@ -24318,10 +24392,11 @@ function $isPageBreakNode(node) {
|
|
|
24318
24392
|
*
|
|
24319
24393
|
*/
|
|
24320
24394
|
|
|
24321
|
-
const ParametersComponent = ({
|
|
24395
|
+
const ParametersComponent = /*#__PURE__*/React.forwardRef(({
|
|
24322
24396
|
nodeKey
|
|
24323
|
-
}) => {
|
|
24397
|
+
}, ref) => {
|
|
24324
24398
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
24399
|
+
const spanRef = React.useRef(null);
|
|
24325
24400
|
const [parameters, setParameters,, latestParameters] = hooks.useStore({
|
|
24326
24401
|
number: '',
|
|
24327
24402
|
value: ''
|
|
@@ -24353,10 +24428,20 @@ const ParametersComponent = ({
|
|
|
24353
24428
|
return true;
|
|
24354
24429
|
}, lexical.COMMAND_PRIORITY_EDITOR));
|
|
24355
24430
|
}, []);
|
|
24431
|
+
React.useImperativeHandle(ref, () => {
|
|
24432
|
+
return {
|
|
24433
|
+
getValue() {
|
|
24434
|
+
return latestParameters.current.value;
|
|
24435
|
+
}
|
|
24436
|
+
};
|
|
24437
|
+
}, []);
|
|
24356
24438
|
return /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
24439
|
+
ref: spanRef,
|
|
24440
|
+
role: "button",
|
|
24441
|
+
tabIndex: 0,
|
|
24357
24442
|
children: parameters.value
|
|
24358
24443
|
});
|
|
24359
|
-
};
|
|
24444
|
+
});
|
|
24360
24445
|
|
|
24361
24446
|
/**
|
|
24362
24447
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -24371,6 +24456,8 @@ class ParametersNode extends lexical.TextDecoratorNode {
|
|
|
24371
24456
|
static collection = new Map();
|
|
24372
24457
|
/** 初始化值 */
|
|
24373
24458
|
|
|
24459
|
+
__ref = /*#__PURE__*/React.createRef();
|
|
24460
|
+
|
|
24374
24461
|
/** 最新的值 */
|
|
24375
24462
|
get parameters() {
|
|
24376
24463
|
return ParametersNode.collection.get(this.__parameters.number) || this.__parameters;
|
|
@@ -24394,9 +24481,19 @@ class ParametersNode extends lexical.TextDecoratorNode {
|
|
|
24394
24481
|
parameters: this.parameters
|
|
24395
24482
|
};
|
|
24396
24483
|
}
|
|
24484
|
+
exportDOM(editor) {
|
|
24485
|
+
const element = document.createElement('section');
|
|
24486
|
+
element.setAttribute('parameter', '');
|
|
24487
|
+
element.setAttribute('data-parameter', base64.toBase64UTF8(JSON.stringify(this.parameters)));
|
|
24488
|
+
element.textContent = this.parameters.value;
|
|
24489
|
+
return {
|
|
24490
|
+
element
|
|
24491
|
+
};
|
|
24492
|
+
}
|
|
24397
24493
|
createDOM(config, editor) {
|
|
24398
24494
|
const span = super.createDOM(config, editor);
|
|
24399
24495
|
span.setAttribute('ignoreusable', '');
|
|
24496
|
+
span.setAttribute('key', this.getKey());
|
|
24400
24497
|
return span;
|
|
24401
24498
|
}
|
|
24402
24499
|
updateDOM(prevNode, dom, config) {
|
|
@@ -24408,8 +24505,12 @@ class ParametersNode extends lexical.TextDecoratorNode {
|
|
|
24408
24505
|
isInline() {
|
|
24409
24506
|
return true;
|
|
24410
24507
|
}
|
|
24508
|
+
getTextContent() {
|
|
24509
|
+
return this.__ref.current?.getValue() || '';
|
|
24510
|
+
}
|
|
24411
24511
|
decorate(editor, config) {
|
|
24412
24512
|
return /*#__PURE__*/jsxRuntime.jsx(ParametersComponent, {
|
|
24513
|
+
ref: this.__ref,
|
|
24413
24514
|
nodeKey: this.getKey()
|
|
24414
24515
|
});
|
|
24415
24516
|
}
|
|
@@ -24421,10 +24522,6 @@ function $isParametersNode(node) {
|
|
|
24421
24522
|
return node instanceof ParametersNode;
|
|
24422
24523
|
}
|
|
24423
24524
|
|
|
24424
|
-
// export function updateParameters(parameters: Parameters) {
|
|
24425
|
-
// return ParametersNode.collection.set(parameters.number, parameters);
|
|
24426
|
-
// }
|
|
24427
|
-
|
|
24428
24525
|
/**
|
|
24429
24526
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
24430
24527
|
*
|
|
@@ -25525,6 +25622,7 @@ exports.$nodeUpgrade = $nodeUpgrade;
|
|
|
25525
25622
|
exports.$removeHighestEmptyListParent = $removeHighestEmptyListParent;
|
|
25526
25623
|
exports.$removeList = $removeList;
|
|
25527
25624
|
exports.$scrollTo = $scrollTo;
|
|
25625
|
+
exports.$selectDecoratorNode = $selectDecoratorNode;
|
|
25528
25626
|
exports.$updateRichHistoryStateMap = $updateRichHistoryStateMap;
|
|
25529
25627
|
exports.$updateRichInstanceContent = $updateRichInstanceContent;
|
|
25530
25628
|
exports.$updateRichInstanceTitle = $updateRichInstanceTitle;
|
|
@@ -25567,8 +25665,10 @@ exports.PARAMETERS_UPDATE = PARAMETERS_UPDATE;
|
|
|
25567
25665
|
exports.PageBreakNode = PageBreakNode;
|
|
25568
25666
|
exports.ParametersNode = ParametersNode;
|
|
25569
25667
|
exports.PlaceholderDecoratorNode = PlaceholderDecoratorNode;
|
|
25668
|
+
exports.PrismTokenizer = PrismTokenizer;
|
|
25570
25669
|
exports.SPLIT_INSTANCE_NODE = SPLIT_INSTANCE_NODE;
|
|
25571
25670
|
exports.clearCache = clearCache;
|
|
25671
|
+
exports.codeNodeTransform = codeNodeTransform;
|
|
25572
25672
|
exports.correctedInstanceParagraph = correctedInstanceParagraph;
|
|
25573
25673
|
exports.fixedAddress = fixedAddress;
|
|
25574
25674
|
exports.getCachedClassNameArray = getCachedClassNameArray;
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
import { $isCodeNode, CodeNode } from '@lexical/code';
|
|
10
10
|
import { $findMatchingParent, addClassNamesToElement, mergeRegister, removeClassNamesFromElement, $getAdjacentCaret, isHTMLElement as isHTMLElement$1, IS_CHROME, $insertNodeToNearestRoot, $getNearestNodeOfType, $descendantsMatching } from '@lexical/utils';
|
|
11
|
-
import { createCommand, ElementNode, $applyNodeReplacement, isHTMLElement, setNodeIndentFromDOM, DecoratorNode, $getEditor, $isTextNode, $createTextNode, TextNode as TextNode$1, $getSelection, $isRootOrShadowRoot, $isRootNode, $getNodeByKey, scrollIntoViewIfNeeded, $isElementNode, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, ParagraphNode, COMMAND_PRIORITY_EDITOR, $getSiblingCaret, $isTabNode, $createTabNode, $createLineBreakNode, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, INSERT_TAB_COMMAND, $insertNodes, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, KEY_ARROW_UP_COMMAND, $isRangeSelection, KEY_ARROW_DOWN_COMMAND, MOVE_TO_START, MOVE_TO_END, $isLineBreakNode, $rewindSiblingCaret, $createParagraphNode, createEditor, RootNode, LineBreakNode, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_NORMAL, $getPreviousSelection,
|
|
11
|
+
import { createCommand, ElementNode, $applyNodeReplacement, isHTMLElement, setNodeIndentFromDOM, DecoratorNode, $getEditor, $isTextNode, $createTextNode, TextNode as TextNode$1, $getSelection, $isRootOrShadowRoot, $isRootNode, $getNodeByKey, scrollIntoViewIfNeeded, $isElementNode, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, $createRangeSelection, $setSelection, ParagraphNode, COMMAND_PRIORITY_EDITOR, $getSiblingCaret, $isTabNode, $createTabNode, $createLineBreakNode, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, INSERT_TAB_COMMAND, $insertNodes, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, KEY_ARROW_UP_COMMAND, $isRangeSelection, KEY_ARROW_DOWN_COMMAND, MOVE_TO_START, MOVE_TO_END, $isLineBreakNode, $rewindSiblingCaret, $createParagraphNode, createEditor, RootNode, LineBreakNode, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, INSERT_PARAGRAPH_COMMAND, COMMAND_PRIORITY_NORMAL, $getPreviousSelection, $isNodeSelection, $isDecoratorNode, CLICK_COMMAND, DELETE_CHARACTER_COMMAND, exportNodeToJSON, TextDecoratorNode, COMMAND_PRIORITY_HIGH, KEY_ESCAPE_COMMAND, $createNodeSelection, DRAGSTART_COMMAND, KEY_ENTER_COMMAND } from 'lexical';
|
|
12
12
|
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
13
13
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
14
14
|
import * as React from 'react';
|
|
15
|
-
import React__default, { useState, useCallback, useEffect, useMemo, useRef, Suspense } from 'react';
|
|
15
|
+
import React__default, { useState, useCallback, useEffect, useMemo, useRef, useImperativeHandle, Suspense } from 'react';
|
|
16
16
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
17
17
|
import { $isListNode, $isListItemNode, $createListItemNode, ListItemNode, ListNode } from '@lexical/list';
|
|
18
18
|
import { TableNode, INSERT_TABLE_COMMAND, $findTableNode, PIXEL_VALUE_REG_EXP, $isTableRowNode, $createTableRowNode, $createTableCellNode, TableCellHeaderStates, $isTableSelection, $isTableCellNode } from '@lexical/table';
|
|
@@ -20,6 +20,7 @@ import { $textToRichNodes, getStorageSerializedString } from 'onchain-lexical-ma
|
|
|
20
20
|
import { dfs as dfs$1 } from 'onchain-utility/traversal';
|
|
21
21
|
import { $setBlocksType } from '@lexical/selection';
|
|
22
22
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
23
|
+
import { toBase64UTF8 } from 'onchain-utility/base64';
|
|
23
24
|
import { useStore } from 'onchain-utility/hooks';
|
|
24
25
|
import { HeadingNode, $isHeadingNode, $isQuoteNode, QuoteNode } from '@lexical/rich-text';
|
|
25
26
|
import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
|
|
@@ -1129,6 +1130,26 @@ function $addInstancesNode({
|
|
|
1129
1130
|
}
|
|
1130
1131
|
}
|
|
1131
1132
|
}
|
|
1133
|
+
function $selectDecoratorNode(node) {
|
|
1134
|
+
if (node) {
|
|
1135
|
+
const [previous, next] = [node.getPreviousSibling(), node.getNextSibling()];
|
|
1136
|
+
const rangeSelection = $createRangeSelection();
|
|
1137
|
+
if (previous) {
|
|
1138
|
+
const isText = $isTextNode(previous);
|
|
1139
|
+
rangeSelection.anchor.set(isText ? previous.getKey() : node.getParent().getKey(), isText ? previous.getTextContentSize() : node.getPreviousSiblings().length, isText ? 'text' : 'element');
|
|
1140
|
+
} else {
|
|
1141
|
+
const parent = node.getParent();
|
|
1142
|
+
rangeSelection.anchor.set(parent.getKey(), 0, 'element');
|
|
1143
|
+
}
|
|
1144
|
+
if (next) {
|
|
1145
|
+
rangeSelection.focus.set(next.getKey(), 0, $isTextNode(next) ? 'text' : 'element');
|
|
1146
|
+
} else {
|
|
1147
|
+
const parent = node.getParent();
|
|
1148
|
+
rangeSelection.focus.set(parent.getKey(), node.getPreviousSiblings().length + 1, 'element');
|
|
1149
|
+
}
|
|
1150
|
+
$setSelection(rangeSelection);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1132
1153
|
|
|
1133
1154
|
/**
|
|
1134
1155
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -2657,7 +2678,7 @@ function $textNodeTransform(node, editor, tokenizer) {
|
|
|
2657
2678
|
// if node's parent is a code node and run highlighting if so
|
|
2658
2679
|
const parentNode = node.getParent();
|
|
2659
2680
|
if ($isInstanceCodeNode(parentNode)) {
|
|
2660
|
-
codeNodeTransform(parentNode,
|
|
2681
|
+
codeNodeTransform(parentNode, null, tokenizer);
|
|
2661
2682
|
} else if ($isInstanceCodeHighlightNode(node)) {
|
|
2662
2683
|
// When code block converted into paragraph or other element
|
|
2663
2684
|
// code highlight nodes converted back to normal text
|
|
@@ -2697,9 +2718,9 @@ function updateCodeGutter(node, editor) {
|
|
|
2697
2718
|
// Especially when pasting code into CodeBlock.
|
|
2698
2719
|
|
|
2699
2720
|
const nodesCurrentlyHighlighting = new Set();
|
|
2700
|
-
function codeNodeTransform(node, editor, tokenizer) {
|
|
2721
|
+
function codeNodeTransform(node, editor, tokenizer, isEnforcement) {
|
|
2701
2722
|
const nodeKey = node.getKey();
|
|
2702
|
-
if (nodesCurrentlyHighlighting.has(nodeKey)) {
|
|
2723
|
+
if (nodesCurrentlyHighlighting.has(nodeKey) && !isEnforcement) {
|
|
2703
2724
|
return;
|
|
2704
2725
|
}
|
|
2705
2726
|
nodesCurrentlyHighlighting.add(nodeKey);
|
|
@@ -2712,7 +2733,8 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
2712
2733
|
// Using nested update call to pass `skipTransforms` since we don't want
|
|
2713
2734
|
// each individual InstanceCodeHighlightNode to be transformed again as it's already
|
|
2714
2735
|
// in its final state
|
|
2715
|
-
|
|
2736
|
+
// eslint-disable-next-line @lexical/rules-of-lexical
|
|
2737
|
+
const transform = () => {
|
|
2716
2738
|
$updateAndRetainSelection(nodeKey, () => {
|
|
2717
2739
|
const currentNode = $getNodeByKey(nodeKey);
|
|
2718
2740
|
if (!$isInstanceCodeNode(currentNode) || !currentNode.isAttached()) {
|
|
@@ -2733,12 +2755,17 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
2733
2755
|
}
|
|
2734
2756
|
return false;
|
|
2735
2757
|
});
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2758
|
+
};
|
|
2759
|
+
if (editor) {
|
|
2760
|
+
editor.update(transform, {
|
|
2761
|
+
onUpdate: () => {
|
|
2762
|
+
nodesCurrentlyHighlighting.delete(nodeKey);
|
|
2763
|
+
},
|
|
2764
|
+
skipTransforms: true
|
|
2765
|
+
});
|
|
2766
|
+
} else {
|
|
2767
|
+
transform();
|
|
2768
|
+
}
|
|
2742
2769
|
}
|
|
2743
2770
|
function $getHighlightNodes(tokens, type) {
|
|
2744
2771
|
const nodes = [];
|
|
@@ -3145,7 +3172,7 @@ function registerCodeHighlighting(editor, tokenizer) {
|
|
|
3145
3172
|
});
|
|
3146
3173
|
}, {
|
|
3147
3174
|
skipInitialization: false
|
|
3148
|
-
}), editor.registerNodeTransform(InstanceCodeNode, node => codeNodeTransform(node,
|
|
3175
|
+
}), editor.registerNodeTransform(InstanceCodeNode, node => codeNodeTransform(node, null, tokenizer)), editor.registerNodeTransform(TextNode$1, node => $textNodeTransform(node, editor, tokenizer)), editor.registerNodeTransform(InstanceCodeHighlightNode, node => $textNodeTransform(node, editor, tokenizer)), editor.registerCommand(KEY_TAB_COMMAND, event => {
|
|
3149
3176
|
const command = $handleTab(event.shiftKey);
|
|
3150
3177
|
if (command === null) {
|
|
3151
3178
|
return false;
|
|
@@ -22140,9 +22167,9 @@ class InstanceEquationNode extends DecoratorNode {
|
|
|
22140
22167
|
return element;
|
|
22141
22168
|
}
|
|
22142
22169
|
exportDOM() {
|
|
22143
|
-
const element = document.createElement('
|
|
22170
|
+
const element = document.createElement('equation');
|
|
22144
22171
|
// Encode the equation as base64 to avoid issues with special characters
|
|
22145
|
-
const equation =
|
|
22172
|
+
const equation = toBase64UTF8(this.__equation);
|
|
22146
22173
|
element.setAttribute('data-lexical-equation', equation);
|
|
22147
22174
|
element.setAttribute('data-lexical-inline', `${this.__inline}`);
|
|
22148
22175
|
katex.render(this.__equation, element, {
|
|
@@ -23536,6 +23563,7 @@ class InstanceListNode extends ListNode {
|
|
|
23536
23563
|
createDOM(config) {
|
|
23537
23564
|
const element = super.createDOM(config);
|
|
23538
23565
|
setDisable(this, element);
|
|
23566
|
+
element.setAttribute('list-type', this.getListType());
|
|
23539
23567
|
return element;
|
|
23540
23568
|
}
|
|
23541
23569
|
updateFromJSON(serializedNode) {
|
|
@@ -23796,7 +23824,28 @@ const InstancePlugin = props => {
|
|
|
23796
23824
|
placeholder
|
|
23797
23825
|
}), $registerInstanceHeadingNodeTransform(editor), $registerInstanceListItemInsertParagraph(editor), $registerNumberDecoratorNodeUpdate(editor), $registerNumberDecoratorDomUpdate(editor), $registerTableCommand(editor),
|
|
23798
23826
|
// $selectionChange(editor, setSelectedInstance),
|
|
23799
|
-
editor.registerCommand(
|
|
23827
|
+
editor.registerCommand(SELECTION_CHANGE_COMMAND, () => {
|
|
23828
|
+
const selection = $getSelection();
|
|
23829
|
+
if ($isNodeSelection(selection)) {
|
|
23830
|
+
const [node] = selection.getNodes();
|
|
23831
|
+
if ($isDecoratorNode(node)) {
|
|
23832
|
+
$selectDecoratorNode(node);
|
|
23833
|
+
}
|
|
23834
|
+
}
|
|
23835
|
+
return false;
|
|
23836
|
+
}, COMMAND_PRIORITY_CRITICAL), editor.registerCommand(CLICK_COMMAND, event => {
|
|
23837
|
+
if (event.target instanceof HTMLElement) {
|
|
23838
|
+
const decoratorRootEle = event.target.closest('[data-lexical-decorator="true"]');
|
|
23839
|
+
if (decoratorRootEle) {
|
|
23840
|
+
const key = decoratorRootEle.getAttribute('key');
|
|
23841
|
+
if (key) {
|
|
23842
|
+
const node = $getNodeByKey(key);
|
|
23843
|
+
$selectDecoratorNode(node);
|
|
23844
|
+
}
|
|
23845
|
+
}
|
|
23846
|
+
}
|
|
23847
|
+
return false;
|
|
23848
|
+
}, COMMAND_PRIORITY_LOW), editor.registerCommand(DELETE_CHARACTER_COMMAND, event => {
|
|
23800
23849
|
const selection = $getSelection();
|
|
23801
23850
|
if (selection) {
|
|
23802
23851
|
return selection.getNodes().some(node => {
|
|
@@ -24159,15 +24208,30 @@ class InternalLinkNode extends TextDecoratorNode {
|
|
|
24159
24208
|
super(key);
|
|
24160
24209
|
this.__number = number;
|
|
24161
24210
|
}
|
|
24211
|
+
|
|
24212
|
+
// get contentEditable() {
|
|
24213
|
+
// return 'true'
|
|
24214
|
+
// }
|
|
24215
|
+
|
|
24162
24216
|
exportJSON() {
|
|
24163
24217
|
return {
|
|
24164
24218
|
...super.exportJSON(),
|
|
24165
24219
|
number: this.__number
|
|
24166
24220
|
};
|
|
24167
24221
|
}
|
|
24222
|
+
exportDOM(editor) {
|
|
24223
|
+
const element = document.createElement('section');
|
|
24224
|
+
element.setAttribute('internal-link', '');
|
|
24225
|
+
element.setAttribute('data-internal-link-number', this.__number);
|
|
24226
|
+
element.textContent = this.getTextContent();
|
|
24227
|
+
return {
|
|
24228
|
+
element
|
|
24229
|
+
};
|
|
24230
|
+
}
|
|
24168
24231
|
createDOM(config, editor) {
|
|
24169
24232
|
const span = super.createDOM(config, editor);
|
|
24170
24233
|
span.setAttribute('ignoreusable', '');
|
|
24234
|
+
span.setAttribute('decorator', 'text');
|
|
24171
24235
|
return span;
|
|
24172
24236
|
}
|
|
24173
24237
|
updateDOM(prevNode, dom, config) {
|
|
@@ -24179,6 +24243,16 @@ class InternalLinkNode extends TextDecoratorNode {
|
|
|
24179
24243
|
isInline() {
|
|
24180
24244
|
return true;
|
|
24181
24245
|
}
|
|
24246
|
+
isSelected(selection) {
|
|
24247
|
+
return true;
|
|
24248
|
+
}
|
|
24249
|
+
getTextContent() {
|
|
24250
|
+
const insNode = $getInstanceNodeByNumber(this.__number);
|
|
24251
|
+
if (insNode) {
|
|
24252
|
+
return getLatestValue(insNode.__instance.value, 'insDesc') || '';
|
|
24253
|
+
}
|
|
24254
|
+
return '';
|
|
24255
|
+
}
|
|
24182
24256
|
decorate(editor, config) {
|
|
24183
24257
|
return /*#__PURE__*/jsx(InternalLinkComponent, {
|
|
24184
24258
|
editor: editor,
|
|
@@ -24304,10 +24378,11 @@ function $isPageBreakNode(node) {
|
|
|
24304
24378
|
*
|
|
24305
24379
|
*/
|
|
24306
24380
|
|
|
24307
|
-
const ParametersComponent = ({
|
|
24381
|
+
const ParametersComponent = /*#__PURE__*/React__default.forwardRef(({
|
|
24308
24382
|
nodeKey
|
|
24309
|
-
}) => {
|
|
24383
|
+
}, ref) => {
|
|
24310
24384
|
const [editor] = useLexicalComposerContext();
|
|
24385
|
+
const spanRef = useRef(null);
|
|
24311
24386
|
const [parameters, setParameters,, latestParameters] = useStore({
|
|
24312
24387
|
number: '',
|
|
24313
24388
|
value: ''
|
|
@@ -24339,10 +24414,20 @@ const ParametersComponent = ({
|
|
|
24339
24414
|
return true;
|
|
24340
24415
|
}, COMMAND_PRIORITY_EDITOR));
|
|
24341
24416
|
}, []);
|
|
24417
|
+
useImperativeHandle(ref, () => {
|
|
24418
|
+
return {
|
|
24419
|
+
getValue() {
|
|
24420
|
+
return latestParameters.current.value;
|
|
24421
|
+
}
|
|
24422
|
+
};
|
|
24423
|
+
}, []);
|
|
24342
24424
|
return /*#__PURE__*/jsx("span", {
|
|
24425
|
+
ref: spanRef,
|
|
24426
|
+
role: "button",
|
|
24427
|
+
tabIndex: 0,
|
|
24343
24428
|
children: parameters.value
|
|
24344
24429
|
});
|
|
24345
|
-
};
|
|
24430
|
+
});
|
|
24346
24431
|
|
|
24347
24432
|
/**
|
|
24348
24433
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -24357,6 +24442,8 @@ class ParametersNode extends TextDecoratorNode {
|
|
|
24357
24442
|
static collection = new Map();
|
|
24358
24443
|
/** 初始化值 */
|
|
24359
24444
|
|
|
24445
|
+
__ref = /*#__PURE__*/React__default.createRef();
|
|
24446
|
+
|
|
24360
24447
|
/** 最新的值 */
|
|
24361
24448
|
get parameters() {
|
|
24362
24449
|
return ParametersNode.collection.get(this.__parameters.number) || this.__parameters;
|
|
@@ -24380,9 +24467,19 @@ class ParametersNode extends TextDecoratorNode {
|
|
|
24380
24467
|
parameters: this.parameters
|
|
24381
24468
|
};
|
|
24382
24469
|
}
|
|
24470
|
+
exportDOM(editor) {
|
|
24471
|
+
const element = document.createElement('section');
|
|
24472
|
+
element.setAttribute('parameter', '');
|
|
24473
|
+
element.setAttribute('data-parameter', toBase64UTF8(JSON.stringify(this.parameters)));
|
|
24474
|
+
element.textContent = this.parameters.value;
|
|
24475
|
+
return {
|
|
24476
|
+
element
|
|
24477
|
+
};
|
|
24478
|
+
}
|
|
24383
24479
|
createDOM(config, editor) {
|
|
24384
24480
|
const span = super.createDOM(config, editor);
|
|
24385
24481
|
span.setAttribute('ignoreusable', '');
|
|
24482
|
+
span.setAttribute('key', this.getKey());
|
|
24386
24483
|
return span;
|
|
24387
24484
|
}
|
|
24388
24485
|
updateDOM(prevNode, dom, config) {
|
|
@@ -24394,8 +24491,12 @@ class ParametersNode extends TextDecoratorNode {
|
|
|
24394
24491
|
isInline() {
|
|
24395
24492
|
return true;
|
|
24396
24493
|
}
|
|
24494
|
+
getTextContent() {
|
|
24495
|
+
return this.__ref.current?.getValue() || '';
|
|
24496
|
+
}
|
|
24397
24497
|
decorate(editor, config) {
|
|
24398
24498
|
return /*#__PURE__*/jsx(ParametersComponent, {
|
|
24499
|
+
ref: this.__ref,
|
|
24399
24500
|
nodeKey: this.getKey()
|
|
24400
24501
|
});
|
|
24401
24502
|
}
|
|
@@ -24407,10 +24508,6 @@ function $isParametersNode(node) {
|
|
|
24407
24508
|
return node instanceof ParametersNode;
|
|
24408
24509
|
}
|
|
24409
24510
|
|
|
24410
|
-
// export function updateParameters(parameters: Parameters) {
|
|
24411
|
-
// return ParametersNode.collection.set(parameters.number, parameters);
|
|
24412
|
-
// }
|
|
24413
|
-
|
|
24414
24511
|
/**
|
|
24415
24512
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
24416
24513
|
*
|
|
@@ -25434,4 +25531,4 @@ var InlineImageComponent$1 = {
|
|
|
25434
25531
|
default: InlineImageComponent
|
|
25435
25532
|
};
|
|
25436
25533
|
|
|
25437
|
-
export { $addInstancesNode, $createBarDecoratorNode, $createCollapsibleContainerNode, $createCollapsibleContentNode, $createCollapsibleTitleNode, $createFragmentNode, $createImageNode, $createInlineImageNode, $createInstanceCodeHighlightNode, $createInstanceCodeNode, $createInstanceEquationNode, $createInstanceHeadingNode, $createInstanceHorizontalRuleNode, $createInstanceListItemNode, $createInstanceListNode, $createInstanceNode, $createInstanceParagraphNode, $createInstanceQuoteNode, $createInstanceTableNode, $createInstanceTitleNode, $createInternalLinkNode, $createKeywordNode, $createNumberDecoratorNode, $createPageBreakNode, $createParametersNode, $createPlaceholderDecoratorNode, $createTitleOnlyInstanceNode, $findNearestListItemNode, $getAllListItems, $getAnchorRootNode, $getInstanceNodeByChild, $getInstanceNodeByNumber, $getInstanceNodeKeyByNumber, $getListDepth, $getTitleNodeByChild, $getTopListNode, $handleIndent, $handleListInsertParagraph, $handleOutdent, $insertInstanceList, $isBarDecoratorNode, $isCollapsibleContainerNode, $isCollapsibleContentNode, $isCollapsibleTitleNode, $isEmptyInstanceParagraphNode, $isEmptyParagraphNode, $isImageNode, $isInInstanceTitleNode, $isInlineImageNode, $isInstanceCodeHighlightNode, $isInstanceCodeNode, $isInstanceEquationNode, $isInstanceHeadingNode, $isInstanceHorizontalRuleNode, $isInstanceListItemNode, $isInstanceListNode, $isInstanceNode, $isInstanceParagraphFormalNode, $isInstanceParagraphNode, $isInstanceQuoteNode, $isInstanceTableNode, $isInstanceTitleNode, $isInternalLinkNode, $isKeywordNode, $isLastItemInList, $isNumberDecoratorNode, $isPageBreakNode, $isParametersNode, $isPlaceholderDecoratorNode, $isRemoved, $isSelectedTitleNode, $isTextTypeNode, $nodeDowngrade, $nodeUpgrade, $removeHighestEmptyListParent, $removeList, $scrollTo, $updateRichHistoryStateMap, $updateRichInstanceContent, $updateRichInstanceTitle, $wrapInListItem, ADD_COMMENT, ADD_NEW_INSTANCE_NODE, BarDecoratorNode, COMPONENT_UPDATE, CollapsibleContainerNode, CollapsibleContentNode, CollapsibleTitleNode, DELETE_INSTANCE_NODE, DisableSelector, Fragment, INSERT_COLLAPSIBLE_COMMAND, INSERT_INS_HORIZONTAL_RULE_COMMAND, INSERT_PARAMETERS, INSTANCE_TITLE_UPDATE, ImageNode, InlineImageNode, InstanceCodeHighlightNode, InstanceCodeNode, InstanceEquationNode, InstanceHeadingNode, InstanceHorizontalRuleNode, InstanceListItemNode, InstanceListNode, InstanceNode, InstanceParagraphNode, InstanceParagraphType, InstancePlugin, InstanceQuoteNode, InstanceTableNode, InstanceTitleNode, InternalLinkNode, KeywordNode, NumberDecoratorNode, OPEN_CREATE_WINDOW, PARAMETERS_UPDATE, PageBreakNode, ParametersNode, PlaceholderDecoratorNode, SPLIT_INSTANCE_NODE, clearCache, correctedInstanceParagraph, fixedAddress, getCachedClassNameArray, getCodeLanguages, getDefaultCodeLanguage, getInstanceAttrValue, getInstanceBaseInfo, getLanguageFriendlyName, getLatestValue, getTemporaryContentText, instanceNodeMap, internalLinkNameUpdateMap, isCompleteInstance, isNestedListNode, mergeLists, mergeNextSiblingListIfSameType, nodeMoveDown, nodeMoveUp, normalizeCodeLang, numberNodeKey, paragraphSymbol, registerCodeHighlighting, setDisable, setInstanceAttrValue, setTemporaryContentText, updateChildrenListItemValue, updateRelatedInternalLink, useContentEditable };
|
|
25534
|
+
export { $addInstancesNode, $createBarDecoratorNode, $createCollapsibleContainerNode, $createCollapsibleContentNode, $createCollapsibleTitleNode, $createFragmentNode, $createImageNode, $createInlineImageNode, $createInstanceCodeHighlightNode, $createInstanceCodeNode, $createInstanceEquationNode, $createInstanceHeadingNode, $createInstanceHorizontalRuleNode, $createInstanceListItemNode, $createInstanceListNode, $createInstanceNode, $createInstanceParagraphNode, $createInstanceQuoteNode, $createInstanceTableNode, $createInstanceTitleNode, $createInternalLinkNode, $createKeywordNode, $createNumberDecoratorNode, $createPageBreakNode, $createParametersNode, $createPlaceholderDecoratorNode, $createTitleOnlyInstanceNode, $findNearestListItemNode, $getAllListItems, $getAnchorRootNode, $getInstanceNodeByChild, $getInstanceNodeByNumber, $getInstanceNodeKeyByNumber, $getListDepth, $getTitleNodeByChild, $getTopListNode, $handleIndent, $handleListInsertParagraph, $handleOutdent, $insertInstanceList, $isBarDecoratorNode, $isCollapsibleContainerNode, $isCollapsibleContentNode, $isCollapsibleTitleNode, $isEmptyInstanceParagraphNode, $isEmptyParagraphNode, $isImageNode, $isInInstanceTitleNode, $isInlineImageNode, $isInstanceCodeHighlightNode, $isInstanceCodeNode, $isInstanceEquationNode, $isInstanceHeadingNode, $isInstanceHorizontalRuleNode, $isInstanceListItemNode, $isInstanceListNode, $isInstanceNode, $isInstanceParagraphFormalNode, $isInstanceParagraphNode, $isInstanceQuoteNode, $isInstanceTableNode, $isInstanceTitleNode, $isInternalLinkNode, $isKeywordNode, $isLastItemInList, $isNumberDecoratorNode, $isPageBreakNode, $isParametersNode, $isPlaceholderDecoratorNode, $isRemoved, $isSelectedTitleNode, $isTextTypeNode, $nodeDowngrade, $nodeUpgrade, $removeHighestEmptyListParent, $removeList, $scrollTo, $selectDecoratorNode, $updateRichHistoryStateMap, $updateRichInstanceContent, $updateRichInstanceTitle, $wrapInListItem, ADD_COMMENT, ADD_NEW_INSTANCE_NODE, BarDecoratorNode, COMPONENT_UPDATE, CollapsibleContainerNode, CollapsibleContentNode, CollapsibleTitleNode, DELETE_INSTANCE_NODE, DisableSelector, Fragment, INSERT_COLLAPSIBLE_COMMAND, INSERT_INS_HORIZONTAL_RULE_COMMAND, INSERT_PARAMETERS, INSTANCE_TITLE_UPDATE, ImageNode, InlineImageNode, InstanceCodeHighlightNode, InstanceCodeNode, InstanceEquationNode, InstanceHeadingNode, InstanceHorizontalRuleNode, InstanceListItemNode, InstanceListNode, InstanceNode, InstanceParagraphNode, InstanceParagraphType, InstancePlugin, InstanceQuoteNode, InstanceTableNode, InstanceTitleNode, InternalLinkNode, KeywordNode, NumberDecoratorNode, OPEN_CREATE_WINDOW, PARAMETERS_UPDATE, PageBreakNode, ParametersNode, PlaceholderDecoratorNode, PrismTokenizer, SPLIT_INSTANCE_NODE, clearCache, codeNodeTransform, correctedInstanceParagraph, fixedAddress, getCachedClassNameArray, getCodeLanguages, getDefaultCodeLanguage, getInstanceAttrValue, getInstanceBaseInfo, getLanguageFriendlyName, getLatestValue, getTemporaryContentText, instanceNodeMap, internalLinkNameUpdateMap, isCompleteInstance, isNestedListNode, mergeLists, mergeNextSiblingListIfSameType, nodeMoveDown, nodeMoveUp, normalizeCodeLang, numberNodeKey, paragraphSymbol, registerCodeHighlighting, setDisable, setInstanceAttrValue, setTemporaryContentText, updateChildrenListItemValue, updateRelatedInternalLink, useContentEditable };
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"instance"
|
|
8
8
|
],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.0.
|
|
10
|
+
"version": "0.0.15",
|
|
11
11
|
"types": "index.d.ts",
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"@lexical/table": "^0.30.0",
|
|
24
24
|
"@lexical/utils": "^0.30.0",
|
|
25
25
|
"lexical": "0.30.0",
|
|
26
|
-
"onchain-lexical-context": "^0.0.
|
|
27
|
-
"onchain-lexical-markdown": "^0.0.
|
|
28
|
-
"onchain-lexical-ui": "^0.0.
|
|
29
|
-
"onchain-utility": "^0.0.
|
|
26
|
+
"onchain-lexical-context": "^0.0.13",
|
|
27
|
+
"onchain-lexical-markdown": "^0.0.14",
|
|
28
|
+
"onchain-lexical-ui": "^0.0.13",
|
|
29
|
+
"onchain-utility": "^0.0.11"
|
|
30
30
|
},
|
|
31
31
|
"sideEffects": false,
|
|
32
32
|
"exports": {
|
|
@@ -212,7 +212,7 @@ function $textNodeTransform(
|
|
|
212
212
|
// if node's parent is a code node and run highlighting if so
|
|
213
213
|
const parentNode = node.getParent();
|
|
214
214
|
if ($isInstanceCodeNode(parentNode)) {
|
|
215
|
-
codeNodeTransform(parentNode,
|
|
215
|
+
codeNodeTransform(parentNode, null, tokenizer);
|
|
216
216
|
} else if ($isInstanceCodeHighlightNode(node)) {
|
|
217
217
|
// When code block converted into paragraph or other element
|
|
218
218
|
// code highlight nodes converted back to normal text
|
|
@@ -254,14 +254,14 @@ function updateCodeGutter(node: InstanceCodeNode, editor: LexicalEditor): void {
|
|
|
254
254
|
|
|
255
255
|
const nodesCurrentlyHighlighting = new Set();
|
|
256
256
|
|
|
257
|
-
function codeNodeTransform(
|
|
257
|
+
export function codeNodeTransform(
|
|
258
258
|
node: InstanceCodeNode,
|
|
259
|
-
editor: LexicalEditor,
|
|
259
|
+
editor: LexicalEditor | null,
|
|
260
260
|
tokenizer: Tokenizer,
|
|
261
|
+
isEnforcement?: boolean
|
|
261
262
|
) {
|
|
262
263
|
const nodeKey = node.getKey();
|
|
263
|
-
|
|
264
|
-
if (nodesCurrentlyHighlighting.has(nodeKey)) {
|
|
264
|
+
if (nodesCurrentlyHighlighting.has(nodeKey) && !isEnforcement) {
|
|
265
265
|
return;
|
|
266
266
|
}
|
|
267
267
|
|
|
@@ -275,42 +275,48 @@ function codeNodeTransform(
|
|
|
275
275
|
// Using nested update call to pass `skipTransforms` since we don't want
|
|
276
276
|
// each individual InstanceCodeHighlightNode to be transformed again as it's already
|
|
277
277
|
// in its final state
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
278
|
+
// eslint-disable-next-line @lexical/rules-of-lexical
|
|
279
|
+
const transform = () => {
|
|
280
|
+
$updateAndRetainSelection(nodeKey, () => {
|
|
281
|
+
const currentNode = $getNodeByKey(nodeKey);
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
if (!$isInstanceCodeNode(currentNode) || !currentNode.isAttached()) {
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if (from !== to || nodesForReplacement.length) {
|
|
300
|
-
node.splice(from, to - from, nodesForReplacement);
|
|
301
|
-
return true;
|
|
302
|
-
}
|
|
287
|
+
const code = currentNode.getTextContent();
|
|
288
|
+
const tokens = tokenizer.tokenize(
|
|
289
|
+
code,
|
|
290
|
+
currentNode.getLanguage() || tokenizer.defaultLanguage,
|
|
291
|
+
);
|
|
292
|
+
const highlightNodes = $getHighlightNodes(tokens);
|
|
293
|
+
const diffRange = getDiffRange(
|
|
294
|
+
currentNode.getChildren(),
|
|
295
|
+
highlightNodes,
|
|
296
|
+
);
|
|
297
|
+
const {from, to, nodesForReplacement} = diffRange;
|
|
303
298
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
299
|
+
if (from !== to || nodesForReplacement.length) {
|
|
300
|
+
node.splice(from, to - from, nodesForReplacement);
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return false;
|
|
305
|
+
});
|
|
306
|
+
};
|
|
307
|
+
if (editor) {
|
|
308
|
+
editor.update(transform,
|
|
309
|
+
{
|
|
310
|
+
onUpdate: () => {
|
|
311
|
+
nodesCurrentlyHighlighting.delete(nodeKey);
|
|
312
|
+
},
|
|
313
|
+
skipTransforms: true,
|
|
310
314
|
},
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
);
|
|
316
|
+
} else {
|
|
317
|
+
transform();
|
|
318
|
+
}
|
|
319
|
+
|
|
314
320
|
}
|
|
315
321
|
|
|
316
322
|
function $getHighlightNodes(
|
|
@@ -842,7 +848,7 @@ export function registerCodeHighlighting(
|
|
|
842
848
|
{skipInitialization: false},
|
|
843
849
|
),
|
|
844
850
|
editor.registerNodeTransform(InstanceCodeNode, (node) =>
|
|
845
|
-
codeNodeTransform(node,
|
|
851
|
+
codeNodeTransform(node, null, tokenizer as Tokenizer),
|
|
846
852
|
),
|
|
847
853
|
editor.registerNodeTransform(TextNode, (node) =>
|
|
848
854
|
$textNodeTransform(node, editor, tokenizer as Tokenizer),
|
package/src/collapsible/index.ts
CHANGED
package/src/equation/index.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import type {JSX} from 'react';
|
|
|
19
19
|
|
|
20
20
|
import katex from 'katex';
|
|
21
21
|
import {$applyNodeReplacement, DecoratorNode, DOMExportOutput} from 'lexical';
|
|
22
|
+
import { toBase64UTF8 } from 'onchain-utility/base64';
|
|
22
23
|
import * as React from 'react';
|
|
23
24
|
|
|
24
25
|
const EquationComponent = React.lazy(() => import('./EquationComponent'));
|
|
@@ -89,9 +90,9 @@ export class InstanceEquationNode extends DecoratorNode<JSX.Element> {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
exportDOM(): DOMExportOutput {
|
|
92
|
-
const element = document.createElement('
|
|
93
|
+
const element = document.createElement('equation');
|
|
93
94
|
// Encode the equation as base64 to avoid issues with special characters
|
|
94
|
-
const equation =
|
|
95
|
+
const equation = toBase64UTF8(this.__equation);
|
|
95
96
|
element.setAttribute('data-lexical-equation', equation);
|
|
96
97
|
element.setAttribute('data-lexical-inline', `${this.__inline}`);
|
|
97
98
|
katex.render(this.__equation, element, {
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,7 @@ export {
|
|
|
21
21
|
$isInstanceCodeNode,
|
|
22
22
|
InstanceCodeNode,
|
|
23
23
|
} from './code';
|
|
24
|
-
export {registerCodeHighlighting} from './code/codeHighlighter';
|
|
24
|
+
export {codeNodeTransform, PrismTokenizer,registerCodeHighlighting} from './code/codeHighlighter';
|
|
25
25
|
export {
|
|
26
26
|
$createInstanceCodeHighlightNode,
|
|
27
27
|
$isInstanceCodeHighlightNode,
|
package/src/instancePlugin.ts
CHANGED
|
@@ -21,9 +21,12 @@ import {
|
|
|
21
21
|
$createTextNode,
|
|
22
22
|
$getNodeByKey,
|
|
23
23
|
$getSelection,
|
|
24
|
+
$isDecoratorNode,
|
|
24
25
|
$isElementNode,
|
|
26
|
+
$isNodeSelection,
|
|
25
27
|
$isRangeSelection,
|
|
26
28
|
$setSelection,
|
|
29
|
+
CLICK_COMMAND,
|
|
27
30
|
COMMAND_PRIORITY_CRITICAL,
|
|
28
31
|
COMMAND_PRIORITY_LOW,
|
|
29
32
|
DELETE_CHARACTER_COMMAND,
|
|
@@ -31,6 +34,7 @@ import {
|
|
|
31
34
|
exportNodeToJSON,
|
|
32
35
|
INSERT_PARAGRAPH_COMMAND,
|
|
33
36
|
LexicalNode,
|
|
37
|
+
SELECTION_CHANGE_COMMAND,
|
|
34
38
|
SerializedLexicalNode,
|
|
35
39
|
} from 'lexical';
|
|
36
40
|
import {getStorageSerializedString} from 'onchain-lexical-markdown';
|
|
@@ -59,12 +63,18 @@ import {
|
|
|
59
63
|
$registerInstanceParagraphNodeTransform,
|
|
60
64
|
} from './paragraph';
|
|
61
65
|
import {$registerInstanceHeadingNodeTransform} from './paragraph/title';
|
|
66
|
+
import {ParametersNode} from './parameters';
|
|
62
67
|
import {
|
|
63
68
|
$createInstanceTableNode,
|
|
64
69
|
$isInstanceTableNode,
|
|
65
70
|
$registerTableCommand,
|
|
66
71
|
} from './table';
|
|
67
|
-
import {
|
|
72
|
+
import {
|
|
73
|
+
$addInstancesNode,
|
|
74
|
+
$selectDecoratorNode,
|
|
75
|
+
clearCache,
|
|
76
|
+
setTemporaryContentText,
|
|
77
|
+
} from './utils';
|
|
68
78
|
|
|
69
79
|
export const InstancePlugin: React.FC<PluginProps> = (props) => {
|
|
70
80
|
const {placeholder} = props;
|
|
@@ -79,6 +89,39 @@ export const InstancePlugin: React.FC<PluginProps> = (props) => {
|
|
|
79
89
|
$registerNumberDecoratorDomUpdate(editor),
|
|
80
90
|
$registerTableCommand(editor),
|
|
81
91
|
// $selectionChange(editor, setSelectedInstance),
|
|
92
|
+
editor.registerCommand(
|
|
93
|
+
SELECTION_CHANGE_COMMAND,
|
|
94
|
+
() => {
|
|
95
|
+
const selection = $getSelection();
|
|
96
|
+
if ($isNodeSelection(selection)) {
|
|
97
|
+
const [node] = selection.getNodes();
|
|
98
|
+
if ($isDecoratorNode(node)) {
|
|
99
|
+
$selectDecoratorNode(node);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
},
|
|
104
|
+
COMMAND_PRIORITY_CRITICAL,
|
|
105
|
+
),
|
|
106
|
+
editor.registerCommand(
|
|
107
|
+
CLICK_COMMAND,
|
|
108
|
+
(event: MouseEvent) => {
|
|
109
|
+
if (event.target instanceof HTMLElement) {
|
|
110
|
+
const decoratorRootEle = event.target.closest(
|
|
111
|
+
'[data-lexical-decorator="true"]',
|
|
112
|
+
);
|
|
113
|
+
if (decoratorRootEle) {
|
|
114
|
+
const key = decoratorRootEle.getAttribute('key');
|
|
115
|
+
if (key) {
|
|
116
|
+
const node = $getNodeByKey<ParametersNode>(key);
|
|
117
|
+
$selectDecoratorNode(node);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
},
|
|
123
|
+
COMMAND_PRIORITY_LOW,
|
|
124
|
+
),
|
|
82
125
|
editor.registerCommand(
|
|
83
126
|
DELETE_CHARACTER_COMMAND,
|
|
84
127
|
(event) => {
|
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
$applyNodeReplacement,
|
|
11
|
+
BaseSelection,
|
|
12
|
+
DOMExportOutput,
|
|
11
13
|
EditorConfig,
|
|
12
14
|
LexicalEditor,
|
|
15
|
+
LexicalNode,
|
|
13
16
|
SerializedTextDecoratorNode,
|
|
14
17
|
Spread,
|
|
15
18
|
TextDecoratorNode,
|
|
16
19
|
} from 'lexical';
|
|
17
20
|
import React from 'react';
|
|
18
21
|
|
|
22
|
+
import {$getInstanceNodeByNumber, getLatestValue} from '../utils';
|
|
19
23
|
import InternalLinkComponent from './internalLinkComponent';
|
|
20
24
|
|
|
21
25
|
export type SerializedInternalNode = Spread<
|
|
@@ -45,6 +49,10 @@ export class InternalLinkNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
45
49
|
this.__number = number;
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
// get contentEditable() {
|
|
53
|
+
// return 'true'
|
|
54
|
+
// }
|
|
55
|
+
|
|
48
56
|
exportJSON(): SerializedInternalNode {
|
|
49
57
|
return {
|
|
50
58
|
...super.exportJSON(),
|
|
@@ -52,9 +60,18 @@ export class InternalLinkNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
52
60
|
};
|
|
53
61
|
}
|
|
54
62
|
|
|
63
|
+
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
|
64
|
+
const element = document.createElement('section');
|
|
65
|
+
element.setAttribute('internal-link', '');
|
|
66
|
+
element.setAttribute('data-internal-link-number', this.__number);
|
|
67
|
+
element.textContent = this.getTextContent();
|
|
68
|
+
return {element};
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
createDOM(config: EditorConfig, editor?: LexicalEditor): HTMLElement {
|
|
56
72
|
const span = super.createDOM(config, editor);
|
|
57
73
|
span.setAttribute('ignoreusable', '');
|
|
74
|
+
span.setAttribute('decorator', 'text');
|
|
58
75
|
return span;
|
|
59
76
|
}
|
|
60
77
|
|
|
@@ -70,6 +87,18 @@ export class InternalLinkNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
70
87
|
return true;
|
|
71
88
|
}
|
|
72
89
|
|
|
90
|
+
isSelected(selection?: null | BaseSelection): boolean {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getTextContent(): string {
|
|
95
|
+
const insNode = $getInstanceNodeByNumber(this.__number);
|
|
96
|
+
if (insNode) {
|
|
97
|
+
return getLatestValue(insNode.__instance.value, 'insDesc') || '';
|
|
98
|
+
}
|
|
99
|
+
return '';
|
|
100
|
+
}
|
|
101
|
+
|
|
73
102
|
decorate(editor: LexicalEditor, config: EditorConfig): JSX.Element {
|
|
74
103
|
return (
|
|
75
104
|
<InternalLinkComponent
|
|
@@ -88,7 +117,7 @@ export function $createInternalLinkNode(number: string): InternalLinkNode {
|
|
|
88
117
|
}
|
|
89
118
|
|
|
90
119
|
export function $isInternalLinkNode(
|
|
91
|
-
node:
|
|
120
|
+
node: LexicalNode | null | undefined,
|
|
92
121
|
): node is InternalLinkNode {
|
|
93
122
|
return node instanceof InternalLinkNode;
|
|
94
123
|
}
|
package/src/list/index.ts
CHANGED
package/src/parameters/index.tsx
CHANGED
|
@@ -8,16 +8,22 @@
|
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
$applyNodeReplacement,
|
|
11
|
+
DOMConversionMap,
|
|
12
|
+
DOMExportOutput,
|
|
11
13
|
EditorConfig,
|
|
12
14
|
LexicalEditor,
|
|
13
15
|
LexicalNode,
|
|
14
16
|
SerializedTextDecoratorNode,
|
|
17
|
+
SerializedTextNode,
|
|
15
18
|
Spread,
|
|
16
19
|
TextDecoratorNode,
|
|
20
|
+
TextNode,
|
|
17
21
|
} from 'lexical';
|
|
22
|
+
import {toBase64UTF8} from 'onchain-utility/base64';
|
|
18
23
|
import React from 'react';
|
|
19
24
|
|
|
20
25
|
import ParametersComponent from './parametersComponent';
|
|
26
|
+
import {ParametersRef} from './types';
|
|
21
27
|
|
|
22
28
|
export interface Parameters {
|
|
23
29
|
value: string;
|
|
@@ -38,6 +44,8 @@ export class ParametersNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
38
44
|
/** 初始化值 */
|
|
39
45
|
__parameters: Parameters;
|
|
40
46
|
|
|
47
|
+
__ref = React.createRef<ParametersRef>();
|
|
48
|
+
|
|
41
49
|
/** 最新的值 */
|
|
42
50
|
get parameters() {
|
|
43
51
|
return (
|
|
@@ -71,10 +79,18 @@ export class ParametersNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
71
79
|
parameters: this.parameters,
|
|
72
80
|
};
|
|
73
81
|
}
|
|
82
|
+
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
|
83
|
+
const element = document.createElement('section');
|
|
84
|
+
element.setAttribute('parameter', '');
|
|
85
|
+
element.setAttribute('data-parameter', toBase64UTF8(JSON.stringify(this.parameters)));
|
|
86
|
+
element.textContent = this.parameters.value;
|
|
87
|
+
return {element};
|
|
88
|
+
}
|
|
74
89
|
|
|
75
90
|
createDOM(config: EditorConfig, editor?: LexicalEditor): HTMLElement {
|
|
76
91
|
const span = super.createDOM(config, editor);
|
|
77
92
|
span.setAttribute('ignoreusable', '');
|
|
93
|
+
span.setAttribute('key', this.getKey());
|
|
78
94
|
return span;
|
|
79
95
|
}
|
|
80
96
|
|
|
@@ -90,8 +106,12 @@ export class ParametersNode extends TextDecoratorNode<React.ReactNode> {
|
|
|
90
106
|
return true;
|
|
91
107
|
}
|
|
92
108
|
|
|
109
|
+
getTextContent(): string {
|
|
110
|
+
return this.__ref.current?.getValue() || '';
|
|
111
|
+
}
|
|
112
|
+
|
|
93
113
|
decorate(editor: LexicalEditor, config: EditorConfig): JSX.Element {
|
|
94
|
-
return <ParametersComponent nodeKey={this.getKey()} />;
|
|
114
|
+
return <ParametersComponent ref={this.__ref} nodeKey={this.getKey()} />;
|
|
95
115
|
}
|
|
96
116
|
}
|
|
97
117
|
|
|
@@ -108,3 +128,30 @@ export function $isParametersNode(
|
|
|
108
128
|
// export function updateParameters(parameters: Parameters) {
|
|
109
129
|
// return ParametersNode.collection.set(parameters.number, parameters);
|
|
110
130
|
// }
|
|
131
|
+
|
|
132
|
+
class TestNode extends TextNode {
|
|
133
|
+
static getType(): string {
|
|
134
|
+
return 'Parameters';
|
|
135
|
+
}
|
|
136
|
+
static clone(node: TestNode): TestNode {
|
|
137
|
+
return new TestNode(node.__text, node.__key);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static importDOM(): DOMConversionMap | null {
|
|
141
|
+
return TextNode.importDOM();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static importJSON(serializedNode: SerializedTextNode): TextNode {
|
|
145
|
+
return $createTestNode().updateFromJSON(serializedNode);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function $createTestNode(text = ''): TestNode {
|
|
150
|
+
return $applyNodeReplacement(new TestNode(text));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function $isTestNode(
|
|
154
|
+
node: LexicalNode | null | undefined,
|
|
155
|
+
): node is TestNode {
|
|
156
|
+
return node instanceof TestNode;
|
|
157
|
+
}
|
|
@@ -10,46 +10,66 @@ import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
|
10
10
|
import {mergeRegister} from '@lexical/utils';
|
|
11
11
|
import {$getNodeByKey, COMMAND_PRIORITY_EDITOR} from 'lexical';
|
|
12
12
|
import {useStore} from 'onchain-utility/hooks';
|
|
13
|
-
import {useEffect} from 'react';
|
|
13
|
+
import React, {useEffect, useImperativeHandle, useRef} from 'react';
|
|
14
14
|
|
|
15
15
|
import {PARAMETERS_UPDATE} from '../const';
|
|
16
16
|
import {$isParametersNode} from '.';
|
|
17
|
+
import {ParametersRef} from './types';
|
|
17
18
|
|
|
18
|
-
const ParametersComponent =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
editor.read(() => {
|
|
27
|
-
const node = $getNodeByKey(nodeKey);
|
|
28
|
-
if ($isParametersNode(node)) {
|
|
29
|
-
setParameters(node.parameters);
|
|
30
|
-
}
|
|
19
|
+
const ParametersComponent = React.forwardRef<ParametersRef, {nodeKey: string}>(
|
|
20
|
+
({nodeKey}, ref) => {
|
|
21
|
+
const [editor] = useLexicalComposerContext();
|
|
22
|
+
const spanRef = useRef<HTMLSpanElement>(null);
|
|
23
|
+
const [parameters, setParameters, , latestParameters] = useStore({
|
|
24
|
+
number: '',
|
|
25
|
+
value: '',
|
|
31
26
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
editor.read(() => {
|
|
30
|
+
const node = $getNodeByKey(nodeKey);
|
|
31
|
+
if ($isParametersNode(node)) {
|
|
32
|
+
setParameters(node.parameters);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return mergeRegister(
|
|
36
|
+
editor.registerCommand(
|
|
37
|
+
PARAMETERS_UPDATE,
|
|
38
|
+
({number, value}) => {
|
|
39
|
+
const latest = latestParameters.current;
|
|
40
|
+
if (number !== latest.number) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const node = $getNodeByKey(nodeKey);
|
|
44
|
+
if ($isParametersNode(node)) {
|
|
45
|
+
setParameters({value});
|
|
46
|
+
Object.assign(node.parameters, {value});
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
COMMAND_PRIORITY_EDITOR,
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
55
|
+
useImperativeHandle(
|
|
56
|
+
ref,
|
|
57
|
+
() => {
|
|
58
|
+
return {
|
|
59
|
+
getValue() {
|
|
60
|
+
return latestParameters.current.value;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
[],
|
|
49
65
|
);
|
|
50
|
-
}, []);
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
}
|
|
67
|
+
return (
|
|
68
|
+
<span ref={spanRef} role="button" tabIndex={0}>
|
|
69
|
+
{parameters.value}
|
|
70
|
+
</span>
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
);
|
|
54
74
|
|
|
55
75
|
export default ParametersComponent;
|
package/src/utils.ts
CHANGED
|
@@ -15,12 +15,16 @@ import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
|
15
15
|
import {$isQuoteNode} from '@lexical/rich-text';
|
|
16
16
|
import {$findMatchingParent} from '@lexical/utils';
|
|
17
17
|
import {
|
|
18
|
+
$createRangeSelection,
|
|
18
19
|
$getEditor,
|
|
19
20
|
$getNodeByKey,
|
|
20
21
|
$getSelection,
|
|
21
22
|
$isElementNode,
|
|
22
23
|
$isRootNode,
|
|
24
|
+
$isTextNode,
|
|
25
|
+
$setSelection,
|
|
23
26
|
COMMAND_PRIORITY_CRITICAL,
|
|
27
|
+
DecoratorNode,
|
|
24
28
|
type EditorThemeClasses,
|
|
25
29
|
ElementNode,
|
|
26
30
|
LexicalEditor,
|
|
@@ -566,3 +570,38 @@ export function $addInstancesNode({
|
|
|
566
570
|
}
|
|
567
571
|
}
|
|
568
572
|
}
|
|
573
|
+
|
|
574
|
+
export function $selectDecoratorNode<T>(node?: DecoratorNode<T> | null) {
|
|
575
|
+
if (node) {
|
|
576
|
+
const [previous, next] = [node.getPreviousSibling(), node.getNextSibling()];
|
|
577
|
+
const rangeSelection = $createRangeSelection();
|
|
578
|
+
if (previous) {
|
|
579
|
+
const isText = $isTextNode(previous);
|
|
580
|
+
rangeSelection.anchor.set(
|
|
581
|
+
isText ? previous.getKey() : node.getParent()!.getKey(),
|
|
582
|
+
isText
|
|
583
|
+
? previous.getTextContentSize()
|
|
584
|
+
: node.getPreviousSiblings().length,
|
|
585
|
+
isText ? 'text' : 'element',
|
|
586
|
+
);
|
|
587
|
+
} else {
|
|
588
|
+
const parent = node.getParent()!;
|
|
589
|
+
rangeSelection.anchor.set(parent.getKey(), 0, 'element');
|
|
590
|
+
}
|
|
591
|
+
if (next) {
|
|
592
|
+
rangeSelection.focus.set(
|
|
593
|
+
next.getKey(),
|
|
594
|
+
0,
|
|
595
|
+
$isTextNode(next) ? 'text' : 'element',
|
|
596
|
+
);
|
|
597
|
+
} else {
|
|
598
|
+
const parent = node.getParent()!;
|
|
599
|
+
rangeSelection.focus.set(
|
|
600
|
+
parent.getKey(),
|
|
601
|
+
node.getPreviousSiblings().length + 1,
|
|
602
|
+
'element',
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
$setSelection(rangeSelection);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
File without changes
|