mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Lexical: Added table cell node import logic
This commit is contained in:
parent
b3d3b14f79
commit
fcc1c2968d
@ -1,7 +1,24 @@
|
|||||||
import {EditorConfig} from "lexical/LexicalEditor";
|
import {
|
||||||
import {DOMExportOutput, LexicalEditor, LexicalNode, Spread} from "lexical";
|
$createParagraphNode,
|
||||||
|
$isElementNode,
|
||||||
|
$isLineBreakNode,
|
||||||
|
$isTextNode,
|
||||||
|
DOMConversionMap,
|
||||||
|
DOMConversionOutput,
|
||||||
|
DOMExportOutput,
|
||||||
|
EditorConfig,
|
||||||
|
LexicalEditor,
|
||||||
|
LexicalNode,
|
||||||
|
Spread
|
||||||
|
} from "lexical";
|
||||||
|
|
||||||
import {SerializedTableCellNode, TableCellHeaderStates, TableCellNode} from "@lexical/table";
|
import {
|
||||||
|
$createTableCellNode,
|
||||||
|
$isTableCellNode,
|
||||||
|
SerializedTableCellNode,
|
||||||
|
TableCellHeaderStates,
|
||||||
|
TableCellNode
|
||||||
|
} from "@lexical/table";
|
||||||
import {TableCellHeaderState} from "@lexical/table/LexicalTableCellNode";
|
import {TableCellHeaderState} from "@lexical/table/LexicalTableCellNode";
|
||||||
|
|
||||||
export type SerializedCustomTableCellNode = Spread<{
|
export type SerializedCustomTableCellNode = Spread<{
|
||||||
@ -54,13 +71,24 @@ export class CustomTableCellNode extends TableCellNode {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - Import DOM
|
|
||||||
|
|
||||||
updateDOM(prevNode: CustomTableCellNode): boolean {
|
updateDOM(prevNode: CustomTableCellNode): boolean {
|
||||||
return super.updateDOM(prevNode)
|
return super.updateDOM(prevNode)
|
||||||
|| this.__styles !== prevNode.__styles;
|
|| this.__styles !== prevNode.__styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static importDOM(): DOMConversionMap | null {
|
||||||
|
return {
|
||||||
|
td: (node: Node) => ({
|
||||||
|
conversion: $convertCustomTableCellNodeElement,
|
||||||
|
priority: 0,
|
||||||
|
}),
|
||||||
|
th: (node: Node) => ({
|
||||||
|
conversion: $convertCustomTableCellNodeElement,
|
||||||
|
priority: 0,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
||||||
const element = this.createDOM(editor._config);
|
const element = this.createDOM(editor._config);
|
||||||
return {
|
return {
|
||||||
@ -68,6 +96,18 @@ export class CustomTableCellNode extends TableCellNode {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static importJSON(serializedNode: SerializedCustomTableCellNode): CustomTableCellNode {
|
||||||
|
const node = $createCustomTableCellNode(
|
||||||
|
serializedNode.headerState,
|
||||||
|
serializedNode.colSpan,
|
||||||
|
serializedNode.width,
|
||||||
|
);
|
||||||
|
|
||||||
|
node.setStyles(new Map<string, string>(Object.entries(serializedNode.styles)));
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
exportJSON(): SerializedCustomTableCellNode {
|
exportJSON(): SerializedCustomTableCellNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
@ -77,6 +117,100 @@ export class CustomTableCellNode extends TableCellNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function $convertCustomTableCellNodeElement(domNode: Node): DOMConversionOutput {
|
||||||
|
const output = $convertTableCellNodeElement(domNode);
|
||||||
|
|
||||||
|
if (domNode instanceof HTMLElement && output.node instanceof CustomTableCellNode) {
|
||||||
|
const styleMap = new Map<string, string>();
|
||||||
|
const styleNames = Array.from(domNode.style);
|
||||||
|
for (const style of styleNames) {
|
||||||
|
styleMap.set(style, domNode.style.getPropertyValue(style));
|
||||||
|
}
|
||||||
|
output.node.setStyles(styleMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function taken from:
|
||||||
|
* https://github.com/facebook/lexical/blob/e1881a6e409e1541c10dd0b5378f3a38c9dc8c9e/packages/lexical-table/src/LexicalTableCellNode.ts#L289
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
* MIT LICENSE
|
||||||
|
* Modified since copy.
|
||||||
|
*/
|
||||||
|
export function $convertTableCellNodeElement(
|
||||||
|
domNode: Node,
|
||||||
|
): DOMConversionOutput {
|
||||||
|
const domNode_ = domNode as HTMLTableCellElement;
|
||||||
|
const nodeName = domNode.nodeName.toLowerCase();
|
||||||
|
|
||||||
|
let width: number | undefined = undefined;
|
||||||
|
|
||||||
|
|
||||||
|
const PIXEL_VALUE_REG_EXP = /^(\d+(?:\.\d+)?)px$/;
|
||||||
|
if (PIXEL_VALUE_REG_EXP.test(domNode_.style.width)) {
|
||||||
|
width = parseFloat(domNode_.style.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableCellNode = $createTableCellNode(
|
||||||
|
nodeName === 'th'
|
||||||
|
? TableCellHeaderStates.ROW
|
||||||
|
: TableCellHeaderStates.NO_STATUS,
|
||||||
|
domNode_.colSpan,
|
||||||
|
width,
|
||||||
|
);
|
||||||
|
|
||||||
|
tableCellNode.__rowSpan = domNode_.rowSpan;
|
||||||
|
|
||||||
|
const style = domNode_.style;
|
||||||
|
const textDecoration = style.textDecoration.split(' ');
|
||||||
|
const hasBoldFontWeight =
|
||||||
|
style.fontWeight === '700' || style.fontWeight === 'bold';
|
||||||
|
const hasLinethroughTextDecoration = textDecoration.includes('line-through');
|
||||||
|
const hasItalicFontStyle = style.fontStyle === 'italic';
|
||||||
|
const hasUnderlineTextDecoration = textDecoration.includes('underline');
|
||||||
|
return {
|
||||||
|
after: (childLexicalNodes) => {
|
||||||
|
if (childLexicalNodes.length === 0) {
|
||||||
|
childLexicalNodes.push($createParagraphNode());
|
||||||
|
}
|
||||||
|
return childLexicalNodes;
|
||||||
|
},
|
||||||
|
forChild: (lexicalNode, parentLexicalNode) => {
|
||||||
|
if ($isTableCellNode(parentLexicalNode) && !$isElementNode(lexicalNode)) {
|
||||||
|
const paragraphNode = $createParagraphNode();
|
||||||
|
if (
|
||||||
|
$isLineBreakNode(lexicalNode) &&
|
||||||
|
lexicalNode.getTextContent() === '\n'
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($isTextNode(lexicalNode)) {
|
||||||
|
if (hasBoldFontWeight) {
|
||||||
|
lexicalNode.toggleFormat('bold');
|
||||||
|
}
|
||||||
|
if (hasLinethroughTextDecoration) {
|
||||||
|
lexicalNode.toggleFormat('strikethrough');
|
||||||
|
}
|
||||||
|
if (hasItalicFontStyle) {
|
||||||
|
lexicalNode.toggleFormat('italic');
|
||||||
|
}
|
||||||
|
if (hasUnderlineTextDecoration) {
|
||||||
|
lexicalNode.toggleFormat('underline');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paragraphNode.append(lexicalNode);
|
||||||
|
return paragraphNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lexicalNode;
|
||||||
|
},
|
||||||
|
node: tableCellNode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function $createCustomTableCellNode(
|
export function $createCustomTableCellNode(
|
||||||
headerState: TableCellHeaderState,
|
headerState: TableCellHeaderState,
|
||||||
colSpan = 1,
|
colSpan = 1,
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
## In progress
|
## In progress
|
||||||
|
|
||||||
- Table features
|
- Table features
|
||||||
- CustomTableCellNode importDOM logic
|
|
||||||
- Merge cell action
|
- Merge cell action
|
||||||
- Row properties form logic
|
- Row properties form logic
|
||||||
- Table properties form logic
|
- Table properties form logic
|
||||||
|
Loading…
Reference in New Issue
Block a user