Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: HTML output of Table is missing colgroup element #4281

Merged
merged 2 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions demos/src/Nodes/Table/React/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ context('/src/Nodes/Table/React/', () => {
const html = editor.getHTML()

expect(html).to.equal(
'<table><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>',
'<table style="minWidth: 25px"><colgroup><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>',
)
})
})
Expand All @@ -75,7 +75,7 @@ context('/src/Nodes/Table/React/', () => {
const html = editor.getHTML()

expect(html).to.equal(
'<table><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>',
'<table style="minWidth: 25px"><colgroup><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>',
)
})
})
Expand Down
4 changes: 2 additions & 2 deletions demos/src/Nodes/Table/Vue/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ context('/src/Nodes/Table/Vue/', () => {

const html = editor.getHTML()

expect(html).to.equal('<table><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>')
expect(html).to.equal('<table style="minWidth: 25px"><colgroup><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>')
})
})

Expand All @@ -72,7 +72,7 @@ context('/src/Nodes/Table/Vue/', () => {

const html = editor.getHTML()

expect(html).to.equal('<table><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>')
expect(html).to.equal('<table style="minWidth: 25px"><colgroup><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>')
})
})

Expand Down
22 changes: 20 additions & 2 deletions packages/extension-table/src/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -110,8 +112,24 @@ export const Table = Node.create<TableOptions>({
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}`,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minWidth or min-width ?

}),
colgroup,
['tbody', 0],
]

return table
},

addCommands() {
Expand Down
51 changes: 51 additions & 0 deletions packages/extension-table/src/utilities/createColGroup.ts
Original file line number Diff line number Diff line change
@@ -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 }
}