From 6b2edc5d820891acf04fc75982ba8d529317b6ed Mon Sep 17 00:00:00 2001 From: Timo Santi Date: Tue, 10 Oct 2023 05:22:58 +0300 Subject: [PATCH] [Bug]: HTML output of Table is missing colgroup element (#4281) * [Bug]: HTML output of Table is missing colgroup element Fixes #4280 * Fixed typo and added some documentation --- demos/src/Nodes/Table/React/index.spec.js | 4 +- demos/src/Nodes/Table/Vue/index.spec.js | 4 +- packages/extension-table/src/table.ts | 22 +++++++- .../src/utilities/createColGroup.ts | 51 +++++++++++++++++++ 4 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 packages/extension-table/src/utilities/createColGroup.ts diff --git a/demos/src/Nodes/Table/React/index.spec.js b/demos/src/Nodes/Table/React/index.spec.js index 28396028a..57530920d 100644 --- a/demos/src/Nodes/Table/React/index.spec.js +++ b/demos/src/Nodes/Table/React/index.spec.js @@ -63,7 +63,7 @@ context('/src/Nodes/Table/React/', () => { const html = editor.getHTML() expect(html).to.equal( - '

', + '

', ) }) }) @@ -75,7 +75,7 @@ context('/src/Nodes/Table/React/', () => { const html = editor.getHTML() expect(html).to.equal( - '

', + '

', ) }) }) diff --git a/demos/src/Nodes/Table/Vue/index.spec.js b/demos/src/Nodes/Table/Vue/index.spec.js index bdb1dada6..09082c895 100644 --- a/demos/src/Nodes/Table/Vue/index.spec.js +++ b/demos/src/Nodes/Table/Vue/index.spec.js @@ -62,7 +62,7 @@ context('/src/Nodes/Table/Vue/', () => { const html = editor.getHTML() - expect(html).to.equal('

') + expect(html).to.equal('

') }) }) @@ -72,7 +72,7 @@ context('/src/Nodes/Table/Vue/', () => { const html = editor.getHTML() - expect(html).to.equal('

') + expect(html).to.equal('

') }) }) diff --git a/packages/extension-table/src/table.ts b/packages/extension-table/src/table.ts index 944f7bd05..b16898105 100644 --- a/packages/extension-table/src/table.ts +++ b/packages/extension-table/src/table.ts @@ -22,8 +22,10 @@ import { toggleHeaderCell, } from '@tiptap/pm/tables' import { NodeView } from '@tiptap/pm/view' +import { DOMOutputSpec } from 'prosemirror-model' import { TableView } from './TableView.js' +import { createColGroup } from './utilities/createColGroup.js' import { createTable } from './utilities/createTable.js' import { deleteTableWhenAllCellsSelected } from './utilities/deleteTableWhenAllCellsSelected.js' @@ -110,8 +112,24 @@ export const Table = Node.create({ return [{ tag: 'table' }] }, - renderHTML({ HTMLAttributes }) { - return ['table', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), ['tbody', 0]] + renderHTML({ node, HTMLAttributes }) { + const { colgroup, tableWidth, tableMinWidth } = createColGroup( + node, + this.options.cellMinWidth, + ) + + const table: DOMOutputSpec = [ + 'table', + mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { + style: tableWidth + ? `width: ${tableWidth}` + : `minWidth: ${tableMinWidth}`, + }), + colgroup, + ['tbody', 0], + ] + + return table }, addCommands() { diff --git a/packages/extension-table/src/utilities/createColGroup.ts b/packages/extension-table/src/utilities/createColGroup.ts new file mode 100644 index 000000000..c93dbf61a --- /dev/null +++ b/packages/extension-table/src/utilities/createColGroup.ts @@ -0,0 +1,51 @@ +import { Node as ProseMirrorNode } from '@tiptap/pm/model' +import { DOMOutputSpec } from 'prosemirror-model' + +/** + * Creates a colgroup element for a table node in ProseMirror. + * + * @param node - The ProseMirror node representing the table. + * @param cellMinWidth - The minimum width of a cell in the table. + * @param overrideCol - (Optional) The index of the column to override the width of. + * @param overrideValue - (Optional) The width value to use for the overridden column. + * @returns An object containing the colgroup element, the total width of the table, and the minimum width of the table. + */ +export function createColGroup( + node: ProseMirrorNode, + cellMinWidth: number, + overrideCol?: number, + overrideValue?: any, +) { + let totalWidth = 0 + let fixedWidth = true + const cols: DOMOutputSpec[] = [] + const row = node.firstChild + + if (!row) { + return {} + } + + for (let i = 0, col = 0; i < row.childCount; i += 1) { + const { colspan, colwidth } = row.child(i).attrs + + for (let j = 0; j < colspan; j += 1, col += 1) { + const hasWidth = overrideCol === col ? overrideValue : colwidth && colwidth[j] + const cssWidth = hasWidth ? `${hasWidth}px` : '' + + totalWidth += hasWidth || cellMinWidth + + if (!hasWidth) { + fixedWidth = false + } + + cols.push(['col', cssWidth ? { style: `width: ${cssWidth}` } : {}]) + } + } + + const tableWidth = fixedWidth ? `${totalWidth}px` : '' + const tableMinWidth = fixedWidth ? '' : `${totalWidth}px` + + const colgroup: DOMOutputSpec = ['colgroup', {}, ...cols] + + return { colgroup, tableWidth, tableMinWidth } +}