Skip to content

Commit 57d8449

Browse files
committed
Lexical: Merged custom table node code
1 parent ebd4604 commit 57d8449

17 files changed

+323
-788
lines changed

resources/js/wysiwyg/lexical/table/LexicalTableCellNode.ts

+86-48
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import {
2828
ElementNode,
2929
} from 'lexical';
3030

31-
import {COLUMN_WIDTH, PIXEL_VALUE_REG_EXP} from './constants';
31+
import {extractStyleMapFromElement, StyleMap} from "../../utils/dom";
32+
import {CommonBlockAlignment, extractAlignmentFromElement} from "../../nodes/_common";
3233

3334
export const TableCellHeaderStates = {
3435
BOTH: 3,
@@ -47,6 +48,8 @@ export type SerializedTableCellNode = Spread<
4748
headerState: TableCellHeaderState;
4849
width?: number;
4950
backgroundColor?: null | string;
51+
styles: Record<string, string>;
52+
alignment: CommonBlockAlignment;
5053
},
5154
SerializedElementNode
5255
>;
@@ -63,6 +66,10 @@ export class TableCellNode extends ElementNode {
6366
__width?: number;
6467
/** @internal */
6568
__backgroundColor: null | string;
69+
/** @internal */
70+
__styles: StyleMap = new Map;
71+
/** @internal */
72+
__alignment: CommonBlockAlignment = '';
6673

6774
static getType(): string {
6875
return 'tablecell';
@@ -77,6 +84,8 @@ export class TableCellNode extends ElementNode {
7784
);
7885
cellNode.__rowSpan = node.__rowSpan;
7986
cellNode.__backgroundColor = node.__backgroundColor;
87+
cellNode.__styles = new Map(node.__styles);
88+
cellNode.__alignment = node.__alignment;
8089
return cellNode;
8190
}
8291

@@ -94,16 +103,20 @@ export class TableCellNode extends ElementNode {
94103
}
95104

96105
static importJSON(serializedNode: SerializedTableCellNode): TableCellNode {
97-
const colSpan = serializedNode.colSpan || 1;
98-
const rowSpan = serializedNode.rowSpan || 1;
99-
const cellNode = $createTableCellNode(
100-
serializedNode.headerState,
101-
colSpan,
102-
serializedNode.width || undefined,
106+
const node = $createTableCellNode(
107+
serializedNode.headerState,
108+
serializedNode.colSpan,
109+
serializedNode.width,
103110
);
104-
cellNode.__rowSpan = rowSpan;
105-
cellNode.__backgroundColor = serializedNode.backgroundColor || null;
106-
return cellNode;
111+
112+
if (serializedNode.rowSpan) {
113+
node.setRowSpan(serializedNode.rowSpan);
114+
}
115+
116+
node.setStyles(new Map(Object.entries(serializedNode.styles)));
117+
node.setAlignment(serializedNode.alignment);
118+
119+
return node;
107120
}
108121

109122
constructor(
@@ -144,34 +157,19 @@ export class TableCellNode extends ElementNode {
144157
this.hasHeader() && config.theme.tableCellHeader,
145158
);
146159

160+
for (const [name, value] of this.__styles.entries()) {
161+
element.style.setProperty(name, value);
162+
}
163+
164+
if (this.__alignment) {
165+
element.classList.add('align-' + this.__alignment);
166+
}
167+
147168
return element;
148169
}
149170

150171
exportDOM(editor: LexicalEditor): DOMExportOutput {
151172
const {element} = super.exportDOM(editor);
152-
153-
if (element) {
154-
const element_ = element as HTMLTableCellElement;
155-
element_.style.border = '1px solid black';
156-
if (this.__colSpan > 1) {
157-
element_.colSpan = this.__colSpan;
158-
}
159-
if (this.__rowSpan > 1) {
160-
element_.rowSpan = this.__rowSpan;
161-
}
162-
element_.style.width = `${this.getWidth() || COLUMN_WIDTH}px`;
163-
164-
element_.style.verticalAlign = 'top';
165-
element_.style.textAlign = 'start';
166-
167-
const backgroundColor = this.getBackgroundColor();
168-
if (backgroundColor !== null) {
169-
element_.style.backgroundColor = backgroundColor;
170-
} else if (this.hasHeader()) {
171-
element_.style.backgroundColor = '#f2f3f5';
172-
}
173-
}
174-
175173
return {
176174
element,
177175
};
@@ -186,6 +184,8 @@ export class TableCellNode extends ElementNode {
186184
rowSpan: this.__rowSpan,
187185
type: 'tablecell',
188186
width: this.getWidth(),
187+
styles: Object.fromEntries(this.__styles),
188+
alignment: this.__alignment,
189189
};
190190
}
191191

@@ -231,6 +231,38 @@ export class TableCellNode extends ElementNode {
231231
return this.getLatest().__width;
232232
}
233233

234+
clearWidth(): void {
235+
const self = this.getWritable();
236+
self.__width = undefined;
237+
}
238+
239+
getStyles(): StyleMap {
240+
const self = this.getLatest();
241+
return new Map(self.__styles);
242+
}
243+
244+
setStyles(styles: StyleMap): void {
245+
const self = this.getWritable();
246+
self.__styles = new Map(styles);
247+
}
248+
249+
setAlignment(alignment: CommonBlockAlignment) {
250+
const self = this.getWritable();
251+
self.__alignment = alignment;
252+
}
253+
254+
getAlignment(): CommonBlockAlignment {
255+
const self = this.getLatest();
256+
return self.__alignment;
257+
}
258+
259+
updateTag(tag: string): void {
260+
const isHeader = tag.toLowerCase() === 'th';
261+
const state = isHeader ? TableCellHeaderStates.ROW : TableCellHeaderStates.NO_STATUS;
262+
const self = this.getWritable();
263+
self.__headerState = state;
264+
}
265+
234266
getBackgroundColor(): null | string {
235267
return this.getLatest().__backgroundColor;
236268
}
@@ -265,7 +297,9 @@ export class TableCellNode extends ElementNode {
265297
prevNode.__width !== this.__width ||
266298
prevNode.__colSpan !== this.__colSpan ||
267299
prevNode.__rowSpan !== this.__rowSpan ||
268-
prevNode.__backgroundColor !== this.__backgroundColor
300+
prevNode.__backgroundColor !== this.__backgroundColor ||
301+
prevNode.__styles !== this.__styles ||
302+
prevNode.__alignment !== this.__alignment
269303
);
270304
}
271305

@@ -287,38 +321,42 @@ export class TableCellNode extends ElementNode {
287321
}
288322

289323
export function $convertTableCellNodeElement(
290-
domNode: Node,
324+
domNode: Node,
291325
): DOMConversionOutput {
292326
const domNode_ = domNode as HTMLTableCellElement;
293327
const nodeName = domNode.nodeName.toLowerCase();
294328

295329
let width: number | undefined = undefined;
296330

331+
332+
const PIXEL_VALUE_REG_EXP = /^(\d+(?:\.\d+)?)px$/;
297333
if (PIXEL_VALUE_REG_EXP.test(domNode_.style.width)) {
298334
width = parseFloat(domNode_.style.width);
299335
}
300336

301337
const tableCellNode = $createTableCellNode(
302-
nodeName === 'th'
303-
? TableCellHeaderStates.ROW
304-
: TableCellHeaderStates.NO_STATUS,
305-
domNode_.colSpan,
306-
width,
338+
nodeName === 'th'
339+
? TableCellHeaderStates.ROW
340+
: TableCellHeaderStates.NO_STATUS,
341+
domNode_.colSpan,
342+
width,
307343
);
308344

309345
tableCellNode.__rowSpan = domNode_.rowSpan;
310-
const backgroundColor = domNode_.style.backgroundColor;
311-
if (backgroundColor !== '') {
312-
tableCellNode.__backgroundColor = backgroundColor;
313-
}
314346

315347
const style = domNode_.style;
316348
const textDecoration = style.textDecoration.split(' ');
317349
const hasBoldFontWeight =
318-
style.fontWeight === '700' || style.fontWeight === 'bold';
350+
style.fontWeight === '700' || style.fontWeight === 'bold';
319351
const hasLinethroughTextDecoration = textDecoration.includes('line-through');
320352
const hasItalicFontStyle = style.fontStyle === 'italic';
321353
const hasUnderlineTextDecoration = textDecoration.includes('underline');
354+
355+
if (domNode instanceof HTMLElement) {
356+
tableCellNode.setStyles(extractStyleMapFromElement(domNode));
357+
tableCellNode.setAlignment(extractAlignmentFromElement(domNode));
358+
}
359+
322360
return {
323361
after: (childLexicalNodes) => {
324362
if (childLexicalNodes.length === 0) {
@@ -330,8 +368,8 @@ export function $convertTableCellNodeElement(
330368
if ($isTableCellNode(parentLexicalNode) && !$isElementNode(lexicalNode)) {
331369
const paragraphNode = $createParagraphNode();
332370
if (
333-
$isLineBreakNode(lexicalNode) &&
334-
lexicalNode.getTextContent() === '\n'
371+
$isLineBreakNode(lexicalNode) &&
372+
lexicalNode.getTextContent() === '\n'
335373
) {
336374
return null;
337375
}
@@ -360,7 +398,7 @@ export function $convertTableCellNodeElement(
360398
}
361399

362400
export function $createTableCellNode(
363-
headerState: TableCellHeaderState,
401+
headerState: TableCellHeaderState = TableCellHeaderStates.NO_STATUS,
364402
colSpan = 1,
365403
width?: number,
366404
): TableCellNode {

0 commit comments

Comments
 (0)