@lexical/list 0.50.1-nightly.20260916.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LexicalList.dev.js +318 -42
- package/dist/LexicalList.js.flow +23 -2
- package/dist/LexicalList.prod.js +1 -1
- package/dist/LexicalListGeneratedJSON.d.ts +28 -0
- package/dist/LexicalListItemNode.d.ts +30 -5
- package/dist/LexicalListNode.d.ts +30 -5
- package/package.json +6 -6
- package/src/LexicalListGeneratedJSON.ts +365 -0
- package/src/LexicalListItemNode.ts +59 -26
- package/src/LexicalListNode.ts +54 -30
package/dist/LexicalList.dev.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { $getNearestNodeOfType, calculateZoomLevel } from '@lexical/utils';
|
|
10
|
-
import { $getSelection, $isRangeSelection, $isTextNode, $isRootOrShadowRoot, $createParagraphNode, $copyNode, $isElementNode, $getSlotHost, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, $applyNodeReplacement, ElementNode, buildImportMap, $getSiblingCaret, $insertNodeToNearestRootAtCaret, $rewindSiblingCaret, $getDocument, setDOMStyleFromCSS, isHTMLElement, $isParagraphNode, $setFormatFromDOM, $setDirectionFromDOM, normalizeClassNames, removeClassNamesFromElement, addClassNamesToElement, getStyleObjectFromCSS, createCommand, mergeRegister, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_SPACE_COMMAND, $getNearestNodeFromDOMNode, KEY_ARROW_LEFT_COMMAND, $findMatchingParent, getActiveElement, registerEventListeners, IS_FIREFOX, registerEventListener, getNearestEditorFromDOMNode, $addUpdateTag, SKIP_SELECTION_FOCUS_TAG, SKIP_DOM_SELECTION_TAG, $createLineBreakNode, $getNodeByKey, INSERT_PARAGRAPH_COMMAND, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_BEFORE_EDITOR, TextNode } from 'lexical';
|
|
10
|
+
import { $getSelection, $isRangeSelection, $isTextNode, $isRootOrShadowRoot, $createParagraphNode, $copyNode, $isElementNode, $getSlotHost, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, getterTableOf, setterTableOf, setterDefaultOf, aliasTableOf, $applyNodeReplacement, ElementNode, buildImportMap, $getSiblingCaret, $insertNodeToNearestRootAtCaret, $rewindSiblingCaret, $getDocument, setDOMStyleFromCSS, isHTMLElement, $isParagraphNode, nodeSchema, withField, numberValue, withAccessors, optional, booleanValue, $setFormatFromDOM, $setDirectionFromDOM, normalizeClassNames, removeClassNamesFromElement, addClassNamesToElement, getStyleObjectFromCSS, enumValue, aliasedValue, createCommand, mergeRegister, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_SPACE_COMMAND, $getNearestNodeFromDOMNode, KEY_ARROW_LEFT_COMMAND, $findMatchingParent, getActiveElement, registerEventListeners, IS_FIREFOX, registerEventListener, getNearestEditorFromDOMNode, $addUpdateTag, SKIP_SELECTION_FOCUS_TAG, SKIP_DOM_SELECTION_TAG, $createLineBreakNode, $getNodeByKey, INSERT_PARAGRAPH_COMMAND, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_BEFORE_EDITOR, TextNode } from 'lexical';
|
|
11
11
|
import { effect } from '@lexical/extension/signals';
|
|
12
12
|
import { namedSignals } from '@lexical/extension/namedSignals';
|
|
13
13
|
import { sel, isElementOfTag, $propagateTextAlignToBlockChildren, $isBlockLevel, CoreImportExtension, DOMImportExtension, ImportOverlays, defineOverlayRules, createImportState, InlineSchema } from '@lexical/html';
|
|
@@ -604,6 +604,269 @@ function $handleListInsertParagraph(restoreNumbering = false) {
|
|
|
604
604
|
return true;
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
609
|
+
*
|
|
610
|
+
* This source code is licensed under the MIT license found in the
|
|
611
|
+
* LICENSE file in the root directory of this source tree.
|
|
612
|
+
*
|
|
613
|
+
*/
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
// The JSON number grammar, anchored, matching numberValue: `Number()` alone
|
|
617
|
+
// reads '0x10' as 16 and '' as 0, and neither is a shape a JSON encoder
|
|
618
|
+
// produces. Emitted from the same source the codegen verified against, so the
|
|
619
|
+
// two cannot be different functions.
|
|
620
|
+
const JSON_NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
621
|
+
function num(v, d) {
|
|
622
|
+
if (typeof v === 'number') {
|
|
623
|
+
return Number.isFinite(v) ? v : d;
|
|
624
|
+
}
|
|
625
|
+
if (typeof v !== 'string' || !JSON_NUMBER.test(v)) {
|
|
626
|
+
return d;
|
|
627
|
+
}
|
|
628
|
+
const n = Number(v);
|
|
629
|
+
return Number.isFinite(n) ? n : d;
|
|
630
|
+
}
|
|
631
|
+
function numC(v, d, min, max, integer) {
|
|
632
|
+
const n = num(v, d);
|
|
633
|
+
return n >= min && n <= max && (false || Number.isInteger(n)) ? n : d;
|
|
634
|
+
}
|
|
635
|
+
function numK(v, d, min, max, integer) {
|
|
636
|
+
const n = num(v, NaN);
|
|
637
|
+
if (!Number.isFinite(n) || !Number.isInteger(n)) {
|
|
638
|
+
return d;
|
|
639
|
+
}
|
|
640
|
+
return n < min ? min : n > max ? max : n;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* ListNode's schema-declared fields, for a clone. Generated from that
|
|
645
|
+
* schema; do not edit by hand.
|
|
646
|
+
*
|
|
647
|
+
* @internal
|
|
648
|
+
*/
|
|
649
|
+
function afterCloneListNode(node, prevNode) {
|
|
650
|
+
node.__listType = prevNode.__listType;
|
|
651
|
+
node.__start = prevNode.__start;
|
|
652
|
+
node.__tag = prevNode.__tag;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/** ListNode's generated implementations, for its `$config`. @internal */
|
|
656
|
+
const GENERATED_LIST = fields => {
|
|
657
|
+
const LIST_FORMAT_GETTER = getterTableOf(fields, 'format');
|
|
658
|
+
const LIST_FORMAT_SETTER = setterTableOf(fields, 'format');
|
|
659
|
+
const LIST_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format');
|
|
660
|
+
const LIST_LISTTYPE_ALIAS = aliasTableOf(fields, 'listType', 0);
|
|
661
|
+
|
|
662
|
+
/** Generated from ListNode's serialization schema. Do not edit by hand. */
|
|
663
|
+
function exportListNode(node) {
|
|
664
|
+
const textFormat = node.__textFormat;
|
|
665
|
+
const textStyle = node.__textStyle;
|
|
666
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
667
|
+
return {
|
|
668
|
+
children: [],
|
|
669
|
+
listType: node.__listType,
|
|
670
|
+
start: node.__start,
|
|
671
|
+
tag: node.__tag,
|
|
672
|
+
direction: node.__dir,
|
|
673
|
+
format: LIST_FORMAT_GETTER[node.__format],
|
|
674
|
+
indent: node.__indent,
|
|
675
|
+
textFormat: textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
|
|
676
|
+
textStyle: textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
|
|
677
|
+
type: node.__type,
|
|
678
|
+
version: 1
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/** Generated from ListNode's serialization schema. Do not edit by hand. */
|
|
683
|
+
function exportCompactListNode(node) {
|
|
684
|
+
const textFormat = node.__textFormat;
|
|
685
|
+
const textStyle = node.__textStyle;
|
|
686
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
687
|
+
const json = {
|
|
688
|
+
type: node.__type,
|
|
689
|
+
children: []
|
|
690
|
+
};
|
|
691
|
+
const listType = node.__listType;
|
|
692
|
+
if (listType !== undefined && listType !== 'number') {
|
|
693
|
+
json.listType = listType;
|
|
694
|
+
}
|
|
695
|
+
const start = node.__start;
|
|
696
|
+
if (start !== undefined && start !== 1) {
|
|
697
|
+
json.start = start;
|
|
698
|
+
}
|
|
699
|
+
const direction = node.__dir;
|
|
700
|
+
if (direction != null) {
|
|
701
|
+
json.direction = direction;
|
|
702
|
+
}
|
|
703
|
+
const format = LIST_FORMAT_GETTER[node.__format];
|
|
704
|
+
if (format !== undefined && format !== '') {
|
|
705
|
+
json.format = format;
|
|
706
|
+
}
|
|
707
|
+
const indent = node.__indent;
|
|
708
|
+
if (indent !== undefined && indent !== 0) {
|
|
709
|
+
json.indent = indent;
|
|
710
|
+
}
|
|
711
|
+
if (textFormat !== undefined && textFormat !== 0 && shouldSerializeTextStyles) {
|
|
712
|
+
json.textFormat = textFormat;
|
|
713
|
+
}
|
|
714
|
+
if (textStyle !== undefined && textStyle !== '' && shouldSerializeTextStyles) {
|
|
715
|
+
json.textStyle = textStyle;
|
|
716
|
+
}
|
|
717
|
+
return json;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/** Generated from ListNode's serialization schema. Do not edit by hand. */
|
|
721
|
+
function updateListNode(node, json) {
|
|
722
|
+
const direction = json.direction;
|
|
723
|
+
node.__dir = direction === null || direction === 'ltr' || direction === 'rtl' ? direction : null;
|
|
724
|
+
const format = json.format;
|
|
725
|
+
node.__format = typeof format === 'string' && format in LIST_FORMAT_SETTER ? LIST_FORMAT_SETTER[format] : LIST_FORMAT_SETTER_DEFAULT;
|
|
726
|
+
node.__indent = numC(json.indent, 0, 0, Infinity);
|
|
727
|
+
node.__textFormat = num(json.textFormat, 0);
|
|
728
|
+
const textStyle = json.textStyle;
|
|
729
|
+
node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
|
|
730
|
+
const listType = json.listType;
|
|
731
|
+
node.setListType(typeof listType === 'string' && listType in LIST_LISTTYPE_ALIAS ? LIST_LISTTYPE_ALIAS[listType] : listType === 'number' || listType === 'bullet' || listType === 'check' ? listType : 'number');
|
|
732
|
+
node.__start = num(json.start, 1);
|
|
733
|
+
return node;
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
exportJSON: exportListNode,
|
|
737
|
+
exportCompactJSON: exportCompactListNode,
|
|
738
|
+
updateFromJSON: updateListNode,
|
|
739
|
+
afterCloneFrom: afterCloneListNode
|
|
740
|
+
};
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* ListItemNode's schema-declared fields, for a clone. Generated from that
|
|
745
|
+
* schema; do not edit by hand.
|
|
746
|
+
*
|
|
747
|
+
* @internal
|
|
748
|
+
*/
|
|
749
|
+
function afterCloneListItemNode(node, prevNode) {
|
|
750
|
+
node.__checked = prevNode.__checked;
|
|
751
|
+
node.__value = prevNode.__value;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/** ListItemNode's generated implementations, for its `$config`. @internal */
|
|
755
|
+
const GENERATED_LISTITEM = fields => {
|
|
756
|
+
const LISTITEM_FORMAT_GETTER = getterTableOf(fields, 'format');
|
|
757
|
+
const LISTITEM_FORMAT_SETTER = setterTableOf(fields, 'format');
|
|
758
|
+
const LISTITEM_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format');
|
|
759
|
+
|
|
760
|
+
/** Generated from ListItemNode's serialization schema. Do not edit by hand. */
|
|
761
|
+
function exportListItemNode(node) {
|
|
762
|
+
const textFormat = node.__textFormat;
|
|
763
|
+
const textStyle = node.__textStyle;
|
|
764
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
765
|
+
return {
|
|
766
|
+
children: [],
|
|
767
|
+
checked: node.getChecked(),
|
|
768
|
+
indent: node.getIndent(),
|
|
769
|
+
value: node.__value,
|
|
770
|
+
direction: node.__dir,
|
|
771
|
+
format: LISTITEM_FORMAT_GETTER[node.__format],
|
|
772
|
+
textFormat: textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
|
|
773
|
+
textStyle: textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
|
|
774
|
+
type: node.__type,
|
|
775
|
+
version: 1
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/** Generated from ListItemNode's serialization schema. Do not edit by hand. */
|
|
780
|
+
function exportCompactListItemNode(node) {
|
|
781
|
+
const textFormat = node.__textFormat;
|
|
782
|
+
const textStyle = node.__textStyle;
|
|
783
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
784
|
+
const json = {
|
|
785
|
+
type: node.__type,
|
|
786
|
+
children: []
|
|
787
|
+
};
|
|
788
|
+
const checked = node.getChecked();
|
|
789
|
+
if (checked !== undefined) {
|
|
790
|
+
json.checked = checked;
|
|
791
|
+
}
|
|
792
|
+
const indent = node.getIndent();
|
|
793
|
+
if (indent !== undefined && indent !== 0) {
|
|
794
|
+
json.indent = indent;
|
|
795
|
+
}
|
|
796
|
+
const value = node.__value;
|
|
797
|
+
if (value !== undefined && value !== 1) {
|
|
798
|
+
json.value = value;
|
|
799
|
+
}
|
|
800
|
+
const direction = node.__dir;
|
|
801
|
+
if (direction != null) {
|
|
802
|
+
json.direction = direction;
|
|
803
|
+
}
|
|
804
|
+
const format = LISTITEM_FORMAT_GETTER[node.__format];
|
|
805
|
+
if (format !== undefined && format !== '') {
|
|
806
|
+
json.format = format;
|
|
807
|
+
}
|
|
808
|
+
if (textFormat !== undefined && textFormat !== 0 && shouldSerializeTextStyles) {
|
|
809
|
+
json.textFormat = textFormat;
|
|
810
|
+
}
|
|
811
|
+
if (textStyle !== undefined && textStyle !== '' && shouldSerializeTextStyles) {
|
|
812
|
+
json.textStyle = textStyle;
|
|
813
|
+
}
|
|
814
|
+
return json;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/** Generated from ListItemNode's serialization schema. Do not edit by hand. */
|
|
818
|
+
function updateListItemNode(node, json) {
|
|
819
|
+
const direction = json.direction;
|
|
820
|
+
node.__dir = direction === null || direction === 'ltr' || direction === 'rtl' ? direction : null;
|
|
821
|
+
const format = json.format;
|
|
822
|
+
node.__format = typeof format === 'string' && format in LISTITEM_FORMAT_SETTER ? LISTITEM_FORMAT_SETTER[format] : LISTITEM_FORMAT_SETTER_DEFAULT;
|
|
823
|
+
node.setIndent(numK(json.indent, 0, 0, 128));
|
|
824
|
+
node.__textFormat = num(json.textFormat, 0);
|
|
825
|
+
const textStyle = json.textStyle;
|
|
826
|
+
node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
|
|
827
|
+
const checked = json.checked;
|
|
828
|
+
node.__checked = checked === undefined ? undefined : typeof checked === 'boolean' ? checked : false;
|
|
829
|
+
node.__value = num(json.value, 1);
|
|
830
|
+
return node;
|
|
831
|
+
}
|
|
832
|
+
return {
|
|
833
|
+
exportJSON: exportListItemNode,
|
|
834
|
+
exportCompactJSON: exportCompactListItemNode,
|
|
835
|
+
updateFromJSON: updateListItemNode,
|
|
836
|
+
afterCloneFrom: afterCloneListItemNode
|
|
837
|
+
};
|
|
838
|
+
};
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* The deepest list nesting `setIndent` will walk to. Each level it steps
|
|
842
|
+
* through nests or unwraps a whole list, so this bounds work an untrusted
|
|
843
|
+
* `indent` could otherwise make unbounded.
|
|
844
|
+
*/
|
|
845
|
+
const MAX_LIST_ITEM_INDENT = 128;
|
|
846
|
+
const listItemNodeSchema = /* @__PURE__ */nodeSchema()({
|
|
847
|
+
// getChecked computes from the parent list's type, so the getter stays a
|
|
848
|
+
// method; setChecked is a bare field write.
|
|
849
|
+
checked: /* @__PURE__ */withAccessors(/* @__PURE__ */optional(/* @__PURE__ */booleanValue()), {
|
|
850
|
+
setter: {
|
|
851
|
+
field: '__checked'
|
|
852
|
+
}
|
|
853
|
+
}),
|
|
854
|
+
// Overrides the inherited ElementNode field to bound it. This indent is
|
|
855
|
+
// structural — applying it nests or unwraps one whole list per level — so an
|
|
856
|
+
// unbounded value out of untrusted JSON would build millions of nodes.
|
|
857
|
+
// `clamp`, because the plain bounds fall back to the *default* for a value
|
|
858
|
+
// outside them, which would read an over-deep item as indent 0 instead of as
|
|
859
|
+
// deeply nested.
|
|
860
|
+
indent: /* @__PURE__ */numberValue(0, {
|
|
861
|
+
clamp: true,
|
|
862
|
+
integer: true,
|
|
863
|
+
max: MAX_LIST_ITEM_INDENT,
|
|
864
|
+
min: 0
|
|
865
|
+
}),
|
|
866
|
+
value: /* @__PURE__ */withField(/* @__PURE__ */numberValue(1), {
|
|
867
|
+
field: '__value'
|
|
868
|
+
})
|
|
869
|
+
});
|
|
607
870
|
function applyMarkerStyles(dom, node, prevNode) {
|
|
608
871
|
const nextTextStyle = node.__textStyle;
|
|
609
872
|
const prevTextStyle = prevNode ? prevNode.__textStyle : '';
|
|
@@ -623,7 +886,10 @@ function applyMarkerStyles(dom, node, prevNode) {
|
|
|
623
886
|
}
|
|
624
887
|
}
|
|
625
888
|
|
|
889
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
890
|
+
|
|
626
891
|
/** @noInheritDoc */
|
|
892
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
627
893
|
class ListItemNode extends ElementNode {
|
|
628
894
|
/** @internal */
|
|
629
895
|
__value;
|
|
@@ -674,12 +940,14 @@ class ListItemNode extends ElementNode {
|
|
|
674
940
|
}
|
|
675
941
|
},
|
|
676
942
|
extends: ElementNode,
|
|
943
|
+
generated: GENERATED_LISTITEM,
|
|
677
944
|
importDOM: buildImportMap({
|
|
678
945
|
li: () => ({
|
|
679
946
|
conversion: $convertListItemElement,
|
|
680
947
|
priority: 0
|
|
681
948
|
})
|
|
682
|
-
})
|
|
949
|
+
}),
|
|
950
|
+
json: listItemNodeSchema
|
|
683
951
|
});
|
|
684
952
|
}
|
|
685
953
|
constructor(value = 1, checked = undefined, key) {
|
|
@@ -687,11 +955,6 @@ class ListItemNode extends ElementNode {
|
|
|
687
955
|
this.__value = value === undefined ? 1 : value;
|
|
688
956
|
this.__checked = checked;
|
|
689
957
|
}
|
|
690
|
-
afterCloneFrom(prevNode) {
|
|
691
|
-
super.afterCloneFrom(prevNode);
|
|
692
|
-
this.__value = prevNode.__value;
|
|
693
|
-
this.__checked = prevNode.__checked;
|
|
694
|
-
}
|
|
695
958
|
createDOM(config) {
|
|
696
959
|
const element = $getDocument().createElement('li');
|
|
697
960
|
this.updateListItemDOM(null, element, config);
|
|
@@ -714,9 +977,6 @@ class ListItemNode extends ElementNode {
|
|
|
714
977
|
this.updateListItemDOM(prevNode, element, config);
|
|
715
978
|
return false;
|
|
716
979
|
}
|
|
717
|
-
updateFromJSON(serializedNode) {
|
|
718
|
-
return super.updateFromJSON(serializedNode).setValue(serializedNode.value).setChecked(serializedNode.checked);
|
|
719
|
-
}
|
|
720
980
|
exportDOM(editor) {
|
|
721
981
|
const element = this.createDOM(editor._config);
|
|
722
982
|
const formatType = this.getFormatType();
|
|
@@ -748,13 +1008,6 @@ class ListItemNode extends ElementNode {
|
|
|
748
1008
|
element
|
|
749
1009
|
};
|
|
750
1010
|
}
|
|
751
|
-
exportJSON() {
|
|
752
|
-
return {
|
|
753
|
-
...super.exportJSON(),
|
|
754
|
-
checked: this.getChecked(),
|
|
755
|
-
value: this.getValue()
|
|
756
|
-
};
|
|
757
|
-
}
|
|
758
1011
|
append(...nodes) {
|
|
759
1012
|
for (let i = 0; i < nodes.length; i++) {
|
|
760
1013
|
const node = nodes[i];
|
|
@@ -949,10 +1202,15 @@ class ListItemNode extends ElementNode {
|
|
|
949
1202
|
indent = Math.floor(indent);
|
|
950
1203
|
if (!(indent >= 0)) {
|
|
951
1204
|
formatDevErrorMessage(`Indent value must be non-negative.`);
|
|
952
|
-
}
|
|
1205
|
+
} // Deliberately not clamped here: the bound belongs on the parse path (see
|
|
1206
|
+
// listItemNodeSchema), because clamping the target of a walk that starts
|
|
1207
|
+
// from the node's *current* indent would outdent an item that is already
|
|
1208
|
+
// nested deeper than the bound — making `item.setIndent(item.getIndent())`
|
|
1209
|
+
// destroy structure rather than do nothing.
|
|
1210
|
+
const target = indent;
|
|
953
1211
|
let currentIndent = this.getIndent();
|
|
954
|
-
while (currentIndent !==
|
|
955
|
-
if (currentIndent <
|
|
1212
|
+
while (currentIndent !== target) {
|
|
1213
|
+
if (currentIndent < target) {
|
|
956
1214
|
$handleIndent(this);
|
|
957
1215
|
currentIndent++;
|
|
958
1216
|
} else {
|
|
@@ -1130,7 +1388,42 @@ function $isListItemNode(node) {
|
|
|
1130
1388
|
*
|
|
1131
1389
|
*/
|
|
1132
1390
|
|
|
1391
|
+
// A literal rather than a `Record<string, ListType>` so that the alias table
|
|
1392
|
+
// below keeps its keys: they are what the schema reports as the legacy
|
|
1393
|
+
// spellings it accepts.
|
|
1394
|
+
const TAG_TO_LIST_TYPE = {
|
|
1395
|
+
ol: 'number',
|
|
1396
|
+
ul: 'bullet'
|
|
1397
|
+
};
|
|
1398
|
+
const listNodeSchema = /* @__PURE__ */nodeSchema()({
|
|
1399
|
+
// 'ul'/'ol' are the legacy tag-form listType some older documents carry,
|
|
1400
|
+
// stated as an alias table rather than a transform: the mapping is data, so
|
|
1401
|
+
// the codegen can compile this property's parse, where an arbitrary
|
|
1402
|
+
// function would have taken the whole class out of the import half.
|
|
1403
|
+
// Read straight off the field; applied through setListType, which also
|
|
1404
|
+
// maintains the derived __tag, so the setter stays a method.
|
|
1405
|
+
listType: /* @__PURE__ */withAccessors(/* @__PURE__ */aliasedValue(/* @__PURE__ */enumValue(['number', 'bullet', 'check']), TAG_TO_LIST_TYPE), {
|
|
1406
|
+
getter: {
|
|
1407
|
+
field: '__listType'
|
|
1408
|
+
}
|
|
1409
|
+
}),
|
|
1410
|
+
start: /* @__PURE__ */withField(/* @__PURE__ */numberValue(1), {
|
|
1411
|
+
field: '__start'
|
|
1412
|
+
}),
|
|
1413
|
+
// Derived from listType rather than stored: written on export, and
|
|
1414
|
+
// deliberately not applied on import.
|
|
1415
|
+
tag: /* @__PURE__ */withAccessors(/* @__PURE__ */enumValue(['ul', 'ol']), {
|
|
1416
|
+
getter: {
|
|
1417
|
+
field: '__tag'
|
|
1418
|
+
},
|
|
1419
|
+
setter: null
|
|
1420
|
+
})
|
|
1421
|
+
});
|
|
1422
|
+
|
|
1423
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
1424
|
+
|
|
1133
1425
|
/** @noInheritDoc */
|
|
1426
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
1134
1427
|
class ListNode extends ElementNode {
|
|
1135
1428
|
/** @internal */
|
|
1136
1429
|
__tag;
|
|
@@ -1147,6 +1440,7 @@ class ListNode extends ElementNode {
|
|
|
1147
1440
|
updateChildrenListItemValue(node);
|
|
1148
1441
|
},
|
|
1149
1442
|
extends: ElementNode,
|
|
1443
|
+
generated: GENERATED_LIST,
|
|
1150
1444
|
importDOM: buildImportMap({
|
|
1151
1445
|
ol: () => ({
|
|
1152
1446
|
conversion: $convertListNode,
|
|
@@ -1156,22 +1450,19 @@ class ListNode extends ElementNode {
|
|
|
1156
1450
|
conversion: $convertListNode,
|
|
1157
1451
|
priority: 0
|
|
1158
1452
|
})
|
|
1159
|
-
})
|
|
1453
|
+
}),
|
|
1454
|
+
json: listNodeSchema
|
|
1160
1455
|
});
|
|
1161
1456
|
}
|
|
1162
1457
|
constructor(listType = 'number', start = 1, key) {
|
|
1163
1458
|
super(key);
|
|
1459
|
+
// Widened for the lookup: the parameter's type excludes the legacy tag
|
|
1460
|
+
// spellings, and this normalizes them for a caller that passes one anyway.
|
|
1164
1461
|
const _listType = TAG_TO_LIST_TYPE[listType] || listType;
|
|
1165
1462
|
this.__listType = _listType;
|
|
1166
1463
|
this.__tag = _listType === 'number' ? 'ol' : 'ul';
|
|
1167
1464
|
this.__start = start;
|
|
1168
1465
|
}
|
|
1169
|
-
afterCloneFrom(prevNode) {
|
|
1170
|
-
super.afterCloneFrom(prevNode);
|
|
1171
|
-
this.__listType = prevNode.__listType;
|
|
1172
|
-
this.__tag = prevNode.__tag;
|
|
1173
|
-
this.__start = prevNode.__start;
|
|
1174
|
-
}
|
|
1175
1466
|
getTag() {
|
|
1176
1467
|
return this.getLatest().__tag;
|
|
1177
1468
|
}
|
|
@@ -1216,9 +1507,6 @@ class ListNode extends ElementNode {
|
|
|
1216
1507
|
}
|
|
1217
1508
|
return false;
|
|
1218
1509
|
}
|
|
1219
|
-
updateFromJSON(serializedNode) {
|
|
1220
|
-
return super.updateFromJSON(serializedNode).setListType(serializedNode.listType).setStart(serializedNode.start);
|
|
1221
|
-
}
|
|
1222
1510
|
exportDOM(editor) {
|
|
1223
1511
|
const element = this.createDOM(editor._config, editor);
|
|
1224
1512
|
if (isHTMLElement(element)) {
|
|
@@ -1240,14 +1528,6 @@ class ListNode extends ElementNode {
|
|
|
1240
1528
|
element
|
|
1241
1529
|
};
|
|
1242
1530
|
}
|
|
1243
|
-
exportJSON() {
|
|
1244
|
-
return {
|
|
1245
|
-
...super.exportJSON(),
|
|
1246
|
-
listType: this.getListType(),
|
|
1247
|
-
start: this.getStart(),
|
|
1248
|
-
tag: this.getTag()
|
|
1249
|
-
};
|
|
1250
|
-
}
|
|
1251
1531
|
canBeEmpty() {
|
|
1252
1532
|
return false;
|
|
1253
1533
|
}
|
|
@@ -1400,10 +1680,6 @@ function $convertListNode(domNode) {
|
|
|
1400
1680
|
node
|
|
1401
1681
|
};
|
|
1402
1682
|
}
|
|
1403
|
-
const TAG_TO_LIST_TYPE = {
|
|
1404
|
-
ol: 'number',
|
|
1405
|
-
ul: 'bullet'
|
|
1406
|
-
};
|
|
1407
1683
|
|
|
1408
1684
|
/**
|
|
1409
1685
|
* Creates a ListNode of listType.
|
package/dist/LexicalList.js.flow
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
RangeSelection,
|
|
16
16
|
LexicalCommand,
|
|
17
17
|
SerializedElementNode,
|
|
18
|
+
SerializedPartial,
|
|
18
19
|
LexicalExtension,
|
|
19
20
|
ExtensionConfigBase,
|
|
20
21
|
} from 'lexical';
|
|
@@ -62,7 +63,17 @@ declare export class ListItemNode extends ElementNode {
|
|
|
62
63
|
getChecked(): boolean | void;
|
|
63
64
|
setChecked(boolean): this;
|
|
64
65
|
toggleChecked(): void;
|
|
65
|
-
|
|
66
|
+
// Both forms, because a Flow object property is invariant: `SerializedPartial`
|
|
67
|
+
// makes each property optional, and an optional property is not a supertype
|
|
68
|
+
// of a required one there, so naming only the relaxed form made the *full*
|
|
69
|
+
// serialized type unassignable — `ListItemNode.importJSON(node.exportJSON())`
|
|
70
|
+
// stopped type-checking. TypeScript needs no union: a required property
|
|
71
|
+
// satisfies an optional one structurally.
|
|
72
|
+
static importJSON(
|
|
73
|
+
serializedNode:
|
|
74
|
+
| SerializedListItemNode
|
|
75
|
+
| SerializedPartial<SerializedListItemNode>,
|
|
76
|
+
): ListItemNode;
|
|
66
77
|
}
|
|
67
78
|
declare export class ListNode extends ElementNode {
|
|
68
79
|
__tag: ListNodeTagType;
|
|
@@ -72,7 +83,17 @@ declare export class ListNode extends ElementNode {
|
|
|
72
83
|
getTag(): ListNodeTagType;
|
|
73
84
|
getStart(): number;
|
|
74
85
|
getListType(): ListType;
|
|
75
|
-
|
|
86
|
+
// Both forms, because a Flow object property is invariant: `SerializedPartial`
|
|
87
|
+
// makes each property optional, and an optional property is not a supertype
|
|
88
|
+
// of a required one there, so naming only the relaxed form made the *full*
|
|
89
|
+
// serialized type unassignable — `ListNode.importJSON(node.exportJSON())`
|
|
90
|
+
// stopped type-checking. TypeScript needs no union: a required property
|
|
91
|
+
// satisfies an optional one structurally.
|
|
92
|
+
static importJSON(
|
|
93
|
+
serializedNode:
|
|
94
|
+
| SerializedListNode
|
|
95
|
+
| SerializedPartial<SerializedListNode>,
|
|
96
|
+
): ListNode;
|
|
76
97
|
}
|
|
77
98
|
declare export function outdentList(): void;
|
|
78
99
|
declare export function $removeList(): void;
|