mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-25 00:16:29 +02:00
render tables in markdown
This commit is contained in:
parent
0d71ad33f5
commit
8e0a3e2991
4 changed files with 75 additions and 0 deletions
|
|
@ -28,6 +28,7 @@
|
|||
"@tiptap/extension-image": "^3.16.0",
|
||||
"@tiptap/extension-link": "^3.15.3",
|
||||
"@tiptap/extension-placeholder": "^3.15.3",
|
||||
"@tiptap/extension-table": "^3.22.4",
|
||||
"@tiptap/extension-task-item": "^3.15.3",
|
||||
"@tiptap/extension-task-list": "^3.15.3",
|
||||
"@tiptap/pm": "^3.15.3",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import Image from '@tiptap/extension-image'
|
|||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import TaskList from '@tiptap/extension-task-list'
|
||||
import TaskItem from '@tiptap/extension-task-item'
|
||||
import { TableKit, renderTableToMarkdown } from '@tiptap/extension-table'
|
||||
import type { JSONContent, MarkdownRendererHelpers } from '@tiptap/react'
|
||||
import { ImageUploadPlaceholderExtension, createImageUploadHandler } from '@/extensions/image-upload'
|
||||
import { TaskBlockExtension } from '@/extensions/task-block'
|
||||
import { TrackBlockExtension } from '@/extensions/track-block'
|
||||
|
|
@ -149,6 +151,17 @@ function serializeList(listNode: JsonNode, indent: number): string[] {
|
|||
return lines
|
||||
}
|
||||
|
||||
// Adapter for tiptap's first-party renderTableToMarkdown. Only renderChildren is
|
||||
// actually invoked — the other helpers are stubs to satisfy the type.
|
||||
const tableRenderHelpers: MarkdownRendererHelpers = {
|
||||
renderChildren: (nodes) => {
|
||||
const arr = Array.isArray(nodes) ? nodes : [nodes]
|
||||
return arr.map(n => n.type === 'paragraph' ? nodeToText(n as JsonNode) : '').join('')
|
||||
},
|
||||
wrapInBlock: (prefix, content) => prefix + content,
|
||||
indent: (content) => content,
|
||||
}
|
||||
|
||||
// Serialize a single top-level block to its markdown string. Empty paragraphs (or blank-marker
|
||||
// paragraphs) return '' to signal "blank line slot" for the join logic in serializeBlocksToMarkdown.
|
||||
function blockToMarkdown(node: JsonNode): string {
|
||||
|
|
@ -192,6 +205,8 @@ function blockToMarkdown(node: JsonNode): string {
|
|||
return '```transcript\n' + (node.attrs?.data as string || '{}') + '\n```'
|
||||
case 'mermaidBlock':
|
||||
return '```mermaid\n' + (node.attrs?.data as string || '') + '\n```'
|
||||
case 'table':
|
||||
return renderTableToMarkdown(node as JSONContent, tableRenderHelpers).trim()
|
||||
case 'codeBlock': {
|
||||
const lang = (node.attrs?.language as string) || ''
|
||||
return '```' + lang + '\n' + nodeToText(node) + '\n```'
|
||||
|
|
@ -697,6 +712,9 @@ export const MarkdownEditor = forwardRef<MarkdownEditorHandle, MarkdownEditorPro
|
|||
TaskItem.configure({
|
||||
nested: true,
|
||||
}),
|
||||
TableKit.configure({
|
||||
table: { resizable: false },
|
||||
}),
|
||||
Placeholder.configure({
|
||||
placeholder,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -146,6 +146,48 @@
|
|||
color: #eb5757;
|
||||
}
|
||||
|
||||
/* Native GFM tables (distinct from the custom tableBlock above) */
|
||||
.tiptap-editor .ProseMirror .tableWrapper {
|
||||
overflow-x: auto;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
font-size: 13px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror table th,
|
||||
.tiptap-editor .ProseMirror table td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 6px 10px;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror table th {
|
||||
background: color-mix(in srgb, var(--foreground) 4%, transparent);
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror table p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tiptap-editor .ProseMirror table .selectedCell::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: color-mix(in srgb, var(--foreground) 8%, transparent);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Divider */
|
||||
.tiptap-editor .ProseMirror hr {
|
||||
border: none;
|
||||
|
|
|
|||
14
apps/x/pnpm-lock.yaml
generated
14
apps/x/pnpm-lock.yaml
generated
|
|
@ -184,6 +184,9 @@ importers:
|
|||
'@tiptap/extension-placeholder':
|
||||
specifier: ^3.15.3
|
||||
version: 3.15.3(@tiptap/extensions@3.15.3(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3))
|
||||
'@tiptap/extension-table':
|
||||
specifier: ^3.22.4
|
||||
version: 3.22.4(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3)
|
||||
'@tiptap/extension-task-item':
|
||||
specifier: ^3.15.3
|
||||
version: 3.15.3(@tiptap/extension-list@3.15.3(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3))
|
||||
|
|
@ -3166,6 +3169,12 @@ packages:
|
|||
peerDependencies:
|
||||
'@tiptap/core': ^3.15.3
|
||||
|
||||
'@tiptap/extension-table@3.22.4':
|
||||
resolution: {integrity: sha512-kjvLv3Z4JI+1tLDqZKa+bKU8VcxY+ZOyMCKWQA7wYmy8nKWkLJ60W+xy8AcXXpHB2goCIgSFLhsTyswx0GXH4w==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': 3.22.4
|
||||
'@tiptap/pm': 3.22.4
|
||||
|
||||
'@tiptap/extension-task-item@3.15.3':
|
||||
resolution: {integrity: sha512-bkrmouc1rE5n9ONw2G7+zCGfBRoF2HJWq8REThPMzg/6+L5GJJ5YTN4UmncaP48U9jHX8xeihjgg9Ypenjl4lw==}
|
||||
peerDependencies:
|
||||
|
|
@ -11151,6 +11160,11 @@ snapshots:
|
|||
dependencies:
|
||||
'@tiptap/core': 3.15.3(@tiptap/pm@3.15.3)
|
||||
|
||||
'@tiptap/extension-table@3.22.4(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.15.3(@tiptap/pm@3.15.3)
|
||||
'@tiptap/pm': 3.15.3
|
||||
|
||||
'@tiptap/extension-task-item@3.15.3(@tiptap/extension-list@3.15.3(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3))':
|
||||
dependencies:
|
||||
'@tiptap/extension-list': 3.15.3(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue