snapshot of https://github.com/ueberdosis/tiptap.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
Some checks failed
Verify / Install node dependencies (push) Failing after 2s
Verify / Build packages (push) Has been skipped
Verify / Check linting & formatting (push) Has been skipped
Verify / Run unit tests (push) Has been skipped
Verify / Run e2e tests (shard 1/4) (push) Has been skipped
Verify / Run e2e tests (shard 2/4) (push) Has been skipped
Verify / Run e2e tests (shard 3/4) (push) Has been skipped
Verify / Run e2e tests (shard 4/4) (push) Has been skipped
Publish / Resolve publish config (push) Failing after 2s
Publish / Send notification to Slack (push) Has been skipped
Publish / Send failure notification to Slack (push) Failing after 8s
Verify / Merge e2e reports (push) Has been skipped
Publish / Build (push) Has been skipped
Publish / Bump Versions OR Release to Registry (push) Has been skipped
This commit is contained in:
154
packages/extension-table/src/table/TableView.ts
Normal file
154
packages/extension-table/src/table/TableView.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import type { Node as PMNode } from '@tiptap/pm/model'
|
||||
import type { EditorView, NodeView, ViewMutationRecord } from '@tiptap/pm/view'
|
||||
|
||||
import { getColStyleDeclaration } from './utilities/colStyle.js'
|
||||
|
||||
export function updateColumns(
|
||||
node: PMNode,
|
||||
colgroup: HTMLTableColElement, // <colgroup> has the same prototype as <col>
|
||||
table: HTMLTableElement,
|
||||
cellMinWidth: number,
|
||||
overrideCol?: number,
|
||||
overrideValue?: number,
|
||||
) {
|
||||
let totalWidth = 0
|
||||
let fixedWidth = true
|
||||
let nextDOM = colgroup.firstChild
|
||||
const row = node.firstChild
|
||||
|
||||
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]) as number | undefined)
|
||||
const cssWidth = hasWidth ? `${hasWidth}px` : ''
|
||||
|
||||
totalWidth += hasWidth || cellMinWidth
|
||||
|
||||
if (!hasWidth) {
|
||||
fixedWidth = false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (nextDOM) {
|
||||
const after = nextDOM.nextSibling
|
||||
|
||||
nextDOM.parentNode?.removeChild(nextDOM)
|
||||
nextDOM = after
|
||||
}
|
||||
|
||||
// Check if user has set a width style on the table node
|
||||
const hasUserWidth =
|
||||
node.attrs.style &&
|
||||
typeof node.attrs.style === 'string' &&
|
||||
/\bwidth\s*:/i.test(node.attrs.style)
|
||||
|
||||
if (fixedWidth && !hasUserWidth) {
|
||||
table.style.width = `${totalWidth}px`
|
||||
table.style.minWidth = ''
|
||||
} else {
|
||||
table.style.width = ''
|
||||
table.style.minWidth = `${totalWidth}px`
|
||||
}
|
||||
}
|
||||
|
||||
export class TableView implements NodeView {
|
||||
node: PMNode
|
||||
|
||||
cellMinWidth: number
|
||||
|
||||
dom: HTMLDivElement
|
||||
|
||||
table: HTMLTableElement
|
||||
|
||||
colgroup: HTMLTableColElement
|
||||
|
||||
contentDOM: HTMLTableSectionElement
|
||||
|
||||
constructor(
|
||||
node: PMNode,
|
||||
cellMinWidth: number,
|
||||
_view?: EditorView,
|
||||
HTMLAttributes: Record<string, any> = {},
|
||||
) {
|
||||
this.node = node
|
||||
this.cellMinWidth = cellMinWidth
|
||||
this.dom = document.createElement('div')
|
||||
this.dom.className = 'tableWrapper'
|
||||
this.table = this.dom.appendChild(document.createElement('table'))
|
||||
|
||||
// Apply extension-configured HTMLAttributes to the table element
|
||||
// (e.g. class, data-* set via Table.configure({ HTMLAttributes }))
|
||||
for (const [key, value] of Object.entries(HTMLAttributes)) {
|
||||
if (value !== undefined && value !== null) {
|
||||
if (key === 'style') {
|
||||
this.table.style.cssText = String(value)
|
||||
} else {
|
||||
this.table.setAttribute(key, String(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply user styles from the ProseMirror document node.
|
||||
// This may come from HTML parsing (e.g. <table style="...">) and should
|
||||
// override any style set via extension-configured HTMLAttributes above.
|
||||
if (node.attrs.style) {
|
||||
this.table.style.cssText = node.attrs.style
|
||||
}
|
||||
|
||||
this.colgroup = this.table.appendChild(document.createElement('colgroup'))
|
||||
updateColumns(node, this.colgroup, this.table, cellMinWidth)
|
||||
this.contentDOM = this.table.appendChild(document.createElement('tbody'))
|
||||
}
|
||||
|
||||
update(node: PMNode) {
|
||||
if (node.type !== this.node.type) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.node = node
|
||||
updateColumns(node, this.colgroup, this.table, this.cellMinWidth)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
ignoreMutation(mutation: ViewMutationRecord) {
|
||||
const target = mutation.target as Node
|
||||
const isInsideWrapper = this.dom.contains(target)
|
||||
const isInsideContent = this.contentDOM.contains(target)
|
||||
|
||||
if (isInsideWrapper && !isInsideContent) {
|
||||
if (
|
||||
mutation.type === 'attributes' ||
|
||||
mutation.type === 'childList' ||
|
||||
mutation.type === 'characterData'
|
||||
) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user