mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-12-03 19:19:01 +08:00
parent
d6e4cafef3
commit
152390130e
5
.changeset/two-rats-watch.md
Normal file
5
.changeset/two-rats-watch.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/extension-table": patch
|
||||
---
|
||||
|
||||
enforce cellMinWidth even on column not resized by the user, fixes #5435
|
@ -56,6 +56,14 @@ context('/src/Nodes/Table/React/', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('sets the minimum width on the colgroups by default (3x1)', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.insertTable({ cols: 3, rows: 1, withHeaderRow: false })
|
||||
|
||||
cy.get('.tiptap').find('col').invoke('attr', 'style').should('eq', 'min-width: 25px;')
|
||||
})
|
||||
})
|
||||
|
||||
it('generates correct markup for a table (1x1)', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
|
||||
@ -63,7 +71,7 @@ context('/src/Nodes/Table/React/', () => {
|
||||
const html = editor.getHTML()
|
||||
|
||||
expect(html).to.equal(
|
||||
'<table style="min-width: 25px"><colgroup><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>',
|
||||
'<table style="min-width: 25px"><colgroup><col style="min-width: 25px"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>',
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -75,7 +83,7 @@ context('/src/Nodes/Table/React/', () => {
|
||||
const html = editor.getHTML()
|
||||
|
||||
expect(html).to.equal(
|
||||
'<table style="min-width: 25px"><colgroup><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>',
|
||||
'<table style="min-width: 25px"><colgroup><col style="min-width: 25px"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -56,13 +56,23 @@ context('/src/Nodes/Table/Vue/', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('sets the minimum width on the colgroups by default (3x1)', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.insertTable({ cols: 3, rows: 1, withHeaderRow: false })
|
||||
|
||||
cy.get('.tiptap').find('col').invoke('attr', 'style').should('eq', 'min-width: 25px;')
|
||||
})
|
||||
})
|
||||
|
||||
it('generates correct markup for a table (1x1)', () => {
|
||||
cy.get('.tiptap').then(([{ editor }]) => {
|
||||
editor.commands.insertTable({ cols: 1, rows: 1, withHeaderRow: false })
|
||||
|
||||
const html = editor.getHTML()
|
||||
|
||||
expect(html).to.equal('<table style="min-width: 25px"><colgroup><col></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>')
|
||||
expect(html).to.equal(
|
||||
'<table style="min-width: 25px"><colgroup><col style="min-width: 25px"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -72,7 +82,9 @@ context('/src/Nodes/Table/Vue/', () => {
|
||||
|
||||
const html = editor.getHTML()
|
||||
|
||||
expect(html).to.equal('<table style="min-width: 25px"><colgroup><col></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>')
|
||||
expect(html).to.equal(
|
||||
'<table style="min-width: 25px"><colgroup><col style="min-width: 25px"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p></p></th></tr></tbody></table>',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1,41 +1,52 @@
|
||||
// @ts-nocheck
|
||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
import { NodeView } from '@tiptap/pm/view'
|
||||
|
||||
import { getColStyleDeclaration } from './utilities/colStyle.js'
|
||||
|
||||
export function updateColumns(
|
||||
node: ProseMirrorNode,
|
||||
colgroup: Element,
|
||||
table: Element,
|
||||
colgroup: HTMLTableColElement, // <colgroup> has the same prototype as <col>
|
||||
table: HTMLTableElement,
|
||||
cellMinWidth: number,
|
||||
overrideCol?: number,
|
||||
overrideValue?: any,
|
||||
overrideValue?: number,
|
||||
) {
|
||||
let totalWidth = 0
|
||||
let fixedWidth = true
|
||||
let nextDOM = colgroup.firstChild
|
||||
const row = node.firstChild
|
||||
|
||||
for (let i = 0, col = 0; i < row.childCount; i += 1) {
|
||||
const { colspan, colwidth } = row.child(i).attrs
|
||||
if (row !== null) {
|
||||
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` : ''
|
||||
for (let j = 0; j < colspan; j += 1, col += 1) {
|
||||
const hasWidth = overrideCol === col ? overrideValue : (colwidth && colwidth[j]) as number | undefined
|
||||
const cssWidth = hasWidth ? `${hasWidth}px` : ''
|
||||
|
||||
totalWidth += hasWidth || cellMinWidth
|
||||
totalWidth += hasWidth || cellMinWidth
|
||||
|
||||
if (!hasWidth) {
|
||||
fixedWidth = false
|
||||
}
|
||||
|
||||
if (!nextDOM) {
|
||||
colgroup.appendChild(document.createElement('col')).style.width = cssWidth
|
||||
} else {
|
||||
if (nextDOM.style.width !== cssWidth) {
|
||||
nextDOM.style.width = cssWidth
|
||||
if (!hasWidth) {
|
||||
fixedWidth = false
|
||||
}
|
||||
|
||||
nextDOM = nextDOM.nextSibling
|
||||
if (!nextDOM) {
|
||||
const colElement = document.createElement('col')
|
||||
|
||||
const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)
|
||||
|
||||
colElement.style.setProperty(propertyKey, propertyValue)
|
||||
|
||||
colgroup.appendChild(colElement)
|
||||
} else {
|
||||
if ((nextDOM as HTMLTableColElement).style.width !== cssWidth) {
|
||||
const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth);
|
||||
|
||||
(nextDOM as HTMLTableColElement).style.setProperty(propertyKey, propertyValue)
|
||||
}
|
||||
|
||||
nextDOM = nextDOM.nextSibling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,7 +54,7 @@ export function updateColumns(
|
||||
while (nextDOM) {
|
||||
const after = nextDOM.nextSibling
|
||||
|
||||
nextDOM.parentNode.removeChild(nextDOM)
|
||||
nextDOM.parentNode?.removeChild(nextDOM)
|
||||
nextDOM = after
|
||||
}
|
||||
|
||||
@ -61,13 +72,13 @@ export class TableView implements NodeView {
|
||||
|
||||
cellMinWidth: number
|
||||
|
||||
dom: Element
|
||||
dom: HTMLDivElement
|
||||
|
||||
table: Element
|
||||
table: HTMLTableElement
|
||||
|
||||
colgroup: Element
|
||||
colgroup: HTMLTableColElement
|
||||
|
||||
contentDOM: Element
|
||||
contentDOM: HTMLTableSectionElement
|
||||
|
||||
constructor(node: ProseMirrorNode, cellMinWidth: number) {
|
||||
this.node = node
|
||||
|
10
packages/extension-table/src/utilities/colStyle.ts
Normal file
10
packages/extension-table/src/utilities/colStyle.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export function getColStyleDeclaration(minWidth: number, width: number | undefined): [string, string] {
|
||||
if (width) {
|
||||
// apply the stored width unless it is below the configured minimum cell width
|
||||
return ['width', `${Math.max(width, minWidth)}px`]
|
||||
}
|
||||
|
||||
// set the minimum with on the column if it has no stored width
|
||||
return ['min-width', `${minWidth}px`]
|
||||
|
||||
}
|
@ -1,5 +1,13 @@
|
||||
import { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
|
||||
import { getColStyleDeclaration } from './colStyle.js'
|
||||
|
||||
export type ColGroup = {
|
||||
colgroup: DOMOutputSpec
|
||||
tableWidth: string
|
||||
tableMinWidth: string
|
||||
} | Record<string, never>;
|
||||
|
||||
/**
|
||||
* Creates a colgroup element for a table node in ProseMirror.
|
||||
*
|
||||
@ -9,12 +17,22 @@ import { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
* @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,
|
||||
): ColGroup
|
||||
export function createColGroup(
|
||||
node: ProseMirrorNode,
|
||||
cellMinWidth: number,
|
||||
overrideCol: number,
|
||||
overrideValue: number,
|
||||
): ColGroup
|
||||
export function createColGroup(
|
||||
node: ProseMirrorNode,
|
||||
cellMinWidth: number,
|
||||
overrideCol?: number,
|
||||
overrideValue?: any,
|
||||
) {
|
||||
overrideValue?: number,
|
||||
): ColGroup {
|
||||
let totalWidth = 0
|
||||
let fixedWidth = true
|
||||
const cols: DOMOutputSpec[] = []
|
||||
@ -28,8 +46,7 @@ export function createColGroup(
|
||||
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` : ''
|
||||
const hasWidth = overrideCol === col ? overrideValue : colwidth && colwidth[j] as number | undefined
|
||||
|
||||
totalWidth += hasWidth || cellMinWidth
|
||||
|
||||
@ -37,7 +54,12 @@ export function createColGroup(
|
||||
fixedWidth = false
|
||||
}
|
||||
|
||||
cols.push(['col', cssWidth ? { style: `width: ${cssWidth}` } : {}])
|
||||
const [property, value] = getColStyleDeclaration(cellMinWidth, hasWidth)
|
||||
|
||||
cols.push([
|
||||
'col',
|
||||
{ style: `${property}: ${value}` },
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user