fix(table): respect resizeable columns colwidths (#4955)

This commit is contained in:
Jaap van Hoek 2024-10-04 14:17:08 +02:00 committed by GitHub
parent 087e5812a6
commit 21df331b60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 209 additions and 4 deletions

View File

@ -0,0 +1,7 @@
---
"@tiptap/extension-table-cell": patch
"@tiptap/extension-table-header": patch
---
Tables now properly respect colwidths with multiple values, fixing resizeable columns when the first row has a colspan

View File

@ -157,8 +157,8 @@ export default () => {
<table>
<tbody>
<tr>
<th>Name</th>
<th colspan="3">Description</th>
<th colwidth="200">Name</th>
<th colspan="3" colwidth="150,100">Description</th>
</tr>
<tr>
<td>Cyndi Lauper</td>

View File

@ -37,7 +37,7 @@ export const TableCell = Node.create<TableCellOptions>({
parseHTML: element => {
const colwidth = element.getAttribute('colwidth')
const value = colwidth
? [parseInt(colwidth, 10)]
? colwidth.split(',').map(width => parseInt(width, 10))
: null
return value

View File

@ -37,7 +37,7 @@ export const TableHeader = Node.create<TableHeaderOptions>({
parseHTML: element => {
const colwidth = element.getAttribute('colwidth')
const value = colwidth
? [parseInt(colwidth, 10)]
? colwidth.split(',').map(width => parseInt(width, 10))
: null
return value

View File

@ -0,0 +1,99 @@
/// <reference types="cypress" />
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import { Table } from '@tiptap/extension-table'
import { TableCell } from '@tiptap/extension-table-cell'
import { TableHeader } from '@tiptap/extension-table-header'
import { TableRow } from '@tiptap/extension-table-row'
import Text from '@tiptap/extension-text'
describe('extension table cell', () => {
const editorElClass = 'tiptap'
let editor: Editor | null = null
const createEditorEl = () => {
const editorEl = document.createElement('div')
editorEl.classList.add(editorElClass)
document.body.appendChild(editorEl)
return editorEl
}
const getEditorEl = () => document.querySelector(`.${editorElClass}`)
it('should start with a Table', () => {
const content = '<table style="width:100%"><tr><td>Firstname</td><td>Lastname</td><td>Age</td></tr><tr><td>Jill</td><td>Smith</td><td>50</td></tr><tr><td>Eve</td><td>Jackson</td><td>94</td></tr><tr><td>John</td><td>Doe</td><td>80</td></tr></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getHTML()).to.include('Jackson')
editor?.destroy()
getEditorEl()?.remove()
})
it('should parse a single colWidth', () => {
const content = '<table><tbody><tr><td colwidth="200">Name</td><td>Description</td></tr><tr><td>Cyndi Lauper</td><td>Singer</td><td>Songwriter</td><td>Actress</td></tr><tr><td>Marie Curie</td><td>Scientist</td><td>Chemist</td><td>Physicist</td></tr><tr><td>Indira Gandhi</td><td>Prime minister</td><td colspan="2">Politician</td></tr></tbody></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getJSON().content[0].content[0].content[0].attrs.colwidth[0]).to.eq(200)
editor?.destroy()
getEditorEl()?.remove()
})
it('should parse multiple colWidths', () => {
const content = '<table><tbody><tr><td colwidth="200">Name</td><td colspan="3" colwidth="150,100">Description</td></tr><tr><td>Cyndi Lauper</td><td>Singer</td><td>Songwriter</td><td>Actress</td></tr><tr><td>Marie Curie</td><td>Scientist</td><td>Chemist</td><td>Physicist</td></tr><tr><td>Indira Gandhi</td><td>Prime minister</td><td colspan="2">Politician</td></tr></tbody></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getJSON().content[0].content[0].content[1].attrs.colwidth).deep.equal([150, 100])
editor?.destroy()
getEditorEl()?.remove()
})
})

View File

@ -0,0 +1,99 @@
/// <reference types="cypress" />
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import { Table } from '@tiptap/extension-table'
import { TableCell } from '@tiptap/extension-table-cell'
import { TableHeader } from '@tiptap/extension-table-header'
import { TableRow } from '@tiptap/extension-table-row'
import Text from '@tiptap/extension-text'
describe('extension table header', () => {
const editorElClass = 'tiptap'
let editor: Editor | null = null
const createEditorEl = () => {
const editorEl = document.createElement('div')
editorEl.classList.add(editorElClass)
document.body.appendChild(editorEl)
return editorEl
}
const getEditorEl = () => document.querySelector(`.${editorElClass}`)
it('should start with a Table', () => {
const content = '<table style="width:100%"><tr><th>Firstname</th><th>Lastname</th><th>Age</th></tr><tr><td>Jill</td><td>Smith</td><td>50</td></tr><tr><td>Eve</td><td>Jackson</td><td>94</td></tr><tr><td>John</td><td>Doe</td><td>80</td></tr></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getHTML()).to.include('Jackson')
editor?.destroy()
getEditorEl()?.remove()
})
it('should parse a single colWidth', () => {
const content = '<table><tbody><tr><th colwidth="200">Name</th><th>Description</th></tr><tr><td>Cyndi Lauper</td><td>Singer</td><td>Songwriter</td><td>Actress</td></tr><tr><td>Marie Curie</td><td>Scientist</td><td>Chemist</td><td>Physicist</td></tr><tr><td>Indira Gandhi</td><td>Prime minister</td><td colspan="2">Politician</td></tr></tbody></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getJSON().content[0].content[0].content[0].attrs.colwidth[0]).to.eq(200)
editor?.destroy()
getEditorEl()?.remove()
})
it('should parse multiple colWidths', () => {
const content = '<table><tbody><tr><th colwidth="200">Name</th><th colspan="3" colwidth="150,100">Description</th></tr><tr><td>Cyndi Lauper</td><td>Singer</td><td>Songwriter</td><td>Actress</td></tr><tr><td>Marie Curie</td><td>Scientist</td><td>Chemist</td><td>Physicist</td></tr><tr><td>Indira Gandhi</td><td>Prime minister</td><td colspan="2">Politician</td></tr></tbody></table>'
editor = new Editor({
element: createEditorEl(),
extensions: [
Document,
Text,
Paragraph,
TableCell,
TableHeader,
TableRow,
Table.configure({
resizable: true,
}),
],
content,
})
expect(editor.getJSON().content[0].content[0].content[1].attrs.colwidth).deep.equal([150, 100])
editor?.destroy()
getEditorEl()?.remove()
})
})