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-image": "^3.16.0",
|
||||||
"@tiptap/extension-link": "^3.15.3",
|
"@tiptap/extension-link": "^3.15.3",
|
||||||
"@tiptap/extension-placeholder": "^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-item": "^3.15.3",
|
||||||
"@tiptap/extension-task-list": "^3.15.3",
|
"@tiptap/extension-task-list": "^3.15.3",
|
||||||
"@tiptap/pm": "^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 Placeholder from '@tiptap/extension-placeholder'
|
||||||
import TaskList from '@tiptap/extension-task-list'
|
import TaskList from '@tiptap/extension-task-list'
|
||||||
import TaskItem from '@tiptap/extension-task-item'
|
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 { ImageUploadPlaceholderExtension, createImageUploadHandler } from '@/extensions/image-upload'
|
||||||
import { TaskBlockExtension } from '@/extensions/task-block'
|
import { TaskBlockExtension } from '@/extensions/task-block'
|
||||||
import { TrackBlockExtension } from '@/extensions/track-block'
|
import { TrackBlockExtension } from '@/extensions/track-block'
|
||||||
|
|
@ -149,6 +151,17 @@ function serializeList(listNode: JsonNode, indent: number): string[] {
|
||||||
return lines
|
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
|
// 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.
|
// paragraphs) return '' to signal "blank line slot" for the join logic in serializeBlocksToMarkdown.
|
||||||
function blockToMarkdown(node: JsonNode): string {
|
function blockToMarkdown(node: JsonNode): string {
|
||||||
|
|
@ -192,6 +205,8 @@ function blockToMarkdown(node: JsonNode): string {
|
||||||
return '```transcript\n' + (node.attrs?.data as string || '{}') + '\n```'
|
return '```transcript\n' + (node.attrs?.data as string || '{}') + '\n```'
|
||||||
case 'mermaidBlock':
|
case 'mermaidBlock':
|
||||||
return '```mermaid\n' + (node.attrs?.data as string || '') + '\n```'
|
return '```mermaid\n' + (node.attrs?.data as string || '') + '\n```'
|
||||||
|
case 'table':
|
||||||
|
return renderTableToMarkdown(node as JSONContent, tableRenderHelpers).trim()
|
||||||
case 'codeBlock': {
|
case 'codeBlock': {
|
||||||
const lang = (node.attrs?.language as string) || ''
|
const lang = (node.attrs?.language as string) || ''
|
||||||
return '```' + lang + '\n' + nodeToText(node) + '\n```'
|
return '```' + lang + '\n' + nodeToText(node) + '\n```'
|
||||||
|
|
@ -697,6 +712,9 @@ export const MarkdownEditor = forwardRef<MarkdownEditorHandle, MarkdownEditorPro
|
||||||
TaskItem.configure({
|
TaskItem.configure({
|
||||||
nested: true,
|
nested: true,
|
||||||
}),
|
}),
|
||||||
|
TableKit.configure({
|
||||||
|
table: { resizable: false },
|
||||||
|
}),
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder,
|
placeholder,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,48 @@
|
||||||
color: #eb5757;
|
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 */
|
/* Divider */
|
||||||
.tiptap-editor .ProseMirror hr {
|
.tiptap-editor .ProseMirror hr {
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
||||||
14
apps/x/pnpm-lock.yaml
generated
14
apps/x/pnpm-lock.yaml
generated
|
|
@ -184,6 +184,9 @@ importers:
|
||||||
'@tiptap/extension-placeholder':
|
'@tiptap/extension-placeholder':
|
||||||
specifier: ^3.15.3
|
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))
|
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':
|
'@tiptap/extension-task-item':
|
||||||
specifier: ^3.15.3
|
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))
|
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:
|
peerDependencies:
|
||||||
'@tiptap/core': ^3.15.3
|
'@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':
|
'@tiptap/extension-task-item@3.15.3':
|
||||||
resolution: {integrity: sha512-bkrmouc1rE5n9ONw2G7+zCGfBRoF2HJWq8REThPMzg/6+L5GJJ5YTN4UmncaP48U9jHX8xeihjgg9Ypenjl4lw==}
|
resolution: {integrity: sha512-bkrmouc1rE5n9ONw2G7+zCGfBRoF2HJWq8REThPMzg/6+L5GJJ5YTN4UmncaP48U9jHX8xeihjgg9Ypenjl4lw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -11151,6 +11160,11 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tiptap/core': 3.15.3(@tiptap/pm@3.15.3)
|
'@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))':
|
'@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:
|
dependencies:
|
||||||
'@tiptap/extension-list': 3.15.3(@tiptap/core@3.15.3(@tiptap/pm@3.15.3))(@tiptap/pm@3.15.3)
|
'@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