diff --git a/packages/ui/package.json b/packages/ui/package.json index 330cf2344c7..d15d8603def 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -30,6 +30,7 @@ "@tiptap/extension-code-block-lowlight": "^3.20.4", "@tiptap/extension-mention": "^3.20.4", "@tiptap/extension-placeholder": "^3.20.4", + "@tiptap/extension-table": "^3.20.4", "@tiptap/markdown": "^3.20.4", "@tiptap/pm": "^3.20.4", "@tiptap/react": "^3.20.4", diff --git a/packages/ui/src/ui-component/dialog/ExpandRichInputDialog.jsx b/packages/ui/src/ui-component/dialog/ExpandRichInputDialog.jsx index 444bfb3503c..160a135a735 100644 --- a/packages/ui/src/ui-component/dialog/ExpandRichInputDialog.jsx +++ b/packages/ui/src/ui-component/dialog/ExpandRichInputDialog.jsx @@ -18,6 +18,7 @@ import Placeholder from '@tiptap/extension-placeholder' import { mergeAttributes } from '@tiptap/core' import StarterKit from '@tiptap/starter-kit' import { Markdown } from '@tiptap/markdown' +import { Table, TableCell, TableHeader, TableRow } from '@tiptap/extension-table' import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight' import { common, createLowlight } from 'lowlight' import { suggestionOptions } from '@/ui-component/input/suggestionOption' @@ -27,6 +28,41 @@ import { isHtmlContent, escapeXmlTags, unescapeXmlEntities, unescapeXmlTags } fr const lowlight = createLowlight(common) +const MarkdownTable = Table.extend({ + renderMarkdown: (node, h) => { + const rows = + node.content?.map((rowNode) => + (rowNode.content || []).map((cellNode) => { + const text = (cellNode.content || []) + .map((childNode) => h.renderChildren(childNode)) + .join(' ') + .replace(/\s+/g, ' ') + .trim() + return { text, isHeader: cellNode.type === 'tableHeader' } + }) + ) || [] + const columnCount = rows.reduce((max, row) => Math.max(max, row.length), 0) + + if (!columnCount) return '' + + const renderRow = (row = []) => + `| ${new Array(columnCount) + .fill(0) + .map((_, index) => row[index]?.text || '') + .join(' | ')} |` + + const headerRow = rows[0] || [] + const hasHeader = headerRow.some((cell) => cell.isHeader) + const bodyRows = hasHeader ? rows.slice(1) : rows + + return [ + renderRow(hasHeader ? headerRow : []), + `| ${new Array(columnCount).fill('---').join(' | ')} |`, + ...bodyRows.map(renderRow) + ].join('\n') + } +}) + // Store import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions' @@ -115,7 +151,16 @@ const extensions = (availableNodesForVariable, availableState, acceptNodeOutputA StarterKit.configure({ codeBlock: false }), - Markdown, + MarkdownTable, + TableRow, + TableHeader, + TableCell, + Markdown.configure({ + markedOptions: { + gfm: true, + breaks: false + } + }), CustomMention.configure({ HTMLAttributes: { class: 'variable' diff --git a/packages/ui/src/ui-component/input/RichInput.jsx b/packages/ui/src/ui-component/input/RichInput.jsx index 69060ca0a2f..83b3db83994 100644 --- a/packages/ui/src/ui-component/input/RichInput.jsx +++ b/packages/ui/src/ui-component/input/RichInput.jsx @@ -6,6 +6,7 @@ import Placeholder from '@tiptap/extension-placeholder' import { mergeAttributes } from '@tiptap/core' import StarterKit from '@tiptap/starter-kit' import { Markdown } from '@tiptap/markdown' +import { Table, TableCell, TableHeader, TableRow } from '@tiptap/extension-table' import { styled } from '@mui/material/styles' import { Box } from '@mui/material' import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight' @@ -17,6 +18,41 @@ import { isHtmlContent, escapeXmlTags, unescapeXmlEntities, unescapeXmlTags } fr const lowlight = createLowlight(common) +const MarkdownTable = Table.extend({ + renderMarkdown: (node, h) => { + const rows = + node.content?.map((rowNode) => + (rowNode.content || []).map((cellNode) => { + const text = (cellNode.content || []) + .map((childNode) => h.renderChildren(childNode)) + .join(' ') + .replace(/\s+/g, ' ') + .trim() + return { text, isHeader: cellNode.type === 'tableHeader' } + }) + ) || [] + const columnCount = rows.reduce((max, row) => Math.max(max, row.length), 0) + + if (!columnCount) return '' + + const renderRow = (row = []) => + `| ${new Array(columnCount) + .fill(0) + .map((_, index) => row[index]?.text || '') + .join(' | ')} |` + + const headerRow = rows[0] || [] + const hasHeader = headerRow.some((cell) => cell.isHeader) + const bodyRows = hasHeader ? rows.slice(1) : rows + + return [ + renderRow(hasHeader ? headerRow : []), + `| ${new Array(columnCount).fill('---').join(' | ')} |`, + ...bodyRows.map(renderRow) + ].join('\n') + } +}) + // define your extension array const extensions = ( availableNodesForVariable, @@ -27,11 +63,20 @@ const extensions = ( isNodeInsideInteration, useMarkdown ) => [ - Markdown, StarterKit.configure({ codeBlock: false, ...(!useMarkdown && { link: false }) }), + MarkdownTable, + TableRow, + TableHeader, + TableCell, + Markdown.configure({ + markedOptions: { + gfm: true, + breaks: false + } + }), CustomMention.configure({ HTMLAttributes: { class: 'variable' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 812b8856aea..a80340cc34b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1364,6 +1364,9 @@ importers: '@tiptap/extension-placeholder': specifier: ^3.20.4 version: 3.20.4(@tiptap/extensions@3.20.4(@tiptap/core@3.20.4(@tiptap/pm@3.20.4))(@tiptap/pm@3.20.4)) + '@tiptap/extension-table': + specifier: ^3.20.4 + version: 3.20.4(@tiptap/core@3.20.4(@tiptap/pm@3.20.4))(@tiptap/pm@3.20.4) '@tiptap/markdown': specifier: ^3.20.4 version: 3.20.4(@tiptap/core@3.20.4(@tiptap/pm@3.20.4))(@tiptap/pm@3.20.4) @@ -8692,6 +8695,12 @@ packages: peerDependencies: '@tiptap/core': ^3.20.4 + '@tiptap/extension-table@3.20.4': + resolution: {integrity: sha512-vEHXRL9k9G02pp3P+DyUnN4YRaRAHGfTBC6gck0s9TpsCM9NIchL0qI1fb/u46Bu6UaoMMk58DGr7xaJ29g7KQ==} + peerDependencies: + '@tiptap/core': ^3.20.4 + '@tiptap/pm': ^3.20.4 + '@tiptap/extension-text@3.20.4': resolution: {integrity: sha512-jchJcBZixDEO2J66Zx5dchsI2mA6IYsROqF8P1poxL4ienH7RVQRCTsBNnSfIeOtREKKWeOU/tEs5fcpvvGwIQ==} peerDependencies: @@ -31532,6 +31541,11 @@ snapshots: dependencies: '@tiptap/core': 3.20.4(@tiptap/pm@3.20.4) + '@tiptap/extension-table@3.20.4(@tiptap/core@3.20.4(@tiptap/pm@3.20.4))(@tiptap/pm@3.20.4)': + dependencies: + '@tiptap/core': 3.20.4(@tiptap/pm@3.20.4) + '@tiptap/pm': 3.20.4 + '@tiptap/extension-text@3.20.4(@tiptap/core@3.20.4(@tiptap/pm@3.20.4))': dependencies: '@tiptap/core': 3.20.4(@tiptap/pm@3.20.4)