Skip to content

Commit 7c21d4f

Browse files
authored
[Breaking Change][lexical] Feature: Add updateFromJSON and move more textFormat/textStyle to ElementNode (facebook#6970)
1 parent aaa9009 commit 7c21d4f

File tree

66 files changed

+809
-578
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+809
-578
lines changed

packages/lexical-code/src/CodeHighlightNode.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
EditorConfig,
1111
EditorThemeClasses,
1212
LexicalNode,
13+
LexicalUpdateJSON,
1314
LineBreakNode,
1415
NodeKey,
1516
SerializedTextNode,
@@ -97,7 +98,7 @@ export class CodeHighlightNode extends TextNode {
9798
__highlightType: string | null | undefined;
9899

99100
constructor(
100-
text: string,
101+
text: string = '',
101102
highlightType?: string | null | undefined,
102103
key?: NodeKey,
103104
) {
@@ -122,6 +123,12 @@ export class CodeHighlightNode extends TextNode {
122123
return self.__highlightType;
123124
}
124125

126+
setHighlightType(highlightType?: string | null | undefined): this {
127+
const self = this.getWritable();
128+
self.__highlightType = highlightType || undefined;
129+
return self;
130+
}
131+
125132
canHaveFormat(): boolean {
126133
return false;
127134
}
@@ -160,15 +167,15 @@ export class CodeHighlightNode extends TextNode {
160167
static importJSON(
161168
serializedNode: SerializedCodeHighlightNode,
162169
): CodeHighlightNode {
163-
const node = $createCodeHighlightNode(
164-
serializedNode.text,
165-
serializedNode.highlightType,
166-
);
167-
node.setFormat(serializedNode.format);
168-
node.setDetail(serializedNode.detail);
169-
node.setMode(serializedNode.mode);
170-
node.setStyle(serializedNode.style);
171-
return node;
170+
return $createCodeHighlightNode().updateFromJSON(serializedNode);
171+
}
172+
173+
updateFromJSON(
174+
serializedNode: LexicalUpdateJSON<SerializedCodeHighlightNode>,
175+
): this {
176+
return super
177+
.updateFromJSON(serializedNode)
178+
.setHighlightType(serializedNode.highlightType);
172179
}
173180

174181
exportJSON(): SerializedCodeHighlightNode {
@@ -205,7 +212,7 @@ function getHighlightThemeClass(
205212
}
206213

207214
export function $createCodeHighlightNode(
208-
text: string,
215+
text: string = '',
209216
highlightType?: string | null | undefined,
210217
): CodeHighlightNode {
211218
return $applyNodeReplacement(new CodeHighlightNode(text, highlightType));

packages/lexical-code/src/CodeNode.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
EditorConfig,
1515
LexicalEditor,
1616
LexicalNode,
17+
LexicalUpdateJSON,
1718
NodeKey,
1819
ParagraphNode,
1920
RangeSelection,
@@ -88,7 +89,7 @@ export class CodeNode extends ElementNode {
8889

8990
constructor(language?: string | null | undefined, key?: NodeKey) {
9091
super(key);
91-
this.__language = language;
92+
this.__language = language || undefined;
9293
this.__isSyntaxHighlightSupported = isLanguageSupportedByPrism(language);
9394
}
9495

@@ -212,11 +213,13 @@ export class CodeNode extends ElementNode {
212213
}
213214

214215
static importJSON(serializedNode: SerializedCodeNode): CodeNode {
215-
const node = $createCodeNode(serializedNode.language);
216-
node.setFormat(serializedNode.format);
217-
node.setIndent(serializedNode.indent);
218-
node.setDirection(serializedNode.direction);
219-
return node;
216+
return $createCodeNode().updateFromJSON(serializedNode);
217+
}
218+
219+
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedCodeNode>): this {
220+
return super
221+
.updateFromJSON(serializedNode)
222+
.setLanguage(serializedNode.language);
220223
}
221224

222225
exportJSON(): SerializedCodeNode {
@@ -317,11 +320,12 @@ export class CodeNode extends ElementNode {
317320
return true;
318321
}
319322

320-
setLanguage(language: string): void {
323+
setLanguage(language: string | null | undefined): this {
321324
const writable = this.getWritable();
322-
writable.__language = language;
325+
writable.__language = language || undefined;
323326
writable.__isSyntaxHighlightSupported =
324327
isLanguageSupportedByPrism(language);
328+
return writable;
325329
}
326330

327331
getLanguage(): string | null | undefined {

packages/lexical-hashtag/src/LexicalHashtagNode.ts

+2-16
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@
66
*
77
*/
88

9-
import type {
10-
EditorConfig,
11-
LexicalNode,
12-
NodeKey,
13-
SerializedTextNode,
14-
} from 'lexical';
9+
import type {EditorConfig, LexicalNode, SerializedTextNode} from 'lexical';
1510

1611
import {addClassNamesToElement} from '@lexical/utils';
1712
import {$applyNodeReplacement, TextNode} from 'lexical';
@@ -26,23 +21,14 @@ export class HashtagNode extends TextNode {
2621
return new HashtagNode(node.__text, node.__key);
2722
}
2823

29-
constructor(text: string, key?: NodeKey) {
30-
super(text, key);
31-
}
32-
3324
createDOM(config: EditorConfig): HTMLElement {
3425
const element = super.createDOM(config);
3526
addClassNamesToElement(element, config.theme.hashtag);
3627
return element;
3728
}
3829

3930
static importJSON(serializedNode: SerializedTextNode): HashtagNode {
40-
const node = $createHashtagNode(serializedNode.text);
41-
node.setFormat(serializedNode.format);
42-
node.setDetail(serializedNode.detail);
43-
node.setMode(serializedNode.mode);
44-
node.setStyle(serializedNode.style);
45-
return node;
31+
return $createHashtagNode().updateFromJSON(serializedNode);
4632
}
4733

4834
canInsertTextBefore(): boolean {

packages/lexical-link/src/index.ts

+42-31
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
EditorConfig,
1414
LexicalCommand,
1515
LexicalNode,
16+
LexicalUpdateJSON,
1617
NodeKey,
1718
Point,
1819
RangeSelection,
@@ -87,7 +88,11 @@ export class LinkNode extends ElementNode {
8788
);
8889
}
8990

90-
constructor(url: string, attributes: LinkAttributes = {}, key?: NodeKey) {
91+
constructor(
92+
url: string = '',
93+
attributes: LinkAttributes = {},
94+
key?: NodeKey,
95+
) {
9196
super(key);
9297
const {target = null, rel = null, title = null} = attributes;
9398
this.__url = url;
@@ -162,18 +167,17 @@ export class LinkNode extends ElementNode {
162167
};
163168
}
164169

165-
static importJSON(
166-
serializedNode: SerializedLinkNode | SerializedAutoLinkNode,
167-
): LinkNode {
168-
const node = $createLinkNode(serializedNode.url, {
169-
rel: serializedNode.rel,
170-
target: serializedNode.target,
171-
title: serializedNode.title,
172-
});
173-
node.setFormat(serializedNode.format);
174-
node.setIndent(serializedNode.indent);
175-
node.setDirection(serializedNode.direction);
176-
return node;
170+
static importJSON(serializedNode: SerializedLinkNode): LinkNode {
171+
return $createLinkNode().updateFromJSON(serializedNode);
172+
}
173+
174+
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedLinkNode>): this {
175+
return super
176+
.updateFromJSON(serializedNode)
177+
.setURL(serializedNode.url)
178+
.setRel(serializedNode.rel || null)
179+
.setTarget(serializedNode.target || null)
180+
.setTitle(serializedNode.title || null);
177181
}
178182

179183
sanitizeUrl(url: string): string {
@@ -203,36 +207,40 @@ export class LinkNode extends ElementNode {
203207
return this.getLatest().__url;
204208
}
205209

206-
setURL(url: string): void {
210+
setURL(url: string): this {
207211
const writable = this.getWritable();
208212
writable.__url = url;
213+
return writable;
209214
}
210215

211216
getTarget(): null | string {
212217
return this.getLatest().__target;
213218
}
214219

215-
setTarget(target: null | string): void {
220+
setTarget(target: null | string): this {
216221
const writable = this.getWritable();
217222
writable.__target = target;
223+
return writable;
218224
}
219225

220226
getRel(): null | string {
221227
return this.getLatest().__rel;
222228
}
223229

224-
setRel(rel: null | string): void {
230+
setRel(rel: null | string): this {
225231
const writable = this.getWritable();
226232
writable.__rel = rel;
233+
return writable;
227234
}
228235

229236
getTitle(): null | string {
230237
return this.getLatest().__title;
231238
}
232239

233-
setTitle(title: null | string): void {
240+
setTitle(title: null | string): this {
234241
const writable = this.getWritable();
235242
writable.__title = title;
243+
return writable;
236244
}
237245

238246
insertNewAfter(
@@ -316,7 +324,7 @@ function $convertAnchorElement(domNode: Node): DOMConversionOutput {
316324
* @returns The LinkNode.
317325
*/
318326
export function $createLinkNode(
319-
url: string,
327+
url: string = '',
320328
attributes?: LinkAttributes,
321329
): LinkNode {
322330
return $applyNodeReplacement(new LinkNode(url, attributes));
@@ -347,7 +355,11 @@ export class AutoLinkNode extends LinkNode {
347355
/** Indicates whether the autolink was ever unlinked. **/
348356
__isUnlinked: boolean;
349357

350-
constructor(url: string, attributes: AutoLinkAttributes = {}, key?: NodeKey) {
358+
constructor(
359+
url: string = '',
360+
attributes: AutoLinkAttributes = {},
361+
key?: NodeKey,
362+
) {
351363
super(url, attributes, key);
352364
this.__isUnlinked =
353365
attributes.isUnlinked !== undefined && attributes.isUnlinked !== null
@@ -376,7 +388,7 @@ export class AutoLinkNode extends LinkNode {
376388
return this.__isUnlinked;
377389
}
378390

379-
setIsUnlinked(value: boolean) {
391+
setIsUnlinked(value: boolean): this {
380392
const self = this.getWritable();
381393
self.__isUnlinked = value;
382394
return self;
@@ -402,16 +414,15 @@ export class AutoLinkNode extends LinkNode {
402414
}
403415

404416
static importJSON(serializedNode: SerializedAutoLinkNode): AutoLinkNode {
405-
const node = $createAutoLinkNode(serializedNode.url, {
406-
isUnlinked: serializedNode.isUnlinked,
407-
rel: serializedNode.rel,
408-
target: serializedNode.target,
409-
title: serializedNode.title,
410-
});
411-
node.setFormat(serializedNode.format);
412-
node.setIndent(serializedNode.indent);
413-
node.setDirection(serializedNode.direction);
414-
return node;
417+
return $createAutoLinkNode().updateFromJSON(serializedNode);
418+
}
419+
420+
updateFromJSON(
421+
serializedNode: LexicalUpdateJSON<SerializedAutoLinkNode>,
422+
): this {
423+
return super
424+
.updateFromJSON(serializedNode)
425+
.setIsUnlinked(serializedNode.isUnlinked || false);
415426
}
416427

417428
static importDOM(): null {
@@ -456,7 +467,7 @@ export class AutoLinkNode extends LinkNode {
456467
* @returns The LinkNode.
457468
*/
458469
export function $createAutoLinkNode(
459-
url: string,
470+
url: string = '',
460471
attributes?: AutoLinkAttributes,
461472
): AutoLinkNode {
462473
return $applyNodeReplacement(new AutoLinkNode(url, attributes));

packages/lexical-list/src/LexicalListItemNode.ts

+22-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
EditorConfig,
1616
EditorThemeClasses,
1717
LexicalNode,
18+
LexicalUpdateJSON,
1819
NodeKey,
1920
ParagraphNode,
2021
RangeSelection,
@@ -123,12 +124,16 @@ export class ListItemNode extends ElementNode {
123124
}
124125

125126
static importJSON(serializedNode: SerializedListItemNode): ListItemNode {
126-
const node = $createListItemNode();
127-
node.setChecked(serializedNode.checked);
128-
node.setValue(serializedNode.value);
129-
node.setFormat(serializedNode.format);
130-
node.setDirection(serializedNode.direction);
131-
return node;
127+
return $createListItemNode().updateFromJSON(serializedNode);
128+
}
129+
130+
updateFromJSON(
131+
serializedNode: LexicalUpdateJSON<SerializedListItemNode>,
132+
): this {
133+
return super
134+
.updateFromJSON(serializedNode)
135+
.setValue(serializedNode.value)
136+
.setChecked(serializedNode.checked);
132137
}
133138

134139
exportDOM(editor: LexicalEditor): DOMExportOutput {
@@ -257,9 +262,10 @@ export class ListItemNode extends ElementNode {
257262
_: RangeSelection,
258263
restoreSelection = true,
259264
): ListItemNode | ParagraphNode {
260-
const newElement = $createListItemNode(
261-
this.__checked == null ? undefined : false,
262-
);
265+
const newElement = $createListItemNode()
266+
.updateFromJSON(this.exportJSON())
267+
.setChecked(this.getChecked() ? false : undefined);
268+
263269
this.insertAfter(newElement, restoreSelection);
264270

265271
return newElement;
@@ -310,9 +316,10 @@ export class ListItemNode extends ElementNode {
310316
return self.__value;
311317
}
312318

313-
setValue(value: number): void {
319+
setValue(value: number): this {
314320
const self = this.getWritable();
315321
self.__value = value;
322+
return self;
316323
}
317324

318325
getChecked(): boolean | undefined {
@@ -328,13 +335,15 @@ export class ListItemNode extends ElementNode {
328335
return listType === 'check' ? Boolean(self.__checked) : undefined;
329336
}
330337

331-
setChecked(checked?: boolean): void {
338+
setChecked(checked?: boolean): this {
332339
const self = this.getWritable();
333340
self.__checked = checked;
341+
return self;
334342
}
335343

336-
toggleChecked(): void {
337-
this.setChecked(!this.__checked);
344+
toggleChecked(): this {
345+
const self = this.getWritable();
346+
return self.setChecked(!self.__checked);
338347
}
339348

340349
getIndent(): number {

0 commit comments

Comments
 (0)