@tiptap/extension-table 3.28.0 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -316,7 +316,9 @@ function renderTableToMarkdown(node, h, options = {}) {
316
316
  } else {
317
317
  raw = cellNode.content ? h.renderChildren(cellNode.content) : "";
318
318
  }
319
- const text = collapseWhitespace(raw);
319
+ const text = collapseWhitespace(
320
+ raw.split(cellSep).join("\n").replace(/[ \t]*\r?\n[ \t]*/g, "<br>")
321
+ );
320
322
  const isHeader = cellNode.type === "tableHeader";
321
323
  const align = normalizeTableCellAlignFromAttributes(cellNode.attrs);
322
324
  cells.push({ text, isHeader, align });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/table/table.ts","../../src/utils/parseAlign.ts","../../src/table/utilities/colStyle.ts","../../src/table/TableView.ts","../../src/table/utilities/createColGroup.ts","../../src/table/utilities/createCell.ts","../../src/table/utilities/getTableNodeTypes.ts","../../src/table/utilities/createTable.ts","../../src/table/utilities/deleteTableWhenAllCellsSelected.ts","../../src/table/utilities/isCellSelection.ts","../../src/table/utilities/markdown.ts"],"sourcesContent":["import '../types.js'\n\nimport {\n type JSONContent,\n type MarkdownToken,\n callOrReturn,\n getExtensionField,\n mergeAttributes,\n Node,\n} from '@tiptap/core'\nimport type { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { TextSelection } from '@tiptap/pm/state'\nimport {\n addColumnAfter,\n addColumnBefore,\n addRowAfter,\n addRowBefore,\n CellSelection,\n columnResizing,\n deleteColumn,\n deleteRow,\n deleteTable,\n fixTables,\n goToNextCell,\n mergeCells,\n setCellAttr,\n splitCell,\n tableEditing,\n toggleHeader,\n toggleHeaderCell,\n} from '@tiptap/pm/tables'\nimport type { EditorView, NodeView } from '@tiptap/pm/view'\n\nimport { type TableCellAlign, normalizeTableCellAlign } from '../utils/parseAlign.js'\nimport { TableView } from './TableView.js'\nimport { createColGroup } from './utilities/createColGroup.js'\nimport { createTable } from './utilities/createTable.js'\nimport { deleteTableWhenAllCellsSelected } from './utilities/deleteTableWhenAllCellsSelected.js'\nimport renderTableToMarkdown, { preprocessTablePipes } from './utilities/markdown.js'\n\ntype MarkdownTableToken = {\n align?: Array<TableCellAlign | null>\n header?: { tokens: MarkdownToken[]; align?: TableCellAlign | null }[]\n rows?: { tokens: MarkdownToken[]; align?: TableCellAlign | null }[][]\n} & MarkdownToken\n\nexport interface TableOptions {\n /**\n * HTML attributes for the table element.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>\n\n /**\n * Enables the resizing of tables.\n * @default false\n * @example true\n */\n resizable: boolean\n\n /**\n * Controls whether the table should be wrapped in a div with class \"tableWrapper\" when rendered.\n * In editable mode with resizable tables, this wrapper is always present via TableView.\n * @default false\n * @example true\n */\n renderWrapper: boolean\n\n /**\n * The width of the resize handle.\n * @default 5\n * @example 10\n */\n handleWidth: number\n\n /**\n * The minimum width of a cell.\n * @default 25\n * @example 50\n */\n cellMinWidth: number\n\n /**\n * The node view to render the table.\n * @default TableView\n */\n View:\n | (new (\n node: ProseMirrorNode,\n cellMinWidth: number,\n view: EditorView,\n HTMLAttributes?: Record<string, any>,\n ) => NodeView)\n | null\n\n /**\n * Enables the resizing of the last column.\n * @default true\n * @example false\n */\n lastColumnResizable: boolean\n\n /**\n * Allow table node selection.\n * @default false\n * @example true\n */\n allowTableNodeSelection: boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n table: {\n /**\n * Insert a table\n * @param options The table attributes\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n */\n insertTable: (options?: {\n rows?: number\n cols?: number\n withHeaderRow?: boolean\n }) => ReturnType\n\n /**\n * Add a column before the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addColumnBefore()\n */\n addColumnBefore: () => ReturnType\n\n /**\n * Add a column after the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addColumnAfter()\n */\n addColumnAfter: () => ReturnType\n\n /**\n * Delete the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteColumn()\n */\n deleteColumn: () => ReturnType\n\n /**\n * Add a row before the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addRowBefore()\n */\n addRowBefore: () => ReturnType\n\n /**\n * Add a row after the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addRowAfter()\n */\n addRowAfter: () => ReturnType\n\n /**\n * Delete the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteRow()\n */\n deleteRow: () => ReturnType\n\n /**\n * Delete the current table\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteTable()\n */\n deleteTable: () => ReturnType\n\n /**\n * Merge the currently selected cells\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.mergeCells()\n */\n mergeCells: () => ReturnType\n\n /**\n * Split the currently selected cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.splitCell()\n */\n splitCell: () => ReturnType\n\n /**\n * Toggle the header column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderColumn()\n */\n toggleHeaderColumn: () => ReturnType\n\n /**\n * Toggle the header row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderRow()\n */\n toggleHeaderRow: () => ReturnType\n\n /**\n * Toggle the header cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderCell()\n */\n toggleHeaderCell: () => ReturnType\n\n /**\n * Merge or split the currently selected cells\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.mergeOrSplit()\n */\n mergeOrSplit: () => ReturnType\n\n /**\n * Set a cell attribute\n * @param name The attribute name\n * @param value The attribute value\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.setCellAttribute('align', 'right')\n */\n setCellAttribute: (name: string, value: any) => ReturnType\n\n /**\n * Moves the selection to the next cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.goToNextCell()\n */\n goToNextCell: () => ReturnType\n\n /**\n * Moves the selection to the previous cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.goToPreviousCell()\n */\n goToPreviousCell: () => ReturnType\n\n /**\n * Try to fix the table structure if necessary\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.fixTables()\n */\n fixTables: () => ReturnType\n\n /**\n * Set a cell selection inside the current table\n * @param position The cell position\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.setCellSelection({ anchorCell: 1, headCell: 2 })\n */\n setCellSelection: (position: { anchorCell: number; headCell?: number }) => ReturnType\n }\n }\n}\n\n/**\n * This extension allows you to create tables.\n * @see https://www.tiptap.dev/api/nodes/table\n */\nexport const Table = Node.create<TableOptions>({\n name: 'table',\n\n // @ts-ignore\n addOptions() {\n return {\n HTMLAttributes: {},\n resizable: false,\n renderWrapper: false,\n handleWidth: 5,\n cellMinWidth: 25,\n // TODO: fix\n View: TableView,\n lastColumnResizable: true,\n allowTableNodeSelection: false,\n }\n },\n\n content: 'tableRow+',\n\n tableRole: 'table',\n\n isolating: true,\n\n group: 'block',\n\n parseHTML() {\n return [{ tag: 'table' }]\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const { colgroup, tableWidth, tableMinWidth } = createColGroup(node, this.options.cellMinWidth)\n\n const userStyles = HTMLAttributes.style as string | undefined\n\n function getTableStyle() {\n if (userStyles) {\n return userStyles\n }\n\n return tableWidth ? `width: ${tableWidth}` : `min-width: ${tableMinWidth}`\n }\n\n const table: DOMOutputSpec = [\n 'table',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n style: getTableStyle(),\n }),\n colgroup,\n ['tbody', 0],\n ]\n\n return this.options.renderWrapper ? ['div', { class: 'tableWrapper' }, table] : table\n },\n\n parseMarkdown: (token: MarkdownTableToken, h) => {\n const rows = []\n const alignments = Array.isArray(token.align) ? token.align : []\n\n if (token.header) {\n const headerCells: JSONContent[] = []\n\n token.header.forEach((cell, index) => {\n const align = normalizeTableCellAlign(alignments[index] ?? cell.align)\n const attrs = align ? { align } : {}\n\n headerCells.push(\n h.createNode('tableHeader', attrs, [\n { type: 'paragraph', content: h.parseInline(cell.tokens) },\n ]),\n )\n })\n\n rows.push(h.createNode('tableRow', {}, headerCells))\n }\n\n if (token.rows) {\n token.rows.forEach(row => {\n const bodyCells: JSONContent[] = []\n row.forEach((cell, index) => {\n const align = normalizeTableCellAlign(alignments[index] ?? cell.align)\n const attrs = align ? { align } : {}\n\n bodyCells.push(\n h.createNode('tableCell', attrs, [\n { type: 'paragraph', content: h.parseInline(cell.tokens) },\n ]),\n )\n })\n rows.push(h.createNode('tableRow', {}, bodyCells))\n })\n }\n\n return h.createNode('table', undefined, rows)\n },\n\n renderMarkdown: (node, h) => {\n return renderTableToMarkdown(node, h)\n },\n\n markdownTokenizer: {\n name: 'table',\n level: 'block' as const,\n start: (src: string) => {\n const lines = src.split('\\n')\n if (lines.length < 2) return -1\n const sep = lines[1]\n if (!/^[ \\t|:]*-[ \\t|:-]*$/.test(sep) || !sep.includes('|')) return -1\n return lines[0].includes('|') ? 0 : -1\n },\n tokenize(src, _tokens, helper) {\n // Marked terminates a table block at a blank line. Slicing to the first\n // \\n\\n keeps helper.blockTokens isolated to the candidate table so it\n // cannot consume content that follows. When no blank line exists the\n // full remaining source is used and marked's own table regex determines\n // the boundary (it excludes headings, fences, blockquotes, etc.).\n const blankLineIndex = src.indexOf('\\n\\n')\n const candidate = blankLineIndex >= 0 ? src.slice(0, blankLineIndex) : src\n\n // A GFM table needs at least a header and a separator row (two lines).\n const candidateLines = candidate.split('\\n')\n if (candidateLines.length < 2) return undefined\n\n // Guard: the second line must match a GFM delimiter row (dashes, colons,\n // pipes, spaces) AND must contain at least one '|'. A bare '---' matches\n // the dash pattern but is a setext heading marker, not a table separator.\n // Calling helper.blockTokens on non-table content contaminates the outer\n // lexer's inline queue with preprocessed (backslash-modified) content.\n const sep = candidateLines[1]\n if (!/^[ \\t|:]*-[ \\t|:-]*$/.test(sep) || !sep.includes('|')) return undefined\n\n const preprocessed = preprocessTablePipes(candidate)\n\n // Nothing to fix — let marked's built-in handle it.\n if (preprocessed === candidate) return undefined\n\n // Re-lex only the preprocessed candidate. The recursive call to our\n // tokenizer finds no unescaped pipes left inside code spans and returns\n // undefined, so marked's built-in table tokenizer produces\n // correctly-split cells.\n const block = helper.blockTokens(preprocessed)\n const tableToken = block[0]\n if (tableToken?.type !== 'table' || !tableToken.raw) return undefined\n\n // preprocessTablePipes only inserts backslashes (never adds or removes\n // newlines), so line N in preprocessed maps 1-to-1 to line N in src.\n // Use the token's line count to reconstruct raw from the original src so\n // marked advances its cursor by the correct amount.\n const lineCount = tableToken.raw.split('\\n').length\n const raw = src.split('\\n').slice(0, lineCount).join('\\n')\n\n return { ...tableToken, raw }\n },\n },\n\n addCommands() {\n return {\n insertTable:\n ({ rows = 3, cols = 3, withHeaderRow = true } = {}) =>\n ({ tr, dispatch, editor }) => {\n const node = createTable(editor.schema, rows, cols, withHeaderRow)\n\n if (dispatch) {\n const offset = tr.selection.from + 1\n\n tr.replaceSelectionWith(node)\n .scrollIntoView()\n .setSelection(TextSelection.near(tr.doc.resolve(offset)))\n }\n\n return true\n },\n addColumnBefore:\n () =>\n ({ state, dispatch }) => {\n return addColumnBefore(state, dispatch)\n },\n addColumnAfter:\n () =>\n ({ state, dispatch }) => {\n return addColumnAfter(state, dispatch)\n },\n deleteColumn:\n () =>\n ({ state, dispatch }) => {\n return deleteColumn(state, dispatch)\n },\n addRowBefore:\n () =>\n ({ state, dispatch }) => {\n return addRowBefore(state, dispatch)\n },\n addRowAfter:\n () =>\n ({ state, dispatch }) => {\n return addRowAfter(state, dispatch)\n },\n deleteRow:\n () =>\n ({ state, dispatch }) => {\n return deleteRow(state, dispatch)\n },\n deleteTable:\n () =>\n ({ state, dispatch }) => {\n return deleteTable(state, dispatch)\n },\n mergeCells:\n () =>\n ({ state, dispatch }) => {\n return mergeCells(state, dispatch)\n },\n splitCell:\n () =>\n ({ state, dispatch }) => {\n return splitCell(state, dispatch)\n },\n toggleHeaderColumn:\n () =>\n ({ state, dispatch }) => {\n return toggleHeader('column')(state, dispatch)\n },\n toggleHeaderRow:\n () =>\n ({ state, dispatch }) => {\n return toggleHeader('row')(state, dispatch)\n },\n toggleHeaderCell:\n () =>\n ({ state, dispatch }) => {\n return toggleHeaderCell(state, dispatch)\n },\n mergeOrSplit:\n () =>\n ({ state, dispatch }) => {\n if (mergeCells(state, dispatch)) {\n return true\n }\n\n return splitCell(state, dispatch)\n },\n setCellAttribute:\n (name, value) =>\n ({ state, dispatch }) => {\n return setCellAttr(name, value)(state, dispatch)\n },\n goToNextCell:\n () =>\n ({ state, dispatch }) => {\n return goToNextCell(1)(state, dispatch)\n },\n goToPreviousCell:\n () =>\n ({ state, dispatch }) => {\n return goToNextCell(-1)(state, dispatch)\n },\n fixTables:\n () =>\n ({ state, dispatch }) => {\n if (dispatch) {\n fixTables(state)\n }\n\n return true\n },\n setCellSelection:\n position =>\n ({ tr, dispatch }) => {\n if (dispatch) {\n const selection = CellSelection.create(tr.doc, position.anchorCell, position.headCell)\n\n // @ts-ignore\n tr.setSelection(selection)\n }\n\n return true\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n Tab: () => {\n if (this.editor.commands.goToNextCell()) {\n return true\n }\n\n if (!this.editor.can().addRowAfter()) {\n return false\n }\n\n return this.editor.chain().addRowAfter().goToNextCell().run()\n },\n 'Shift-Tab': () => this.editor.commands.goToPreviousCell(),\n Backspace: deleteTableWhenAllCellsSelected,\n 'Mod-Backspace': deleteTableWhenAllCellsSelected,\n Delete: deleteTableWhenAllCellsSelected,\n 'Mod-Delete': deleteTableWhenAllCellsSelected,\n }\n },\n\n addProseMirrorPlugins() {\n const isResizable = this.options.resizable && this.editor.isEditable\n\n return [\n ...(isResizable\n ? [\n columnResizing({\n handleWidth: this.options.handleWidth,\n cellMinWidth: this.options.cellMinWidth,\n defaultCellMinWidth: this.options.cellMinWidth,\n View: this.options.View,\n lastColumnResizable: this.options.lastColumnResizable,\n }),\n ]\n : []),\n tableEditing({\n allowTableNodeSelection: this.options.allowTableNodeSelection,\n }),\n ]\n },\n\n addNodeView() {\n // When resizable, the columnResizing plugin registers its own NodeView.\n // We only register one here for the non-resizable case so that\n // <colgroup> stays in sync with column changes (issue #7015).\n const isResizable = this.options.resizable && this.editor.isEditable\n const View = this.options.View\n\n if (isResizable || !View) {\n return null\n }\n\n return ({ node, view, HTMLAttributes }) => {\n const mergedAttributes = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)\n\n return new View(node, this.options.cellMinWidth, view, mergedAttributes) as NodeView\n }\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n }\n\n return {\n tableRole: callOrReturn(getExtensionField(extension, 'tableRole', context)),\n }\n },\n})\n","import type { Attribute } from '@tiptap/core'\n\n/**\n * Supported table cell alignment values\n */\nexport enum TableCellAlign {\n Left = 'left',\n Right = 'right',\n Center = 'center',\n}\n\n/**\n * Normalize unknown input into a supported table alignment\n *\n * @param value - A potential alignment value\n * @returns A valid TableCellAlign value or null\n */\nexport function normalizeTableCellAlign(value: unknown): TableCellAlign | null {\n if (\n value === TableCellAlign.Left ||\n value === TableCellAlign.Right ||\n value === TableCellAlign.Center\n ) {\n return value\n }\n\n return null\n}\n\n/**\n * Parse table cell alignment from an HTML element\n *\n * Prefers inline style (${\"`\"}text-align${\"`\"}) and falls back to the legacy\n * ${\"`\"}align${\"`\"} attribute.\n *\n * @param element - The table cell/header DOM element\n * @returns A valid TableCellAlign value or null\n */\nexport function parseAlign(element: HTMLElement): TableCellAlign | null {\n const styleAlign = (element.style.textAlign || '').trim().toLowerCase()\n const attrAlign = (element.getAttribute('align') || '').trim().toLowerCase()\n const align = styleAlign || attrAlign\n\n return normalizeTableCellAlign(align)\n}\n\n/**\n * Normalize alignment from a generic attrs object that may include an align field\n *\n * @param attributes - A node attrs-like object with an optional align field\n * @returns A valid TableCellAlign value or null.\n */\nexport function normalizeTableCellAlignFromAttributes(\n attributes: { align?: TableCellAlign } | null | undefined,\n): TableCellAlign | null {\n return normalizeTableCellAlign(attributes?.align)\n}\n\n/**\n * Create a reusable Tiptap attribute config for table alignment\n *\n * @returns A Tiptap Attribute definition that parses and renders table alignment\n */\nexport function createAlignAttribute(): Attribute {\n return {\n default: null,\n parseHTML: (element: HTMLElement) => parseAlign(element),\n renderHTML: (attributes: { align?: TableCellAlign | null }) => {\n if (!attributes.align) {\n return {}\n }\n\n return {\n style: `text-align: ${attributes.align}`,\n }\n },\n }\n}\n","export function getColStyleDeclaration(\n minWidth: number,\n width: number | undefined,\n): [string, string] {\n if (width) {\n // apply the stored width unless it is below the configured minimum cell width\n return ['width', `${Math.max(width, minWidth)}px`]\n }\n\n // set the minimum with on the column if it has no stored width\n return ['min-width', `${minWidth}px`]\n}\n","import type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { EditorView, NodeView, ViewMutationRecord } from '@tiptap/pm/view'\n\nimport { getColStyleDeclaration } from './utilities/colStyle.js'\n\nexport function updateColumns(\n node: ProseMirrorNode,\n colgroup: HTMLTableColElement, // <colgroup> has the same prototype as <col>\n table: HTMLTableElement,\n cellMinWidth: number,\n overrideCol?: number,\n overrideValue?: number,\n) {\n let totalWidth = 0\n let fixedWidth = true\n let nextDOM = colgroup.firstChild\n const row = node.firstChild\n\n if (row !== null) {\n for (let i = 0, col = 0; i < row.childCount; i += 1) {\n const { colspan, colwidth } = row.child(i).attrs\n\n for (let j = 0; j < colspan; j += 1, col += 1) {\n const hasWidth =\n overrideCol === col ? overrideValue : ((colwidth && colwidth[j]) as number | undefined)\n const cssWidth = hasWidth ? `${hasWidth}px` : ''\n\n totalWidth += hasWidth || cellMinWidth\n\n if (!hasWidth) {\n fixedWidth = false\n }\n\n if (!nextDOM) {\n const colElement = document.createElement('col')\n\n const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n colElement.style.setProperty(propertyKey, propertyValue)\n\n colgroup.appendChild(colElement)\n } else {\n if ((nextDOM as HTMLTableColElement).style.width !== cssWidth) {\n const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n ;(nextDOM as HTMLTableColElement).style.setProperty(propertyKey, propertyValue)\n }\n\n nextDOM = nextDOM.nextSibling\n }\n }\n }\n }\n\n while (nextDOM) {\n const after = nextDOM.nextSibling\n\n nextDOM.parentNode?.removeChild(nextDOM)\n nextDOM = after\n }\n\n // Check if user has set a width style on the table node\n const hasUserWidth =\n node.attrs.style &&\n typeof node.attrs.style === 'string' &&\n /\\bwidth\\s*:/i.test(node.attrs.style)\n\n if (fixedWidth && !hasUserWidth) {\n table.style.width = `${totalWidth}px`\n table.style.minWidth = ''\n } else {\n table.style.width = ''\n table.style.minWidth = `${totalWidth}px`\n }\n}\n\nexport class TableView implements NodeView {\n node: ProseMirrorNode\n\n cellMinWidth: number\n\n dom: HTMLDivElement\n\n table: HTMLTableElement\n\n colgroup: HTMLTableColElement\n\n contentDOM: HTMLTableSectionElement\n\n constructor(\n node: ProseMirrorNode,\n cellMinWidth: number,\n _view?: EditorView,\n HTMLAttributes: Record<string, any> = {},\n ) {\n this.node = node\n this.cellMinWidth = cellMinWidth\n this.dom = document.createElement('div')\n this.dom.className = 'tableWrapper'\n this.table = this.dom.appendChild(document.createElement('table'))\n\n // Apply extension-configured HTMLAttributes to the table element\n // (e.g. class, data-* set via Table.configure({ HTMLAttributes }))\n for (const [key, value] of Object.entries(HTMLAttributes)) {\n if (value !== undefined && value !== null) {\n if (key === 'style') {\n this.table.style.cssText = String(value)\n } else {\n this.table.setAttribute(key, String(value))\n }\n }\n }\n\n // Apply user styles from the ProseMirror document node.\n // This may come from HTML parsing (e.g. <table style=\"...\">) and should\n // override any style set via extension-configured HTMLAttributes above.\n if (node.attrs.style) {\n this.table.style.cssText = node.attrs.style\n }\n\n this.colgroup = this.table.appendChild(document.createElement('colgroup'))\n updateColumns(node, this.colgroup, this.table, cellMinWidth)\n this.contentDOM = this.table.appendChild(document.createElement('tbody'))\n }\n\n update(node: ProseMirrorNode) {\n if (node.type !== this.node.type) {\n return false\n }\n\n this.node = node\n updateColumns(node, this.colgroup, this.table, this.cellMinWidth)\n\n return true\n }\n\n ignoreMutation(mutation: ViewMutationRecord) {\n const target = mutation.target as Node\n const isInsideWrapper = this.dom.contains(target)\n const isInsideContent = this.contentDOM.contains(target)\n\n if (isInsideWrapper && !isInsideContent) {\n if (\n mutation.type === 'attributes' ||\n mutation.type === 'childList' ||\n mutation.type === 'characterData'\n ) {\n return true\n }\n }\n\n return false\n }\n}\n","import type { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'\n\nimport { getColStyleDeclaration } from './colStyle.js'\n\nexport type ColGroup =\n | {\n colgroup: DOMOutputSpec\n tableWidth: string\n tableMinWidth: string\n }\n | Record<string, never>\n\n/**\n * Creates a colgroup element for a table node in ProseMirror.\n *\n * @param node - The ProseMirror node representing the table.\n * @param cellMinWidth - The minimum width of a cell in the table.\n * @param overrideCol - (Optional) The index of the column to override the width of.\n * @param overrideValue - (Optional) The width value to use for the overridden column.\n * @returns An object containing the colgroup element, the total width of the table, and the minimum width of the table.\n */\nexport function createColGroup(node: ProseMirrorNode, cellMinWidth: number): ColGroup\nexport function createColGroup(\n node: ProseMirrorNode,\n cellMinWidth: number,\n overrideCol: number,\n overrideValue: number,\n): ColGroup\nexport function createColGroup(\n node: ProseMirrorNode,\n cellMinWidth: number,\n overrideCol?: number,\n overrideValue?: number,\n): ColGroup {\n let totalWidth = 0\n let fixedWidth = true\n const cols: DOMOutputSpec[] = []\n const row = node.firstChild\n\n if (!row) {\n return {}\n }\n\n for (let i = 0, col = 0; i < row.childCount; i += 1) {\n const { colspan, colwidth } = row.child(i).attrs\n\n for (let j = 0; j < colspan; j += 1, col += 1) {\n const hasWidth =\n overrideCol === col ? overrideValue : colwidth && (colwidth[j] as number | undefined)\n\n totalWidth += hasWidth || cellMinWidth\n\n if (!hasWidth) {\n fixedWidth = false\n }\n\n const [property, value] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n cols.push(['col', { style: `${property}: ${value}` }])\n }\n }\n\n const tableWidth = fixedWidth ? `${totalWidth}px` : ''\n const tableMinWidth = fixedWidth ? '' : `${totalWidth}px`\n\n const colgroup: DOMOutputSpec = ['colgroup', {}, ...cols]\n\n return { colgroup, tableWidth, tableMinWidth }\n}\n","import type { Fragment, Node as ProsemirrorNode, NodeType } from '@tiptap/pm/model'\n\nexport function createCell(\n cellType: NodeType,\n cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,\n): ProsemirrorNode | null | undefined {\n if (cellContent) {\n return cellType.createChecked(null, cellContent)\n }\n\n return cellType.createAndFill()\n}\n","import type { NodeType, Schema } from '@tiptap/pm/model'\n\nexport function getTableNodeTypes(schema: Schema): { [key: string]: NodeType } {\n if (schema.cached.tableNodeTypes) {\n return schema.cached.tableNodeTypes\n }\n\n const roles: { [key: string]: NodeType } = {}\n\n Object.keys(schema.nodes).forEach(type => {\n const nodeType = schema.nodes[type]\n\n if (nodeType.spec.tableRole) {\n roles[nodeType.spec.tableRole] = nodeType\n }\n })\n\n schema.cached.tableNodeTypes = roles\n\n return roles\n}\n","import type { Fragment, Node as ProsemirrorNode, Schema } from '@tiptap/pm/model'\n\nimport { createCell } from './createCell.js'\nimport { getTableNodeTypes } from './getTableNodeTypes.js'\n\nexport function createTable(\n schema: Schema,\n rowsCount: number,\n colsCount: number,\n withHeaderRow: boolean,\n cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,\n): ProsemirrorNode {\n const types = getTableNodeTypes(schema)\n const headerCells: ProsemirrorNode[] = []\n const cells: ProsemirrorNode[] = []\n\n for (let index = 0; index < colsCount; index += 1) {\n const cell = createCell(types.cell, cellContent)\n\n if (cell) {\n cells.push(cell)\n }\n\n if (withHeaderRow) {\n const headerCell = createCell(types.header_cell, cellContent)\n\n if (headerCell) {\n headerCells.push(headerCell)\n }\n }\n }\n\n const rows: ProsemirrorNode[] = []\n\n for (let index = 0; index < rowsCount; index += 1) {\n rows.push(types.row.createChecked(null, withHeaderRow && index === 0 ? headerCells : cells))\n }\n\n return types.table.createChecked(null, rows)\n}\n","import type { KeyboardShortcutCommand } from '@tiptap/core'\nimport { findParentNodeClosestToPos } from '@tiptap/core'\n\nimport { isCellSelection } from './isCellSelection.js'\n\nexport const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => {\n const { selection } = editor.state\n\n if (!isCellSelection(selection)) {\n return false\n }\n\n let cellCount = 0\n const table = findParentNodeClosestToPos(selection.ranges[0].$from, node => {\n return node.type.name === 'table'\n })\n\n table?.node.descendants(node => {\n if (node.type.name === 'table') {\n return false\n }\n\n if (['tableCell', 'tableHeader'].includes(node.type.name)) {\n cellCount += 1\n }\n })\n\n const allCellsSelected = cellCount === selection.ranges.length\n\n if (!allCellsSelected) {\n return false\n }\n\n editor.commands.deleteTable()\n\n return true\n}\n","import { CellSelection } from '@tiptap/pm/tables'\n\nexport function isCellSelection(value: unknown): value is CellSelection {\n return value instanceof CellSelection\n}\n","import type { JSONContent, MarkdownRendererHelpers } from '@tiptap/core'\n\nimport {\n type TableCellAlign as TableCellAlignType,\n normalizeTableCellAlignFromAttributes,\n TableCellAlign,\n} from '../../utils/parseAlign.js'\n\nexport const DEFAULT_CELL_LINE_SEPARATOR = '\\u001F'\n\n/**\n * Walk a single table-row line and escape any `|` characters that appear\n * inside backtick code spans so marked's cell splitter ignores them.\n * Backslash escape sequences outside code spans are passed through untouched.\n * If a backtick run has no matching closer on the same line it is emitted\n * as-is — no over-escaping for malformed input.\n */\nexport function escapeTableCellPipes(line: string): string {\n let result = ''\n let i = 0\n while (i < line.length) {\n if (line[i] === '\\\\' && i + 1 < line.length) {\n result += line[i] + line[i + 1]\n i += 2\n continue\n }\n if (line[i] !== '`') {\n result += line[i++]\n continue\n }\n let runLen = 0\n while (i + runLen < line.length && line[i + runLen] === '`') runLen += 1\n let j = i + runLen\n let found = false\n while (j < line.length) {\n if (line[j] !== '`') {\n j += 1\n continue\n }\n let closeLen = 0\n while (j + closeLen < line.length && line[j + closeLen] === '`') closeLen += 1\n if (closeLen === runLen) {\n const spanContent = line.slice(i + runLen, j)\n result +=\n line.slice(i, i + runLen) +\n spanContent.replace(/(?<!\\\\)\\|/g, '\\\\|') +\n line.slice(j, j + runLen)\n i = j + runLen\n found = true\n break\n }\n j += closeLen\n }\n if (!found) {\n result += line.slice(i, i + runLen)\n i += runLen\n }\n }\n return result\n}\n\n/**\n * Escape pipe characters inside backtick code spans on table-row lines.\n * marked's `splitCells` only recognises backslash-escaped pipes (`\\|`) and\n * splits on every other `|`, so \\`a || b\\` in a table cell would be treated\n * as multiple column delimiters. Escaping them here lets `splitCells` skip\n * them; it already converts `\\|` → `|` after splitting, so the cell content\n * is restored correctly.\n */\nexport function preprocessTablePipes(src: string): string {\n return src\n .split('\\n')\n .map(line => {\n if (!line.includes('|') || !line.includes('`')) return line\n return escapeTableCellPipes(line)\n })\n .join('\\n')\n}\n\nfunction collapseWhitespace(s: string) {\n return (s || '').replace(/\\s+/g, ' ').trim()\n}\n\nexport function renderTableToMarkdown(\n node: JSONContent,\n h: MarkdownRendererHelpers,\n options: { cellLineSeparator?: string } = {},\n) {\n const cellSep = options.cellLineSeparator ?? DEFAULT_CELL_LINE_SEPARATOR\n\n if (!node || !node.content || node.content.length === 0) {\n return ''\n }\n\n // Build rows: each cell is { text, isHeader, align }\n const rows: { text: string; isHeader: boolean; align: TableCellAlignType | null }[][] = []\n\n node.content.forEach(rowNode => {\n const cells: { text: string; isHeader: boolean; align: TableCellAlignType | null }[] = []\n\n if (rowNode.content) {\n rowNode.content.forEach(cellNode => {\n let raw = ''\n\n if (cellNode.content && Array.isArray(cellNode.content) && cellNode.content.length > 1) {\n // Render each direct child separately and join with separator so we can split again later\n const parts = cellNode.content.map(child =>\n h.renderChildren(child as unknown as JSONContent),\n )\n raw = parts.join(cellSep)\n } else {\n raw = cellNode.content\n ? h.renderChildren(cellNode.content as unknown as JSONContent[])\n : ''\n }\n\n const text = collapseWhitespace(raw)\n const isHeader = cellNode.type === 'tableHeader'\n const align = normalizeTableCellAlignFromAttributes(cellNode.attrs)\n\n cells.push({ text, isHeader, align })\n })\n }\n\n rows.push(cells)\n })\n\n const columnCount = rows.reduce((max, r) => Math.max(max, r.length), 0)\n\n if (columnCount === 0) {\n return ''\n }\n\n // Compute max width for each column\n const colWidths = Array.from<number>({ length: columnCount }).fill(0)\n\n rows.forEach(r => {\n for (let i = 0; i < columnCount; i += 1) {\n const cell = r[i]?.text || ''\n const len = cell.length\n if (len > colWidths[i]) {\n colWidths[i] = len\n }\n\n if (colWidths[i] < 3) {\n colWidths[i] = 3\n }\n }\n })\n\n const pad = (s: string, width: number) => s + ' '.repeat(Math.max(0, width - s.length))\n\n const headerRow = rows[0]\n const hasHeader = headerRow.some(c => c.isHeader)\n const colAlignments: Array<TableCellAlignType | null> = Array.from<TableCellAlignType | null>({\n length: columnCount,\n }).fill(null)\n\n rows.forEach(r => {\n for (let i = 0; i < columnCount; i += 1) {\n if (!colAlignments[i] && r[i]?.align) {\n colAlignments[i] = r[i].align\n }\n }\n })\n\n let out = '\\n'\n\n // Render header: if the document has a header row (tableHeader cells) use it,\n // otherwise emit an empty header row so most Markdown parsers will recognize\n // the table (this makes roundtripping to Markdown -> JSON more reliable).\n const headerTexts = Array.from<number>({ length: columnCount }).map((_, i) =>\n hasHeader ? (headerRow[i] && headerRow[i].text) || '' : '',\n )\n\n out += `| ${headerTexts.map((t, i) => pad(t, colWidths[i])).join(' | ')} |\\n`\n\n // Separator (use at least 3 dashes per column and include alignment markers)\n out += `| ${colWidths\n .map((w, index) => {\n const dashCount = Math.max(3, w)\n const alignment = colAlignments[index]\n\n if (alignment === TableCellAlign.Left) {\n return `:${'-'.repeat(dashCount)}`\n }\n\n if (alignment === TableCellAlign.Right) {\n return `${'-'.repeat(dashCount)}:`\n }\n\n if (alignment === TableCellAlign.Center) {\n return `:${'-'.repeat(dashCount)}:`\n }\n\n return '-'.repeat(dashCount)\n })\n .join(' | ')} |\\n`\n\n // Body rows: if we had a header, skip the first row; otherwise render all rows\n const body = hasHeader ? rows.slice(1) : rows\n body.forEach(r => {\n out += `| ${Array.from<number>({ length: columnCount })\n .fill(0)\n .map((_, i) => pad((r[i] && r[i].text) || '', colWidths[i]))\n .join(' | ')} |\\n`\n })\n\n return out\n}\n\nexport default renderTableToMarkdown\n"],"mappings":"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","names":["CellSelection","_a","CellSelection"]}
1
+ {"version":3,"sources":["../../src/table/table.ts","../../src/utils/parseAlign.ts","../../src/table/utilities/colStyle.ts","../../src/table/TableView.ts","../../src/table/utilities/createColGroup.ts","../../src/table/utilities/createCell.ts","../../src/table/utilities/getTableNodeTypes.ts","../../src/table/utilities/createTable.ts","../../src/table/utilities/deleteTableWhenAllCellsSelected.ts","../../src/table/utilities/isCellSelection.ts","../../src/table/utilities/markdown.ts"],"sourcesContent":["import '../types.js'\n\nimport {\n type JSONContent,\n type MarkdownToken,\n callOrReturn,\n getExtensionField,\n mergeAttributes,\n Node,\n} from '@tiptap/core'\nimport type { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { TextSelection } from '@tiptap/pm/state'\nimport {\n addColumnAfter,\n addColumnBefore,\n addRowAfter,\n addRowBefore,\n CellSelection,\n columnResizing,\n deleteColumn,\n deleteRow,\n deleteTable,\n fixTables,\n goToNextCell,\n mergeCells,\n setCellAttr,\n splitCell,\n tableEditing,\n toggleHeader,\n toggleHeaderCell,\n} from '@tiptap/pm/tables'\nimport type { EditorView, NodeView } from '@tiptap/pm/view'\n\nimport { type TableCellAlign, normalizeTableCellAlign } from '../utils/parseAlign.js'\nimport { TableView } from './TableView.js'\nimport { createColGroup } from './utilities/createColGroup.js'\nimport { createTable } from './utilities/createTable.js'\nimport { deleteTableWhenAllCellsSelected } from './utilities/deleteTableWhenAllCellsSelected.js'\nimport renderTableToMarkdown, { preprocessTablePipes } from './utilities/markdown.js'\n\ntype MarkdownTableToken = {\n align?: Array<TableCellAlign | null>\n header?: { tokens: MarkdownToken[]; align?: TableCellAlign | null }[]\n rows?: { tokens: MarkdownToken[]; align?: TableCellAlign | null }[][]\n} & MarkdownToken\n\nexport interface TableOptions {\n /**\n * HTML attributes for the table element.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>\n\n /**\n * Enables the resizing of tables.\n * @default false\n * @example true\n */\n resizable: boolean\n\n /**\n * Controls whether the table should be wrapped in a div with class \"tableWrapper\" when rendered.\n * In editable mode with resizable tables, this wrapper is always present via TableView.\n * @default false\n * @example true\n */\n renderWrapper: boolean\n\n /**\n * The width of the resize handle.\n * @default 5\n * @example 10\n */\n handleWidth: number\n\n /**\n * The minimum width of a cell.\n * @default 25\n * @example 50\n */\n cellMinWidth: number\n\n /**\n * The node view to render the table.\n * @default TableView\n */\n View:\n | (new (\n node: ProseMirrorNode,\n cellMinWidth: number,\n view: EditorView,\n HTMLAttributes?: Record<string, any>,\n ) => NodeView)\n | null\n\n /**\n * Enables the resizing of the last column.\n * @default true\n * @example false\n */\n lastColumnResizable: boolean\n\n /**\n * Allow table node selection.\n * @default false\n * @example true\n */\n allowTableNodeSelection: boolean\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n table: {\n /**\n * Insert a table\n * @param options The table attributes\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n */\n insertTable: (options?: {\n rows?: number\n cols?: number\n withHeaderRow?: boolean\n }) => ReturnType\n\n /**\n * Add a column before the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addColumnBefore()\n */\n addColumnBefore: () => ReturnType\n\n /**\n * Add a column after the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addColumnAfter()\n */\n addColumnAfter: () => ReturnType\n\n /**\n * Delete the current column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteColumn()\n */\n deleteColumn: () => ReturnType\n\n /**\n * Add a row before the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addRowBefore()\n */\n addRowBefore: () => ReturnType\n\n /**\n * Add a row after the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.addRowAfter()\n */\n addRowAfter: () => ReturnType\n\n /**\n * Delete the current row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteRow()\n */\n deleteRow: () => ReturnType\n\n /**\n * Delete the current table\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.deleteTable()\n */\n deleteTable: () => ReturnType\n\n /**\n * Merge the currently selected cells\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.mergeCells()\n */\n mergeCells: () => ReturnType\n\n /**\n * Split the currently selected cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.splitCell()\n */\n splitCell: () => ReturnType\n\n /**\n * Toggle the header column\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderColumn()\n */\n toggleHeaderColumn: () => ReturnType\n\n /**\n * Toggle the header row\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderRow()\n */\n toggleHeaderRow: () => ReturnType\n\n /**\n * Toggle the header cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.toggleHeaderCell()\n */\n toggleHeaderCell: () => ReturnType\n\n /**\n * Merge or split the currently selected cells\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.mergeOrSplit()\n */\n mergeOrSplit: () => ReturnType\n\n /**\n * Set a cell attribute\n * @param name The attribute name\n * @param value The attribute value\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.setCellAttribute('align', 'right')\n */\n setCellAttribute: (name: string, value: any) => ReturnType\n\n /**\n * Moves the selection to the next cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.goToNextCell()\n */\n goToNextCell: () => ReturnType\n\n /**\n * Moves the selection to the previous cell\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.goToPreviousCell()\n */\n goToPreviousCell: () => ReturnType\n\n /**\n * Try to fix the table structure if necessary\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.fixTables()\n */\n fixTables: () => ReturnType\n\n /**\n * Set a cell selection inside the current table\n * @param position The cell position\n * @returns True if the command was successful, otherwise false\n * @example editor.commands.setCellSelection({ anchorCell: 1, headCell: 2 })\n */\n setCellSelection: (position: { anchorCell: number; headCell?: number }) => ReturnType\n }\n }\n}\n\n/**\n * This extension allows you to create tables.\n * @see https://www.tiptap.dev/api/nodes/table\n */\nexport const Table = Node.create<TableOptions>({\n name: 'table',\n\n // @ts-ignore\n addOptions() {\n return {\n HTMLAttributes: {},\n resizable: false,\n renderWrapper: false,\n handleWidth: 5,\n cellMinWidth: 25,\n // TODO: fix\n View: TableView,\n lastColumnResizable: true,\n allowTableNodeSelection: false,\n }\n },\n\n content: 'tableRow+',\n\n tableRole: 'table',\n\n isolating: true,\n\n group: 'block',\n\n parseHTML() {\n return [{ tag: 'table' }]\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const { colgroup, tableWidth, tableMinWidth } = createColGroup(node, this.options.cellMinWidth)\n\n const userStyles = HTMLAttributes.style as string | undefined\n\n function getTableStyle() {\n if (userStyles) {\n return userStyles\n }\n\n return tableWidth ? `width: ${tableWidth}` : `min-width: ${tableMinWidth}`\n }\n\n const table: DOMOutputSpec = [\n 'table',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n style: getTableStyle(),\n }),\n colgroup,\n ['tbody', 0],\n ]\n\n return this.options.renderWrapper ? ['div', { class: 'tableWrapper' }, table] : table\n },\n\n parseMarkdown: (token: MarkdownTableToken, h) => {\n const rows = []\n const alignments = Array.isArray(token.align) ? token.align : []\n\n if (token.header) {\n const headerCells: JSONContent[] = []\n\n token.header.forEach((cell, index) => {\n const align = normalizeTableCellAlign(alignments[index] ?? cell.align)\n const attrs = align ? { align } : {}\n\n headerCells.push(\n h.createNode('tableHeader', attrs, [\n { type: 'paragraph', content: h.parseInline(cell.tokens) },\n ]),\n )\n })\n\n rows.push(h.createNode('tableRow', {}, headerCells))\n }\n\n if (token.rows) {\n token.rows.forEach(row => {\n const bodyCells: JSONContent[] = []\n row.forEach((cell, index) => {\n const align = normalizeTableCellAlign(alignments[index] ?? cell.align)\n const attrs = align ? { align } : {}\n\n bodyCells.push(\n h.createNode('tableCell', attrs, [\n { type: 'paragraph', content: h.parseInline(cell.tokens) },\n ]),\n )\n })\n rows.push(h.createNode('tableRow', {}, bodyCells))\n })\n }\n\n return h.createNode('table', undefined, rows)\n },\n\n renderMarkdown: (node, h) => {\n return renderTableToMarkdown(node, h)\n },\n\n markdownTokenizer: {\n name: 'table',\n level: 'block' as const,\n start: (src: string) => {\n const lines = src.split('\\n')\n if (lines.length < 2) return -1\n const sep = lines[1]\n if (!/^[ \\t|:]*-[ \\t|:-]*$/.test(sep) || !sep.includes('|')) return -1\n return lines[0].includes('|') ? 0 : -1\n },\n tokenize(src, _tokens, helper) {\n // Marked terminates a table block at a blank line. Slicing to the first\n // \\n\\n keeps helper.blockTokens isolated to the candidate table so it\n // cannot consume content that follows. When no blank line exists the\n // full remaining source is used and marked's own table regex determines\n // the boundary (it excludes headings, fences, blockquotes, etc.).\n const blankLineIndex = src.indexOf('\\n\\n')\n const candidate = blankLineIndex >= 0 ? src.slice(0, blankLineIndex) : src\n\n // A GFM table needs at least a header and a separator row (two lines).\n const candidateLines = candidate.split('\\n')\n if (candidateLines.length < 2) return undefined\n\n // Guard: the second line must match a GFM delimiter row (dashes, colons,\n // pipes, spaces) AND must contain at least one '|'. A bare '---' matches\n // the dash pattern but is a setext heading marker, not a table separator.\n // Calling helper.blockTokens on non-table content contaminates the outer\n // lexer's inline queue with preprocessed (backslash-modified) content.\n const sep = candidateLines[1]\n if (!/^[ \\t|:]*-[ \\t|:-]*$/.test(sep) || !sep.includes('|')) return undefined\n\n const preprocessed = preprocessTablePipes(candidate)\n\n // Nothing to fix — let marked's built-in handle it.\n if (preprocessed === candidate) return undefined\n\n // Re-lex only the preprocessed candidate. The recursive call to our\n // tokenizer finds no unescaped pipes left inside code spans and returns\n // undefined, so marked's built-in table tokenizer produces\n // correctly-split cells.\n const block = helper.blockTokens(preprocessed)\n const tableToken = block[0]\n if (tableToken?.type !== 'table' || !tableToken.raw) return undefined\n\n // preprocessTablePipes only inserts backslashes (never adds or removes\n // newlines), so line N in preprocessed maps 1-to-1 to line N in src.\n // Use the token's line count to reconstruct raw from the original src so\n // marked advances its cursor by the correct amount.\n const lineCount = tableToken.raw.split('\\n').length\n const raw = src.split('\\n').slice(0, lineCount).join('\\n')\n\n return { ...tableToken, raw }\n },\n },\n\n addCommands() {\n return {\n insertTable:\n ({ rows = 3, cols = 3, withHeaderRow = true } = {}) =>\n ({ tr, dispatch, editor }) => {\n const node = createTable(editor.schema, rows, cols, withHeaderRow)\n\n if (dispatch) {\n const offset = tr.selection.from + 1\n\n tr.replaceSelectionWith(node)\n .scrollIntoView()\n .setSelection(TextSelection.near(tr.doc.resolve(offset)))\n }\n\n return true\n },\n addColumnBefore:\n () =>\n ({ state, dispatch }) => {\n return addColumnBefore(state, dispatch)\n },\n addColumnAfter:\n () =>\n ({ state, dispatch }) => {\n return addColumnAfter(state, dispatch)\n },\n deleteColumn:\n () =>\n ({ state, dispatch }) => {\n return deleteColumn(state, dispatch)\n },\n addRowBefore:\n () =>\n ({ state, dispatch }) => {\n return addRowBefore(state, dispatch)\n },\n addRowAfter:\n () =>\n ({ state, dispatch }) => {\n return addRowAfter(state, dispatch)\n },\n deleteRow:\n () =>\n ({ state, dispatch }) => {\n return deleteRow(state, dispatch)\n },\n deleteTable:\n () =>\n ({ state, dispatch }) => {\n return deleteTable(state, dispatch)\n },\n mergeCells:\n () =>\n ({ state, dispatch }) => {\n return mergeCells(state, dispatch)\n },\n splitCell:\n () =>\n ({ state, dispatch }) => {\n return splitCell(state, dispatch)\n },\n toggleHeaderColumn:\n () =>\n ({ state, dispatch }) => {\n return toggleHeader('column')(state, dispatch)\n },\n toggleHeaderRow:\n () =>\n ({ state, dispatch }) => {\n return toggleHeader('row')(state, dispatch)\n },\n toggleHeaderCell:\n () =>\n ({ state, dispatch }) => {\n return toggleHeaderCell(state, dispatch)\n },\n mergeOrSplit:\n () =>\n ({ state, dispatch }) => {\n if (mergeCells(state, dispatch)) {\n return true\n }\n\n return splitCell(state, dispatch)\n },\n setCellAttribute:\n (name, value) =>\n ({ state, dispatch }) => {\n return setCellAttr(name, value)(state, dispatch)\n },\n goToNextCell:\n () =>\n ({ state, dispatch }) => {\n return goToNextCell(1)(state, dispatch)\n },\n goToPreviousCell:\n () =>\n ({ state, dispatch }) => {\n return goToNextCell(-1)(state, dispatch)\n },\n fixTables:\n () =>\n ({ state, dispatch }) => {\n if (dispatch) {\n fixTables(state)\n }\n\n return true\n },\n setCellSelection:\n position =>\n ({ tr, dispatch }) => {\n if (dispatch) {\n const selection = CellSelection.create(tr.doc, position.anchorCell, position.headCell)\n\n // @ts-ignore\n tr.setSelection(selection)\n }\n\n return true\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n Tab: () => {\n if (this.editor.commands.goToNextCell()) {\n return true\n }\n\n if (!this.editor.can().addRowAfter()) {\n return false\n }\n\n return this.editor.chain().addRowAfter().goToNextCell().run()\n },\n 'Shift-Tab': () => this.editor.commands.goToPreviousCell(),\n Backspace: deleteTableWhenAllCellsSelected,\n 'Mod-Backspace': deleteTableWhenAllCellsSelected,\n Delete: deleteTableWhenAllCellsSelected,\n 'Mod-Delete': deleteTableWhenAllCellsSelected,\n }\n },\n\n addProseMirrorPlugins() {\n const isResizable = this.options.resizable && this.editor.isEditable\n\n return [\n ...(isResizable\n ? [\n columnResizing({\n handleWidth: this.options.handleWidth,\n cellMinWidth: this.options.cellMinWidth,\n defaultCellMinWidth: this.options.cellMinWidth,\n View: this.options.View,\n lastColumnResizable: this.options.lastColumnResizable,\n }),\n ]\n : []),\n tableEditing({\n allowTableNodeSelection: this.options.allowTableNodeSelection,\n }),\n ]\n },\n\n addNodeView() {\n // When resizable, the columnResizing plugin registers its own NodeView.\n // We only register one here for the non-resizable case so that\n // <colgroup> stays in sync with column changes (issue #7015).\n const isResizable = this.options.resizable && this.editor.isEditable\n const View = this.options.View\n\n if (isResizable || !View) {\n return null\n }\n\n return ({ node, view, HTMLAttributes }) => {\n const mergedAttributes = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)\n\n return new View(node, this.options.cellMinWidth, view, mergedAttributes) as NodeView\n }\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n }\n\n return {\n tableRole: callOrReturn(getExtensionField(extension, 'tableRole', context)),\n }\n },\n})\n","import type { Attribute } from '@tiptap/core'\n\n/**\n * Supported table cell alignment values\n */\nexport enum TableCellAlign {\n Left = 'left',\n Right = 'right',\n Center = 'center',\n}\n\n/**\n * Normalize unknown input into a supported table alignment\n *\n * @param value - A potential alignment value\n * @returns A valid TableCellAlign value or null\n */\nexport function normalizeTableCellAlign(value: unknown): TableCellAlign | null {\n if (\n value === TableCellAlign.Left ||\n value === TableCellAlign.Right ||\n value === TableCellAlign.Center\n ) {\n return value\n }\n\n return null\n}\n\n/**\n * Parse table cell alignment from an HTML element\n *\n * Prefers inline style (${\"`\"}text-align${\"`\"}) and falls back to the legacy\n * ${\"`\"}align${\"`\"} attribute.\n *\n * @param element - The table cell/header DOM element\n * @returns A valid TableCellAlign value or null\n */\nexport function parseAlign(element: HTMLElement): TableCellAlign | null {\n const styleAlign = (element.style.textAlign || '').trim().toLowerCase()\n const attrAlign = (element.getAttribute('align') || '').trim().toLowerCase()\n const align = styleAlign || attrAlign\n\n return normalizeTableCellAlign(align)\n}\n\n/**\n * Normalize alignment from a generic attrs object that may include an align field\n *\n * @param attributes - A node attrs-like object with an optional align field\n * @returns A valid TableCellAlign value or null.\n */\nexport function normalizeTableCellAlignFromAttributes(\n attributes: { align?: TableCellAlign } | null | undefined,\n): TableCellAlign | null {\n return normalizeTableCellAlign(attributes?.align)\n}\n\n/**\n * Create a reusable Tiptap attribute config for table alignment\n *\n * @returns A Tiptap Attribute definition that parses and renders table alignment\n */\nexport function createAlignAttribute(): Attribute {\n return {\n default: null,\n parseHTML: (element: HTMLElement) => parseAlign(element),\n renderHTML: (attributes: { align?: TableCellAlign | null }) => {\n if (!attributes.align) {\n return {}\n }\n\n return {\n style: `text-align: ${attributes.align}`,\n }\n },\n }\n}\n","export function getColStyleDeclaration(\n minWidth: number,\n width: number | undefined,\n): [string, string] {\n if (width) {\n // apply the stored width unless it is below the configured minimum cell width\n return ['width', `${Math.max(width, minWidth)}px`]\n }\n\n // set the minimum with on the column if it has no stored width\n return ['min-width', `${minWidth}px`]\n}\n","import type { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport type { EditorView, NodeView, ViewMutationRecord } from '@tiptap/pm/view'\n\nimport { getColStyleDeclaration } from './utilities/colStyle.js'\n\nexport function updateColumns(\n node: ProseMirrorNode,\n colgroup: HTMLTableColElement, // <colgroup> has the same prototype as <col>\n table: HTMLTableElement,\n cellMinWidth: number,\n overrideCol?: number,\n overrideValue?: number,\n) {\n let totalWidth = 0\n let fixedWidth = true\n let nextDOM = colgroup.firstChild\n const row = node.firstChild\n\n if (row !== null) {\n for (let i = 0, col = 0; i < row.childCount; i += 1) {\n const { colspan, colwidth } = row.child(i).attrs\n\n for (let j = 0; j < colspan; j += 1, col += 1) {\n const hasWidth =\n overrideCol === col ? overrideValue : ((colwidth && colwidth[j]) as number | undefined)\n const cssWidth = hasWidth ? `${hasWidth}px` : ''\n\n totalWidth += hasWidth || cellMinWidth\n\n if (!hasWidth) {\n fixedWidth = false\n }\n\n if (!nextDOM) {\n const colElement = document.createElement('col')\n\n const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n colElement.style.setProperty(propertyKey, propertyValue)\n\n colgroup.appendChild(colElement)\n } else {\n if ((nextDOM as HTMLTableColElement).style.width !== cssWidth) {\n const [propertyKey, propertyValue] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n ;(nextDOM as HTMLTableColElement).style.setProperty(propertyKey, propertyValue)\n }\n\n nextDOM = nextDOM.nextSibling\n }\n }\n }\n }\n\n while (nextDOM) {\n const after = nextDOM.nextSibling\n\n nextDOM.parentNode?.removeChild(nextDOM)\n nextDOM = after\n }\n\n // Check if user has set a width style on the table node\n const hasUserWidth =\n node.attrs.style &&\n typeof node.attrs.style === 'string' &&\n /\\bwidth\\s*:/i.test(node.attrs.style)\n\n if (fixedWidth && !hasUserWidth) {\n table.style.width = `${totalWidth}px`\n table.style.minWidth = ''\n } else {\n table.style.width = ''\n table.style.minWidth = `${totalWidth}px`\n }\n}\n\nexport class TableView implements NodeView {\n node: ProseMirrorNode\n\n cellMinWidth: number\n\n dom: HTMLDivElement\n\n table: HTMLTableElement\n\n colgroup: HTMLTableColElement\n\n contentDOM: HTMLTableSectionElement\n\n constructor(\n node: ProseMirrorNode,\n cellMinWidth: number,\n _view?: EditorView,\n HTMLAttributes: Record<string, any> = {},\n ) {\n this.node = node\n this.cellMinWidth = cellMinWidth\n this.dom = document.createElement('div')\n this.dom.className = 'tableWrapper'\n this.table = this.dom.appendChild(document.createElement('table'))\n\n // Apply extension-configured HTMLAttributes to the table element\n // (e.g. class, data-* set via Table.configure({ HTMLAttributes }))\n for (const [key, value] of Object.entries(HTMLAttributes)) {\n if (value !== undefined && value !== null) {\n if (key === 'style') {\n this.table.style.cssText = String(value)\n } else {\n this.table.setAttribute(key, String(value))\n }\n }\n }\n\n // Apply user styles from the ProseMirror document node.\n // This may come from HTML parsing (e.g. <table style=\"...\">) and should\n // override any style set via extension-configured HTMLAttributes above.\n if (node.attrs.style) {\n this.table.style.cssText = node.attrs.style\n }\n\n this.colgroup = this.table.appendChild(document.createElement('colgroup'))\n updateColumns(node, this.colgroup, this.table, cellMinWidth)\n this.contentDOM = this.table.appendChild(document.createElement('tbody'))\n }\n\n update(node: ProseMirrorNode) {\n if (node.type !== this.node.type) {\n return false\n }\n\n this.node = node\n updateColumns(node, this.colgroup, this.table, this.cellMinWidth)\n\n return true\n }\n\n ignoreMutation(mutation: ViewMutationRecord) {\n const target = mutation.target as Node\n const isInsideWrapper = this.dom.contains(target)\n const isInsideContent = this.contentDOM.contains(target)\n\n if (isInsideWrapper && !isInsideContent) {\n if (\n mutation.type === 'attributes' ||\n mutation.type === 'childList' ||\n mutation.type === 'characterData'\n ) {\n return true\n }\n }\n\n return false\n }\n}\n","import type { DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model'\n\nimport { getColStyleDeclaration } from './colStyle.js'\n\nexport type ColGroup =\n | {\n colgroup: DOMOutputSpec\n tableWidth: string\n tableMinWidth: string\n }\n | Record<string, never>\n\n/**\n * Creates a colgroup element for a table node in ProseMirror.\n *\n * @param node - The ProseMirror node representing the table.\n * @param cellMinWidth - The minimum width of a cell in the table.\n * @param overrideCol - (Optional) The index of the column to override the width of.\n * @param overrideValue - (Optional) The width value to use for the overridden column.\n * @returns An object containing the colgroup element, the total width of the table, and the minimum width of the table.\n */\nexport function createColGroup(node: ProseMirrorNode, cellMinWidth: number): ColGroup\nexport function createColGroup(\n node: ProseMirrorNode,\n cellMinWidth: number,\n overrideCol: number,\n overrideValue: number,\n): ColGroup\nexport function createColGroup(\n node: ProseMirrorNode,\n cellMinWidth: number,\n overrideCol?: number,\n overrideValue?: number,\n): ColGroup {\n let totalWidth = 0\n let fixedWidth = true\n const cols: DOMOutputSpec[] = []\n const row = node.firstChild\n\n if (!row) {\n return {}\n }\n\n for (let i = 0, col = 0; i < row.childCount; i += 1) {\n const { colspan, colwidth } = row.child(i).attrs\n\n for (let j = 0; j < colspan; j += 1, col += 1) {\n const hasWidth =\n overrideCol === col ? overrideValue : colwidth && (colwidth[j] as number | undefined)\n\n totalWidth += hasWidth || cellMinWidth\n\n if (!hasWidth) {\n fixedWidth = false\n }\n\n const [property, value] = getColStyleDeclaration(cellMinWidth, hasWidth)\n\n cols.push(['col', { style: `${property}: ${value}` }])\n }\n }\n\n const tableWidth = fixedWidth ? `${totalWidth}px` : ''\n const tableMinWidth = fixedWidth ? '' : `${totalWidth}px`\n\n const colgroup: DOMOutputSpec = ['colgroup', {}, ...cols]\n\n return { colgroup, tableWidth, tableMinWidth }\n}\n","import type { Fragment, Node as ProsemirrorNode, NodeType } from '@tiptap/pm/model'\n\nexport function createCell(\n cellType: NodeType,\n cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,\n): ProsemirrorNode | null | undefined {\n if (cellContent) {\n return cellType.createChecked(null, cellContent)\n }\n\n return cellType.createAndFill()\n}\n","import type { NodeType, Schema } from '@tiptap/pm/model'\n\nexport function getTableNodeTypes(schema: Schema): { [key: string]: NodeType } {\n if (schema.cached.tableNodeTypes) {\n return schema.cached.tableNodeTypes\n }\n\n const roles: { [key: string]: NodeType } = {}\n\n Object.keys(schema.nodes).forEach(type => {\n const nodeType = schema.nodes[type]\n\n if (nodeType.spec.tableRole) {\n roles[nodeType.spec.tableRole] = nodeType\n }\n })\n\n schema.cached.tableNodeTypes = roles\n\n return roles\n}\n","import type { Fragment, Node as ProsemirrorNode, Schema } from '@tiptap/pm/model'\n\nimport { createCell } from './createCell.js'\nimport { getTableNodeTypes } from './getTableNodeTypes.js'\n\nexport function createTable(\n schema: Schema,\n rowsCount: number,\n colsCount: number,\n withHeaderRow: boolean,\n cellContent?: Fragment | ProsemirrorNode | Array<ProsemirrorNode>,\n): ProsemirrorNode {\n const types = getTableNodeTypes(schema)\n const headerCells: ProsemirrorNode[] = []\n const cells: ProsemirrorNode[] = []\n\n for (let index = 0; index < colsCount; index += 1) {\n const cell = createCell(types.cell, cellContent)\n\n if (cell) {\n cells.push(cell)\n }\n\n if (withHeaderRow) {\n const headerCell = createCell(types.header_cell, cellContent)\n\n if (headerCell) {\n headerCells.push(headerCell)\n }\n }\n }\n\n const rows: ProsemirrorNode[] = []\n\n for (let index = 0; index < rowsCount; index += 1) {\n rows.push(types.row.createChecked(null, withHeaderRow && index === 0 ? headerCells : cells))\n }\n\n return types.table.createChecked(null, rows)\n}\n","import type { KeyboardShortcutCommand } from '@tiptap/core'\nimport { findParentNodeClosestToPos } from '@tiptap/core'\n\nimport { isCellSelection } from './isCellSelection.js'\n\nexport const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => {\n const { selection } = editor.state\n\n if (!isCellSelection(selection)) {\n return false\n }\n\n let cellCount = 0\n const table = findParentNodeClosestToPos(selection.ranges[0].$from, node => {\n return node.type.name === 'table'\n })\n\n table?.node.descendants(node => {\n if (node.type.name === 'table') {\n return false\n }\n\n if (['tableCell', 'tableHeader'].includes(node.type.name)) {\n cellCount += 1\n }\n })\n\n const allCellsSelected = cellCount === selection.ranges.length\n\n if (!allCellsSelected) {\n return false\n }\n\n editor.commands.deleteTable()\n\n return true\n}\n","import { CellSelection } from '@tiptap/pm/tables'\n\nexport function isCellSelection(value: unknown): value is CellSelection {\n return value instanceof CellSelection\n}\n","import type { JSONContent, MarkdownRendererHelpers } from '@tiptap/core'\n\nimport {\n type TableCellAlign as TableCellAlignType,\n normalizeTableCellAlignFromAttributes,\n TableCellAlign,\n} from '../../utils/parseAlign.js'\n\nexport const DEFAULT_CELL_LINE_SEPARATOR = '\\u001F'\n\n/**\n * Walk a single table-row line and escape any `|` characters that appear\n * inside backtick code spans so marked's cell splitter ignores them.\n * Backslash escape sequences outside code spans are passed through untouched.\n * If a backtick run has no matching closer on the same line it is emitted\n * as-is — no over-escaping for malformed input.\n */\nexport function escapeTableCellPipes(line: string): string {\n let result = ''\n let i = 0\n while (i < line.length) {\n if (line[i] === '\\\\' && i + 1 < line.length) {\n result += line[i] + line[i + 1]\n i += 2\n continue\n }\n if (line[i] !== '`') {\n result += line[i++]\n continue\n }\n let runLen = 0\n while (i + runLen < line.length && line[i + runLen] === '`') runLen += 1\n let j = i + runLen\n let found = false\n while (j < line.length) {\n if (line[j] !== '`') {\n j += 1\n continue\n }\n let closeLen = 0\n while (j + closeLen < line.length && line[j + closeLen] === '`') closeLen += 1\n if (closeLen === runLen) {\n const spanContent = line.slice(i + runLen, j)\n result +=\n line.slice(i, i + runLen) +\n spanContent.replace(/(?<!\\\\)\\|/g, '\\\\|') +\n line.slice(j, j + runLen)\n i = j + runLen\n found = true\n break\n }\n j += closeLen\n }\n if (!found) {\n result += line.slice(i, i + runLen)\n i += runLen\n }\n }\n return result\n}\n\n/**\n * Escape pipe characters inside backtick code spans on table-row lines.\n * marked's `splitCells` only recognises backslash-escaped pipes (`\\|`) and\n * splits on every other `|`, so \\`a || b\\` in a table cell would be treated\n * as multiple column delimiters. Escaping them here lets `splitCells` skip\n * them; it already converts `\\|` → `|` after splitting, so the cell content\n * is restored correctly.\n */\nexport function preprocessTablePipes(src: string): string {\n return src\n .split('\\n')\n .map(line => {\n if (!line.includes('|') || !line.includes('`')) return line\n return escapeTableCellPipes(line)\n })\n .join('\\n')\n}\n\nfunction collapseWhitespace(s: string) {\n return (s || '').replace(/\\s+/g, ' ').trim()\n}\n\nexport function renderTableToMarkdown(\n node: JSONContent,\n h: MarkdownRendererHelpers,\n options: { cellLineSeparator?: string } = {},\n) {\n const cellSep = options.cellLineSeparator ?? DEFAULT_CELL_LINE_SEPARATOR\n\n if (!node || !node.content || node.content.length === 0) {\n return ''\n }\n\n // Build rows: each cell is { text, isHeader, align }\n const rows: { text: string; isHeader: boolean; align: TableCellAlignType | null }[][] = []\n\n node.content.forEach(rowNode => {\n const cells: { text: string; isHeader: boolean; align: TableCellAlignType | null }[] = []\n\n if (rowNode.content) {\n rowNode.content.forEach(cellNode => {\n let raw = ''\n\n if (cellNode.content && Array.isArray(cellNode.content) && cellNode.content.length > 1) {\n // Render each direct child separately and join with separator so we can split again later\n const parts = cellNode.content.map(child =>\n h.renderChildren(child as unknown as JSONContent),\n )\n raw = parts.join(cellSep)\n } else {\n raw = cellNode.content\n ? h.renderChildren(cellNode.content as unknown as JSONContent[])\n : ''\n }\n\n // Cells have to stay on a single line, so line breaks become <br> tags.\n // The parser already turns <br> back into hard breaks, so this round trips.\n const text = collapseWhitespace(\n raw\n .split(cellSep)\n .join('\\n')\n .replace(/[ \\t]*\\r?\\n[ \\t]*/g, '<br>'),\n )\n const isHeader = cellNode.type === 'tableHeader'\n const align = normalizeTableCellAlignFromAttributes(cellNode.attrs)\n\n cells.push({ text, isHeader, align })\n })\n }\n\n rows.push(cells)\n })\n\n const columnCount = rows.reduce((max, r) => Math.max(max, r.length), 0)\n\n if (columnCount === 0) {\n return ''\n }\n\n // Compute max width for each column\n const colWidths = Array.from<number>({ length: columnCount }).fill(0)\n\n rows.forEach(r => {\n for (let i = 0; i < columnCount; i += 1) {\n const cell = r[i]?.text || ''\n const len = cell.length\n if (len > colWidths[i]) {\n colWidths[i] = len\n }\n\n if (colWidths[i] < 3) {\n colWidths[i] = 3\n }\n }\n })\n\n const pad = (s: string, width: number) => s + ' '.repeat(Math.max(0, width - s.length))\n\n const headerRow = rows[0]\n const hasHeader = headerRow.some(c => c.isHeader)\n const colAlignments: Array<TableCellAlignType | null> = Array.from<TableCellAlignType | null>({\n length: columnCount,\n }).fill(null)\n\n rows.forEach(r => {\n for (let i = 0; i < columnCount; i += 1) {\n if (!colAlignments[i] && r[i]?.align) {\n colAlignments[i] = r[i].align\n }\n }\n })\n\n let out = '\\n'\n\n // Render header: if the document has a header row (tableHeader cells) use it,\n // otherwise emit an empty header row so most Markdown parsers will recognize\n // the table (this makes roundtripping to Markdown -> JSON more reliable).\n const headerTexts = Array.from<number>({ length: columnCount }).map((_, i) =>\n hasHeader ? (headerRow[i] && headerRow[i].text) || '' : '',\n )\n\n out += `| ${headerTexts.map((t, i) => pad(t, colWidths[i])).join(' | ')} |\\n`\n\n // Separator (use at least 3 dashes per column and include alignment markers)\n out += `| ${colWidths\n .map((w, index) => {\n const dashCount = Math.max(3, w)\n const alignment = colAlignments[index]\n\n if (alignment === TableCellAlign.Left) {\n return `:${'-'.repeat(dashCount)}`\n }\n\n if (alignment === TableCellAlign.Right) {\n return `${'-'.repeat(dashCount)}:`\n }\n\n if (alignment === TableCellAlign.Center) {\n return `:${'-'.repeat(dashCount)}:`\n }\n\n return '-'.repeat(dashCount)\n })\n .join(' | ')} |\\n`\n\n // Body rows: if we had a header, skip the first row; otherwise render all rows\n const body = hasHeader ? rows.slice(1) : rows\n body.forEach(r => {\n out += `| ${Array.from<number>({ length: columnCount })\n .fill(0)\n .map((_, i) => pad((r[i] && r[i].text) || '', colWidths[i]))\n .join(' | ')} |\\n`\n })\n\n return out\n}\n\nexport default renderTableToMarkdown\n"],"mappings":"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","names":["CellSelection","_a","CellSelection"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiptap/extension-table",
3
- "version": "3.28.0",
3
+ "version": "3.29.0",
4
4
  "description": "table extension for tiptap",
5
5
  "keywords": [
6
6
  "tiptap",
@@ -79,12 +79,12 @@
79
79
  }
80
80
  },
81
81
  "devDependencies": {
82
- "@tiptap/core": "^3.28.0",
83
- "@tiptap/pm": "^3.28.0"
82
+ "@tiptap/pm": "^3.29.0",
83
+ "@tiptap/core": "^3.29.0"
84
84
  },
85
85
  "peerDependencies": {
86
- "@tiptap/core": "3.28.0",
87
- "@tiptap/pm": "3.28.0"
86
+ "@tiptap/core": "3.29.0",
87
+ "@tiptap/pm": "3.29.0"
88
88
  },
89
89
  "scripts": {
90
90
  "build": "tsup"
@@ -4,6 +4,7 @@ import { mergeAttributes, Node } from '@tiptap/core'
4
4
 
5
5
  import { createAlignAttribute } from '../utils/parseAlign.js'
6
6
  import { parseColwidth } from '../utils/parseColwidth.js'
7
+ import { fillEmptyCellContent, isEmptyCellElement } from '../utils/fillEmptyCellContent.js'
7
8
 
8
9
  export interface TableCellOptions {
9
10
  /**
@@ -50,7 +51,15 @@ export const TableCell = Node.create<TableCellOptions>({
50
51
  isolating: true,
51
52
 
52
53
  parseHTML() {
53
- return [{ tag: 'td' }]
54
+ return [
55
+ {
56
+ // Backfill empty cells; non-empty cells fall through to the rule below.
57
+ tag: 'td',
58
+ getAttrs: node => (isEmptyCellElement(node) ? {} : false),
59
+ getContent: (_node, schema) => fillEmptyCellContent(schema.nodes[this.name]),
60
+ },
61
+ { tag: 'td' },
62
+ ]
54
63
  },
55
64
 
56
65
  renderHTML({ HTMLAttributes }) {
@@ -4,6 +4,7 @@ import { mergeAttributes, Node } from '@tiptap/core'
4
4
 
5
5
  import { createAlignAttribute } from '../utils/parseAlign.js'
6
6
  import { parseColwidth } from '../utils/parseColwidth.js'
7
+ import { fillEmptyCellContent, isEmptyCellElement } from '../utils/fillEmptyCellContent.js'
7
8
 
8
9
  export interface TableHeaderOptions {
9
10
  /**
@@ -50,7 +51,15 @@ export const TableHeader = Node.create<TableHeaderOptions>({
50
51
  isolating: true,
51
52
 
52
53
  parseHTML() {
53
- return [{ tag: 'th' }]
54
+ return [
55
+ {
56
+ // Backfill empty cells; non-empty cells fall through to the rule below.
57
+ tag: 'th',
58
+ getAttrs: node => (isEmptyCellElement(node) ? {} : false),
59
+ getContent: (_node, schema) => fillEmptyCellContent(schema.nodes[this.name]),
60
+ },
61
+ { tag: 'th' },
62
+ ]
54
63
  },
55
64
 
56
65
  renderHTML({ HTMLAttributes }) {
@@ -114,7 +114,14 @@ export function renderTableToMarkdown(
114
114
  : ''
115
115
  }
116
116
 
117
- const text = collapseWhitespace(raw)
117
+ // Cells have to stay on a single line, so line breaks become <br> tags.
118
+ // The parser already turns <br> back into hard breaks, so this round trips.
119
+ const text = collapseWhitespace(
120
+ raw
121
+ .split(cellSep)
122
+ .join('\n')
123
+ .replace(/[ \t]*\r?\n[ \t]*/g, '<br>'),
124
+ )
118
125
  const isHeader = cellNode.type === 'tableHeader'
119
126
  const align = normalizeTableCellAlignFromAttributes(cellNode.attrs)
120
127
 
@@ -0,0 +1,25 @@
1
+ import type { NodeType } from '@tiptap/pm/model'
2
+ import { Fragment } from '@tiptap/pm/model'
3
+
4
+ // ASCII whitespace only, so a non-breaking-space cell is not treated as empty.
5
+ const COLLAPSIBLE_WHITESPACE = /[ \t\r\n\f]+/g
6
+
7
+ /** Whether a cell/header element has no child elements and only collapsible whitespace. */
8
+ export function isEmptyCellElement(element: HTMLElement): boolean {
9
+ if (element.children.length > 0) {
10
+ return false
11
+ }
12
+
13
+ return (element.textContent ?? '').replace(COLLAPSIBLE_WHITESPACE, '') === ''
14
+ }
15
+
16
+ /** Builds a cell/header's minimal `block+` content, derived from the node type. */
17
+ export function fillEmptyCellContent(cellType: NodeType): Fragment {
18
+ const filled = cellType.createAndFill()
19
+
20
+ if (!filled) {
21
+ throw new Error(`[tiptap error]: "${cellType.name}" has no default content to backfill.`)
22
+ }
23
+
24
+ return filled.content
25
+ }