Needs linking up to the table form still.
markDirty(): void {
this.getWritable();
}
+
+ /**
+ * Insert the DOM of this node into that of the parent.
+ * Allows this node to implement custom DOM attachment logic.
+ * Boolean result indicates if the insertion was handled by the function.
+ * A true return value prevents default insertion logic from taking place.
+ */
+ insertDOMIntoParent(nodeDOM: HTMLElement, parentDOM: HTMLElement): boolean {
+ return false;
+ }
}
function errorOnTypeKlassMismatch(
}
if (parentDOM !== null) {
- if (insertDOM != null) {
- parentDOM.insertBefore(dom, insertDOM);
- } else {
- // @ts-expect-error: internal field
- const possibleLineBreak = parentDOM.__lexicalLineBreak;
- if (possibleLineBreak != null) {
- parentDOM.insertBefore(dom, possibleLineBreak);
+ const inserted = node?.insertDOMIntoParent(dom, parentDOM);
+
+ if (!inserted) {
+ if (insertDOM != null) {
+ parentDOM.insertBefore(dom, insertDOM);
} else {
- parentDOM.appendChild(dom);
+ // @ts-expect-error: internal field
+ const possibleLineBreak = parentDOM.__lexicalLineBreak;
+
+ if (possibleLineBreak != null) {
+ parentDOM.insertBefore(dom, possibleLineBreak);
+ } else {
+ parentDOM.appendChild(dom);
+ }
}
}
}
--- /dev/null
+import {
+ DOMConversionMap,
+ DOMExportOutput,
+ EditorConfig,
+ ElementNode,
+ LexicalEditor,
+ LexicalNode,
+ SerializedElementNode
+} from "lexical";
+
+
+export class CaptionNode extends ElementNode {
+ static getType(): string {
+ return 'caption';
+ }
+
+ static clone(node: CaptionNode): CaptionNode {
+ return new CaptionNode(node.__key);
+ }
+
+ createDOM(_config: EditorConfig, _editor: LexicalEditor): HTMLElement {
+ return document.createElement('caption');
+ }
+
+ updateDOM(_prevNode: unknown, _dom: HTMLElement, _config: EditorConfig): boolean {
+ return false;
+ }
+
+ isParentRequired(): true {
+ return true;
+ }
+
+ canBeEmpty(): boolean {
+ return false;
+ }
+
+ exportJSON(): SerializedElementNode {
+ return {
+ ...super.exportJSON(),
+ type: 'caption',
+ version: 1,
+ };
+ }
+
+ insertDOMIntoParent(nodeDOM: HTMLElement, parentDOM: HTMLElement): boolean {
+ parentDOM.insertBefore(nodeDOM, parentDOM.firstChild);
+ return true;
+ }
+
+ static importJSON(serializedNode: SerializedElementNode): CaptionNode {
+ return $createCaptionNode();
+ }
+
+ static importDOM(): DOMConversionMap | null {
+ return {
+ caption: (node: Node) => ({
+ conversion(domNode: Node) {
+ return {
+ node: $createCaptionNode(),
+ }
+ },
+ priority: 0,
+ }),
+ };
+ }
+}
+
+export function $createCaptionNode(): CaptionNode {
+ return new CaptionNode();
+}
+
+export function $isCaptionNode(node: LexicalNode | null | undefined): node is CaptionNode {
+ return node instanceof CaptionNode;
+}
\ No newline at end of file
for (const child of Array.from(tableElement.children)) {
if (child.nodeName === 'TR') {
tBody.append(child);
+ } else if (child.nodeName === 'CAPTION') {
+ newElement.insertBefore(child, newElement.firstChild);
} else {
newElement.append(child);
}
import {MediaNode} from "@lexical/rich-text/LexicalMediaNode";
import {HeadingNode} from "@lexical/rich-text/LexicalHeadingNode";
import {QuoteNode} from "@lexical/rich-text/LexicalQuoteNode";
+import {CaptionNode} from "@lexical/table/LexicalCaptionNode";
/**
* Load the nodes for lexical.
TableNode,
TableRowNode,
TableCellNode,
+ CaptionNode,
ImageNode, // TODO - Alignment
HorizontalRuleNode,
DetailsNode,