@lexical/mark 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/LexicalMark.dev.js +140 -15
- package/dist/LexicalMark.prod.js +1 -1
- package/dist/LexicalMarkGeneratedJSON.d.ts +18 -0
- package/dist/MarkNode.d.ts +26 -5
- package/package.json +3 -3
- package/src/LexicalMarkGeneratedJSON.ts +184 -0
- package/src/MarkNode.ts +33 -18
package/dist/LexicalMark.dev.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { ElementNode, $getDocument, addClassNamesToElement, removeClassNamesFromElement, $isRangeSelection, $applyNodeReplacement, $isTextNode, $createRangeSelection, $isElementNode, $isDecoratorNode } from 'lexical';
|
|
9
|
+
import { getterTableOf, setterTableOf, setterDefaultOf, ElementNode, $getDocument, addClassNamesToElement, removeClassNamesFromElement, $isRangeSelection, $applyNodeReplacement, nodeSchema, withAccessors, arrayValue, stringValue, $isTextNode, $createRangeSelection, $isElementNode, $isDecoratorNode } from 'lexical';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -16,30 +16,155 @@ import { ElementNode, $getDocument, addClassNamesToElement, removeClassNamesFrom
|
|
|
16
16
|
*
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
// The JSON number grammar, anchored, matching numberValue: `Number()` alone
|
|
21
|
+
// reads '0x10' as 16 and '' as 0, and neither is a shape a JSON encoder
|
|
22
|
+
// produces. Emitted from the same source the codegen verified against, so the
|
|
23
|
+
// two cannot be different functions.
|
|
24
|
+
const JSON_NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
25
|
+
function num(v, d) {
|
|
26
|
+
if (typeof v === 'number') {
|
|
27
|
+
return Number.isFinite(v) ? v : d;
|
|
28
|
+
}
|
|
29
|
+
if (typeof v !== 'string' || !JSON_NUMBER.test(v)) {
|
|
30
|
+
return d;
|
|
31
|
+
}
|
|
32
|
+
const n = Number(v);
|
|
33
|
+
return Number.isFinite(n) ? n : d;
|
|
34
|
+
}
|
|
35
|
+
function numC(v, d, min, max, integer) {
|
|
36
|
+
const n = num(v, d);
|
|
37
|
+
return n >= min && n <= max && (false || Number.isInteger(n)) ? n : d;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* MarkNode's schema-declared fields, for a clone. Generated from that
|
|
42
|
+
* schema; do not edit by hand.
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
function afterCloneMarkNode(node, prevNode) {
|
|
47
|
+
node.__ids = prevNode.__ids;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** MarkNode's generated implementations, for its `$config`. @internal */
|
|
51
|
+
const GENERATED_MARK = fields => {
|
|
52
|
+
const MARK_FORMAT_GETTER = getterTableOf(fields, 'format');
|
|
53
|
+
const MARK_FORMAT_SETTER = setterTableOf(fields, 'format');
|
|
54
|
+
const MARK_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format');
|
|
55
|
+
|
|
56
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
57
|
+
function exportMarkNode(node) {
|
|
58
|
+
const textFormat = node.__textFormat;
|
|
59
|
+
const textStyle = node.__textStyle;
|
|
60
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
61
|
+
return {
|
|
62
|
+
children: [],
|
|
63
|
+
ids: node.getIDs(),
|
|
64
|
+
direction: node.__dir,
|
|
65
|
+
format: MARK_FORMAT_GETTER[node.__format],
|
|
66
|
+
indent: node.__indent,
|
|
67
|
+
textFormat: textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
|
|
68
|
+
textStyle: textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
|
|
69
|
+
type: node.__type,
|
|
70
|
+
version: 1
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
75
|
+
function exportCompactMarkNode(node) {
|
|
76
|
+
const textFormat = node.__textFormat;
|
|
77
|
+
const textStyle = node.__textStyle;
|
|
78
|
+
const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
|
|
79
|
+
const json = {
|
|
80
|
+
type: node.__type,
|
|
81
|
+
children: []
|
|
82
|
+
};
|
|
83
|
+
const ids = node.getIDs();
|
|
84
|
+
if (ids !== undefined && !(Array.isArray(ids) && ids.length === 0)) {
|
|
85
|
+
json.ids = ids;
|
|
86
|
+
}
|
|
87
|
+
const direction = node.__dir;
|
|
88
|
+
if (direction != null) {
|
|
89
|
+
json.direction = direction;
|
|
90
|
+
}
|
|
91
|
+
const format = MARK_FORMAT_GETTER[node.__format];
|
|
92
|
+
if (format !== undefined && format !== '') {
|
|
93
|
+
json.format = format;
|
|
94
|
+
}
|
|
95
|
+
const indent = node.__indent;
|
|
96
|
+
if (indent !== undefined && indent !== 0) {
|
|
97
|
+
json.indent = indent;
|
|
98
|
+
}
|
|
99
|
+
if (textFormat !== undefined && textFormat !== 0 && shouldSerializeTextStyles) {
|
|
100
|
+
json.textFormat = textFormat;
|
|
101
|
+
}
|
|
102
|
+
if (textStyle !== undefined && textStyle !== '' && shouldSerializeTextStyles) {
|
|
103
|
+
json.textStyle = textStyle;
|
|
104
|
+
}
|
|
105
|
+
return json;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
109
|
+
function updateMarkNode(node, json) {
|
|
110
|
+
const direction = json.direction;
|
|
111
|
+
node.__dir = direction === null || direction === 'ltr' || direction === 'rtl' ? direction : null;
|
|
112
|
+
const format = json.format;
|
|
113
|
+
node.__format = typeof format === 'string' && format in MARK_FORMAT_SETTER ? MARK_FORMAT_SETTER[format] : MARK_FORMAT_SETTER_DEFAULT;
|
|
114
|
+
node.__indent = numC(json.indent, 0, 0, Infinity);
|
|
115
|
+
node.__textFormat = num(json.textFormat, 0);
|
|
116
|
+
const textStyle = json.textStyle;
|
|
117
|
+
node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
|
|
118
|
+
const ids = json.ids;
|
|
119
|
+
node.__ids = Array.isArray(ids) ? Array.from(ids, e0 => typeof e0 === 'string' ? e0 : '') : [];
|
|
120
|
+
return node;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
exportJSON: exportMarkNode,
|
|
124
|
+
exportCompactJSON: exportCompactMarkNode,
|
|
125
|
+
updateFromJSON: updateMarkNode,
|
|
126
|
+
afterCloneFrom: afterCloneMarkNode
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
132
|
+
*
|
|
133
|
+
* This source code is licensed under the MIT license found in the
|
|
134
|
+
* LICENSE file in the root directory of this source tree.
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
// Single source of truth for parsing the node-specific properties of a
|
|
139
|
+
// SerializedMarkNode (those it adds over a SerializedElementNode).
|
|
140
|
+
const markNodeSchema = /* @__PURE__ */nodeSchema()({
|
|
141
|
+
// The getter stays a method: getIDs hands out a copy, so the export does not
|
|
142
|
+
// give a caller the node's own array. The setter is the field it writes,
|
|
143
|
+
// which is also what tells the clone where `ids` lives.
|
|
144
|
+
ids: /* @__PURE__ */withAccessors(/* @__PURE__ */arrayValue(/* @__PURE__ */stringValue()), {
|
|
145
|
+
getter: 'getIDs',
|
|
146
|
+
setter: {
|
|
147
|
+
field: '__ids',
|
|
148
|
+
method: 'setIDs'
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
});
|
|
19
152
|
const NO_IDS = [];
|
|
20
153
|
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
155
|
+
|
|
21
156
|
/** @noInheritDoc */
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
22
158
|
class MarkNode extends ElementNode {
|
|
23
159
|
/** @internal */
|
|
24
160
|
__ids;
|
|
25
161
|
$config() {
|
|
26
162
|
return this.config('mark', {
|
|
27
|
-
extends: ElementNode
|
|
163
|
+
extends: ElementNode,
|
|
164
|
+
generated: GENERATED_MARK,
|
|
165
|
+
json: markNodeSchema
|
|
28
166
|
});
|
|
29
167
|
}
|
|
30
|
-
afterCloneFrom(prevNode) {
|
|
31
|
-
super.afterCloneFrom(prevNode);
|
|
32
|
-
this.__ids = prevNode.__ids;
|
|
33
|
-
}
|
|
34
|
-
updateFromJSON(serializedNode) {
|
|
35
|
-
return super.updateFromJSON(serializedNode).setIDs(serializedNode.ids);
|
|
36
|
-
}
|
|
37
|
-
exportJSON() {
|
|
38
|
-
return {
|
|
39
|
-
...super.exportJSON(),
|
|
40
|
-
ids: this.getIDs()
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
168
|
constructor(ids = NO_IDS, key) {
|
|
44
169
|
super(key);
|
|
45
170
|
this.__ids = ids;
|
package/dist/LexicalMark.prod.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{ElementNode as
|
|
9
|
+
import{getterTableOf as t,setterTableOf as e,setterDefaultOf as n,ElementNode as r,$getDocument as i,addClassNamesToElement as s,removeClassNamesFromElement as o,$isRangeSelection as c,$applyNodeReplacement as f,nodeSchema as l,withAccessors as d,arrayValue as u,stringValue as a,$isTextNode as _,$createRangeSelection as m,$isElementNode as h,$isDecoratorNode as g}from"lexical";const y=/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;function x(t,e){if("number"==typeof t)return Number.isFinite(t)?t:e;if("string"!=typeof t||!y.test(t))return e;const n=Number(t);return Number.isFinite(n)?n:e}function p(t,e){t.__ids=e.__ids}const I=r=>{const i=t(r,"format"),s=e(r,"format"),o=n(r,"format");return{exportJSON:function(t){const e=t.__textFormat,n=t.__textStyle,r=(0!==e||""!==n)&&t.shouldSerializeTextStyles();return{children:[],ids:t.getIDs(),direction:t.__dir,format:i[t.__format],indent:t.__indent,textFormat:0!==e&&r?e:void 0,textStyle:""!==n&&r?n:void 0,type:t.__type,version:1}},exportCompactJSON:function(t){const e=t.__textFormat,n=t.__textStyle,r=(0!==e||""!==n)&&t.shouldSerializeTextStyles(),s={type:t.__type,children:[]},o=t.getIDs();void 0===o||Array.isArray(o)&&0===o.length||(s.ids=o);const c=t.__dir;null!=c&&(s.direction=c);const f=i[t.__format];void 0!==f&&""!==f&&(s.format=f);const l=t.__indent;return void 0!==l&&0!==l&&(s.indent=l),void 0!==e&&0!==e&&r&&(s.textFormat=e),void 0!==n&&""!==n&&r&&(s.textStyle=n),s},updateFromJSON:function(t,e){const n=e.direction;t.__dir=null===n||"ltr"===n||"rtl"===n?n:null;const r=e.format;t.__format="string"==typeof r&&r in s?s[r]:o,t.__indent=function(t,e,n,r){const i=x(t,e);return i>=n&&i<=r&&Number.isInteger(i)?i:e}(e.indent,0,0,Infinity),t.__textFormat=x(e.textFormat,0);const i=e.textStyle;t.__textStyle="string"==typeof i?i:"";const c=e.ids;return t.__ids=Array.isArray(c)?Array.from(c,t=>"string"==typeof t?t:""):[],t},afterCloneFrom:p}},D=/* @__PURE__ */l()({ids:/* @__PURE__ */d(/* @__PURE__ */u(/* @__PURE__ */a()),{getter:"getIDs",setter:{field:"__ids",method:"setIDs"}})}),S=[];class v extends r{__ids;$config(){return this.config("mark",{extends:r,generated:I,json:D})}constructor(t=S,e){super(e),this.__ids=t}createDOM(t){const e=i().createElement("mark");return s(e,t.theme.mark),this.__ids.length>1&&s(e,t.theme.markOverlap),e}updateDOM(t,e,n){const r=t.__ids,i=this.__ids,c=r.length,f=i.length,l=n.theme.markOverlap,d=f>1;return c>1!==d&&(d?s(e,l):o(e,l)),!1}hasID(t){return this.getIDs().includes(t)}getIDs(){return Array.from(this.getLatest().__ids)}setIDs(t){const e=this.getWritable();return e.__ids=t,e}addID(t){const e=this.getWritable();return e.__ids.includes(t)?e:e.setIDs([...e.__ids,t])}deleteID(t){const e=this.getWritable(),n=e.__ids.indexOf(t);if(-1===n)return e;const r=Array.from(e.__ids);return r.splice(n,1),e.setIDs(r)}insertNewAfter(t,e=!0){const n=A(this.__ids);return this.insertAfter(n,e),n}canInsertTextBefore(){return!1}canInsertTextAfter(){return!1}canBeEmpty(){return!1}isInline(){return!0}extractWithChild(t,e,n){if(!c(e)||"html"===n)return!1;const r=e.anchor,i=e.focus,s=r.getNode(),o=i.getNode(),f=e.isBackward()?r.offset-i.offset:i.offset-r.offset;return this.isParentOf(s)&&this.isParentOf(o)&&this.getTextContent().length===f}excludeFromCopy(t){return"clone"!==t}}function A(t=S){return f(new v(t))}function F(t){return t instanceof v}function N(t){const e=t.getChildren();let n=null;for(let r=0;r<e.length;r++){const i=e[r];null===n?t.insertBefore(i):n.insertAfter(i),n=i}t.remove()}function O(t,e,n,r){const i=m(),[s,o]=t.isBackward()?[t.focus,t.anchor]:[t.anchor,t.focus];let c,f;i.anchor.set(s.key,s.offset,s.type),i.focus.set(o.key,o.offset,o.type);const l=i.extract();for(const t of l){if(h(f)&&f.isParentOf(t))continue;let e=null;if(_(t))e=t;else{if(F(t))continue;(h(t)||g(t))&&t.isInline()&&(e=t)}if(null!==e){if(e&&e.is(c))continue;const t=e.getParent();if(null!=t&&t.is(c)||(f=void 0),c=t,void 0===f){f=(r||A)([n]),e.insertBefore(f)}f.append(e)}else c=void 0,f=void 0}h(f)&&(e?f.selectStart():f.selectEnd())}function k(t,e){let n=t;for(;null!==n;){if(F(n))return n.getIDs();if(_(n)&&e===n.getTextContentSize()){const t=n.getNextSibling();if(F(t))return t.getIDs()}n=n.getParent()}return null}const b={name:"@lexical/mark",nodes:()=>[v]};export{A as $createMarkNode,k as $getMarkIDs,F as $isMarkNode,N as $unwrapMarkNode,O as $wrapSelectionInMarkNode,b as MarkExtension,v as MarkNode};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { MarkNode } from './MarkNode.js';
|
|
9
|
+
import { type GeneratedJSONFactory } from 'lexical';
|
|
10
|
+
/**
|
|
11
|
+
* MarkNode's schema-declared fields, for a clone. Generated from that
|
|
12
|
+
* schema; do not edit by hand.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function afterCloneMarkNode(node: MarkNode, prevNode: MarkNode): void;
|
|
17
|
+
/** MarkNode's generated implementations, for its `$config`. @internal */
|
|
18
|
+
export declare const GENERATED_MARK: GeneratedJSONFactory;
|
package/dist/MarkNode.d.ts
CHANGED
|
@@ -5,24 +5,45 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { type BaseSelection, type EditorConfig, ElementNode, type LexicalNode, type
|
|
8
|
+
import { type BaseSelection, type EditorConfig, ElementNode, type LexicalNode, type LexicalParseJSON, type NodeKey, type RangeSelection, type SerializedElementNode, type SerializedPartial, type Spread } from 'lexical';
|
|
9
9
|
export type SerializedMarkNode = Spread<{
|
|
10
10
|
ids: string[];
|
|
11
11
|
}, SerializedElementNode>;
|
|
12
|
+
export interface MarkNode {
|
|
13
|
+
exportJSON(compact?: false): SerializedMarkNode;
|
|
14
|
+
exportJSON(compact: boolean): SerializedPartial<SerializedMarkNode>;
|
|
15
|
+
updateFromJSON(serializedNode: LexicalParseJSON<SerializedMarkNode>): this;
|
|
16
|
+
}
|
|
12
17
|
/** @noInheritDoc */
|
|
13
18
|
export declare class MarkNode extends ElementNode {
|
|
14
19
|
/** @internal */
|
|
15
20
|
__ids: readonly string[];
|
|
16
|
-
$config(): import("lexical").BaseStaticNodeConfig & {
|
|
21
|
+
$config(): import("lexical").BaseStaticNodeConfig & import("lexical").StaticNodeConfigAccessor<{
|
|
22
|
+
readonly $transform: (node: ElementNode) => void;
|
|
23
|
+
readonly extends: typeof LexicalNode;
|
|
24
|
+
readonly generated: import("lexical").GeneratedJSONFactory;
|
|
25
|
+
readonly json: import("lexical").NodeSerializationSchema<ElementNode, {
|
|
26
|
+
readonly direction?: "ltr" | "rtl" | null | undefined;
|
|
27
|
+
readonly format?: "" | "left" | "start" | "center" | "right" | "end" | "justify" | undefined;
|
|
28
|
+
readonly indent?: string | number | undefined;
|
|
29
|
+
readonly textFormat?: string | number | undefined;
|
|
30
|
+
readonly textStyle?: string | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
}> & {
|
|
17
33
|
readonly mark?: {
|
|
18
34
|
readonly extends: typeof ElementNode;
|
|
35
|
+
readonly generated: import("lexical").GeneratedJSONFactory;
|
|
36
|
+
readonly json: import("lexical").NodeSerializationSchema<MarkNode, {
|
|
37
|
+
readonly ids?: readonly string[] | undefined;
|
|
38
|
+
}>;
|
|
19
39
|
} | undefined;
|
|
20
40
|
} & import("lexical").StaticNodeTypeAccessor<"mark"> & import("lexical").StaticNodeConfigAccessor<{
|
|
21
41
|
readonly extends: typeof ElementNode;
|
|
42
|
+
readonly generated: import("lexical").GeneratedJSONFactory;
|
|
43
|
+
readonly json: import("lexical").NodeSerializationSchema<MarkNode, {
|
|
44
|
+
readonly ids?: readonly string[] | undefined;
|
|
45
|
+
}>;
|
|
22
46
|
}>;
|
|
23
|
-
afterCloneFrom(prevNode: this): void;
|
|
24
|
-
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedMarkNode>): this;
|
|
25
|
-
exportJSON(): SerializedMarkNode;
|
|
26
47
|
constructor(ids?: readonly string[], key?: NodeKey);
|
|
27
48
|
createDOM(config: EditorConfig): HTMLElement;
|
|
28
49
|
updateDOM(prevNode: this, element: HTMLElement, config: EditorConfig): boolean;
|
package/package.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"mark"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.51.0",
|
|
12
12
|
"main": "./dist/LexicalMark.js",
|
|
13
13
|
"types": "./dist/typescript-too-old.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@lexical/utils": "0.
|
|
16
|
-
"lexical": "0.
|
|
15
|
+
"@lexical/utils": "0.51.0",
|
|
16
|
+
"lexical": "0.51.0"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// @generated by scripts/generate-node-json.mjs from each class's `json`
|
|
10
|
+
// schema. Run `pnpm run generate-node-json` to regenerate; do not edit.
|
|
11
|
+
|
|
12
|
+
// Keys are emitted in the order the schema-driven walk writes them, so the two
|
|
13
|
+
// produce byte-identical JSON. That order is the schema's, not alphabetical.
|
|
14
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
15
|
+
|
|
16
|
+
import type {MarkNode} from './MarkNode';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
type GeneratedJSONFactory,
|
|
20
|
+
getterTableOf,
|
|
21
|
+
setterDefaultOf,
|
|
22
|
+
setterTableOf,
|
|
23
|
+
} from 'lexical';
|
|
24
|
+
|
|
25
|
+
// The JSON number grammar, anchored, matching numberValue: `Number()` alone
|
|
26
|
+
// reads '0x10' as 16 and '' as 0, and neither is a shape a JSON encoder
|
|
27
|
+
// produces. Emitted from the same source the codegen verified against, so the
|
|
28
|
+
// two cannot be different functions.
|
|
29
|
+
const JSON_NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
30
|
+
|
|
31
|
+
function num(v: unknown, d: number): number {
|
|
32
|
+
if (typeof v === 'number') {
|
|
33
|
+
return Number.isFinite(v) ? v : d;
|
|
34
|
+
}
|
|
35
|
+
if (typeof v !== 'string' || !JSON_NUMBER.test(v)) {
|
|
36
|
+
return d;
|
|
37
|
+
}
|
|
38
|
+
const n = Number(v);
|
|
39
|
+
return Number.isFinite(n) ? n : d;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function numC(
|
|
43
|
+
v: unknown,
|
|
44
|
+
d: number,
|
|
45
|
+
min: number,
|
|
46
|
+
max: number,
|
|
47
|
+
integer: boolean,
|
|
48
|
+
): number {
|
|
49
|
+
const n = num(v, d);
|
|
50
|
+
return n >= min && n <= max && (!integer || Number.isInteger(n)) ? n : d;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* MarkNode's schema-declared fields, for a clone. Generated from that
|
|
55
|
+
* schema; do not edit by hand.
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export function afterCloneMarkNode(node: MarkNode, prevNode: MarkNode): void {
|
|
60
|
+
node.__ids = prevNode.__ids;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** MarkNode's generated implementations, for its `$config`. @internal */
|
|
64
|
+
export const GENERATED_MARK: GeneratedJSONFactory = fields => {
|
|
65
|
+
const MARK_FORMAT_GETTER = getterTableOf(fields, 'format') as {
|
|
66
|
+
readonly [key: string]:
|
|
67
|
+
| ''
|
|
68
|
+
| 'center'
|
|
69
|
+
| 'end'
|
|
70
|
+
| 'justify'
|
|
71
|
+
| 'left'
|
|
72
|
+
| 'right'
|
|
73
|
+
| 'start';
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const MARK_FORMAT_SETTER = setterTableOf(fields, 'format') as {
|
|
77
|
+
readonly [key: string]: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const MARK_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format') as
|
|
81
|
+
| 0
|
|
82
|
+
| 1
|
|
83
|
+
| 2
|
|
84
|
+
| 3
|
|
85
|
+
| 4
|
|
86
|
+
| 5
|
|
87
|
+
| 6;
|
|
88
|
+
|
|
89
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
90
|
+
function exportMarkNode(node: MarkNode): {[key: string]: unknown} {
|
|
91
|
+
const textFormat = node.__textFormat;
|
|
92
|
+
const textStyle = node.__textStyle;
|
|
93
|
+
const shouldSerializeTextStyles =
|
|
94
|
+
(textFormat !== 0 || textStyle !== '') &&
|
|
95
|
+
node.shouldSerializeTextStyles();
|
|
96
|
+
return {
|
|
97
|
+
children: [],
|
|
98
|
+
ids: node.getIDs(),
|
|
99
|
+
direction: node.__dir,
|
|
100
|
+
format: MARK_FORMAT_GETTER[node.__format],
|
|
101
|
+
indent: node.__indent,
|
|
102
|
+
textFormat:
|
|
103
|
+
textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
|
|
104
|
+
textStyle:
|
|
105
|
+
textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
|
|
106
|
+
type: node.__type,
|
|
107
|
+
version: 1,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
112
|
+
function exportCompactMarkNode(node: MarkNode): {[key: string]: unknown} {
|
|
113
|
+
const textFormat = node.__textFormat;
|
|
114
|
+
const textStyle = node.__textStyle;
|
|
115
|
+
const shouldSerializeTextStyles =
|
|
116
|
+
(textFormat !== 0 || textStyle !== '') &&
|
|
117
|
+
node.shouldSerializeTextStyles();
|
|
118
|
+
const json: {[key: string]: unknown} = {type: node.__type, children: []};
|
|
119
|
+
const ids = node.getIDs();
|
|
120
|
+
if (ids !== undefined && !(Array.isArray(ids) && ids.length === 0)) {
|
|
121
|
+
json.ids = ids;
|
|
122
|
+
}
|
|
123
|
+
const direction = node.__dir;
|
|
124
|
+
if (direction != null) {
|
|
125
|
+
json.direction = direction;
|
|
126
|
+
}
|
|
127
|
+
const format = MARK_FORMAT_GETTER[node.__format];
|
|
128
|
+
if (format !== undefined && format !== '') {
|
|
129
|
+
json.format = format;
|
|
130
|
+
}
|
|
131
|
+
const indent = node.__indent;
|
|
132
|
+
if (indent !== undefined && indent !== 0) {
|
|
133
|
+
json.indent = indent;
|
|
134
|
+
}
|
|
135
|
+
if (
|
|
136
|
+
textFormat !== undefined &&
|
|
137
|
+
textFormat !== 0 &&
|
|
138
|
+
shouldSerializeTextStyles
|
|
139
|
+
) {
|
|
140
|
+
json.textFormat = textFormat;
|
|
141
|
+
}
|
|
142
|
+
if (
|
|
143
|
+
textStyle !== undefined &&
|
|
144
|
+
textStyle !== '' &&
|
|
145
|
+
shouldSerializeTextStyles
|
|
146
|
+
) {
|
|
147
|
+
json.textStyle = textStyle;
|
|
148
|
+
}
|
|
149
|
+
return json;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Generated from MarkNode's serialization schema. Do not edit by hand. */
|
|
153
|
+
function updateMarkNode(
|
|
154
|
+
node: MarkNode,
|
|
155
|
+
json: {readonly [key: string]: unknown},
|
|
156
|
+
): MarkNode {
|
|
157
|
+
const direction = json.direction;
|
|
158
|
+
node.__dir =
|
|
159
|
+
direction === null || direction === 'ltr' || direction === 'rtl'
|
|
160
|
+
? direction
|
|
161
|
+
: null;
|
|
162
|
+
const format = json.format;
|
|
163
|
+
node.__format =
|
|
164
|
+
typeof format === 'string' && format in MARK_FORMAT_SETTER
|
|
165
|
+
? MARK_FORMAT_SETTER[format]
|
|
166
|
+
: MARK_FORMAT_SETTER_DEFAULT;
|
|
167
|
+
node.__indent = numC(json.indent, 0, 0, Infinity, true);
|
|
168
|
+
node.__textFormat = num(json.textFormat, 0);
|
|
169
|
+
const textStyle = json.textStyle;
|
|
170
|
+
node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
|
|
171
|
+
const ids = json.ids;
|
|
172
|
+
node.__ids = Array.isArray(ids)
|
|
173
|
+
? Array.from(ids, e0 => (typeof e0 === 'string' ? e0 : ''))
|
|
174
|
+
: [];
|
|
175
|
+
return node;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
exportJSON: exportMarkNode,
|
|
180
|
+
exportCompactJSON: exportCompactMarkNode,
|
|
181
|
+
updateFromJSON: updateMarkNode,
|
|
182
|
+
afterCloneFrom: afterCloneMarkNode,
|
|
183
|
+
};
|
|
184
|
+
};
|
package/src/MarkNode.ts
CHANGED
|
@@ -11,18 +11,25 @@ import {
|
|
|
11
11
|
$getDocument,
|
|
12
12
|
$isRangeSelection,
|
|
13
13
|
addClassNamesToElement,
|
|
14
|
+
arrayValue,
|
|
14
15
|
type BaseSelection,
|
|
15
16
|
type EditorConfig,
|
|
16
17
|
ElementNode,
|
|
17
18
|
type LexicalNode,
|
|
18
|
-
type
|
|
19
|
+
type LexicalParseJSON,
|
|
19
20
|
type NodeKey,
|
|
21
|
+
nodeSchema,
|
|
20
22
|
type RangeSelection,
|
|
21
23
|
removeClassNamesFromElement,
|
|
22
24
|
type SerializedElementNode,
|
|
25
|
+
type SerializedPartial,
|
|
23
26
|
type Spread,
|
|
27
|
+
stringValue,
|
|
28
|
+
withAccessors,
|
|
24
29
|
} from 'lexical';
|
|
25
30
|
|
|
31
|
+
import {GENERATED_MARK} from './LexicalMarkGeneratedJSON';
|
|
32
|
+
|
|
26
33
|
export type SerializedMarkNode = Spread<
|
|
27
34
|
{
|
|
28
35
|
ids: string[];
|
|
@@ -30,31 +37,39 @@ export type SerializedMarkNode = Spread<
|
|
|
30
37
|
SerializedElementNode
|
|
31
38
|
>;
|
|
32
39
|
|
|
40
|
+
// Single source of truth for parsing the node-specific properties of a
|
|
41
|
+
// SerializedMarkNode (those it adds over a SerializedElementNode).
|
|
42
|
+
const markNodeSchema = nodeSchema<MarkNode>()({
|
|
43
|
+
// The getter stays a method: getIDs hands out a copy, so the export does not
|
|
44
|
+
// give a caller the node's own array. The setter is the field it writes,
|
|
45
|
+
// which is also what tells the clone where `ids` lives.
|
|
46
|
+
ids: withAccessors(arrayValue(stringValue()), {
|
|
47
|
+
getter: 'getIDs',
|
|
48
|
+
setter: {field: '__ids', method: 'setIDs'},
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
|
|
33
52
|
const NO_IDS: readonly string[] = [];
|
|
34
53
|
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
55
|
+
export interface MarkNode {
|
|
56
|
+
exportJSON(compact?: false): SerializedMarkNode;
|
|
57
|
+
exportJSON(compact: boolean): SerializedPartial<SerializedMarkNode>;
|
|
58
|
+
updateFromJSON(serializedNode: LexicalParseJSON<SerializedMarkNode>): this;
|
|
59
|
+
}
|
|
60
|
+
|
|
35
61
|
/** @noInheritDoc */
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
36
63
|
export class MarkNode extends ElementNode {
|
|
37
64
|
/** @internal */
|
|
38
65
|
__ids: readonly string[];
|
|
39
66
|
|
|
40
67
|
$config() {
|
|
41
|
-
return this.config('mark', {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.__ids = prevNode.__ids;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedMarkNode>): this {
|
|
50
|
-
return super.updateFromJSON(serializedNode).setIDs(serializedNode.ids);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
exportJSON(): SerializedMarkNode {
|
|
54
|
-
return {
|
|
55
|
-
...super.exportJSON(),
|
|
56
|
-
ids: this.getIDs(),
|
|
57
|
-
};
|
|
68
|
+
return this.config('mark', {
|
|
69
|
+
extends: ElementNode,
|
|
70
|
+
generated: GENERATED_MARK,
|
|
71
|
+
json: markNodeSchema,
|
|
72
|
+
});
|
|
58
73
|
}
|
|
59
74
|
|
|
60
75
|
constructor(ids: readonly string[] = NO_IDS, key?: NodeKey) {
|