diff --git a/packages/static-renderer/src/json/renderer.ts b/packages/static-renderer/src/json/renderer.ts index b4ac95a61a..f669c3c81d 100644 --- a/packages/static-renderer/src/json/renderer.ts +++ b/packages/static-renderer/src/json/renderer.ts @@ -29,15 +29,29 @@ export type NodeProps = { * The parent node of the current node */ parent?: TNodeType; - })=> TChildren; + }) => TChildren; }; /** * Props for a mark renderer */ -export type MarkProps = { +export type MarkProps = { + /** + * The current mark to render + */ mark: TMarkType; + /** + * The children of the current mark + */ children?: TChildren; + /** + * The node the current mark is applied to + */ + node: TNodeType; + /** + * The node the current mark is applied to + */ + parent?: TNodeType; }; export type TiptapStaticRendererOptions< @@ -60,18 +74,14 @@ export type TiptapStaticRendererOptions< /** * A node renderer is a function that takes a node and its children and returns the rendered output */ - TNodeRender extends ( - ctx: NodeProps - ) => TReturnType = ( + TNodeRender extends (ctx: NodeProps) => TReturnType = ( ctx: NodeProps ) => TReturnType, /** * A mark renderer is a function that takes a mark and its children and returns the rendered output */ - TMarkRender extends ( - ctx: MarkProps - ) => TReturnType = ( - ctx: MarkProps + TMarkRender extends (ctx: MarkProps) => TReturnType = ( + ctx: MarkProps ) => TReturnType, > = { /** @@ -124,18 +134,14 @@ cb: (node: TNodeType) => void) => void }; /** * A node renderer is a function that takes a node and its children and returns the rendered output */ - TNodeRender extends ( - ctx: NodeProps - ) => TReturnType = ( + TNodeRender extends (ctx: NodeProps) => TReturnType = ( ctx: NodeProps ) => TReturnType, /** * A mark renderer is a function that takes a mark and its children and returns the rendered output */ - TMarkRender extends ( - ctx: MarkProps - ) => TReturnType = ( - ctx: MarkProps + TMarkRender extends (ctx: MarkProps) => TReturnType = ( + ctx: MarkProps ) => TReturnType, >( /** @@ -149,7 +155,7 @@ cb: (node: TNodeType) => void) => void }; } | { component: TMarkRender; - props: MarkProps; + props: MarkProps; } ) => TReturnType, { @@ -157,13 +163,7 @@ cb: (node: TNodeType) => void) => void }; markMapping, unhandledNode, unhandledMark, - }: TiptapStaticRendererOptions< - TReturnType, - TMarkType, - TNodeType, - TNodeRender, - TMarkRender - >, + }: TiptapStaticRendererOptions, ) { /** * Render Tiptap JSON and all its children using the provided node and mark mappings. @@ -181,7 +181,6 @@ cb: (node: TNodeType) => void) => void }; */ parent?: TNodeType; }): TReturnType { - const nodeType = typeof content.type === 'string' ? content.type : content.type.name const NodeHandler = nodeMapping[nodeType] ?? unhandledNode @@ -197,7 +196,7 @@ cb: (node: TNodeType) => void) => void }; renderElement: renderContent, // Lazily compute the children to avoid unnecessary recursion get children() { - // recursively render child content nodes + // recursively render child content nodes const children: TReturnType[] = [] if (content.content) { @@ -231,6 +230,7 @@ cb: (node: TNodeType) => void) => void }; props: { mark, parent, + node: content, children: acc, }, }) diff --git a/packages/static-renderer/src/pm/markdown.example.ts b/packages/static-renderer/src/pm/markdown.example.ts index 5e97521b32..c97d5d26ad 100644 --- a/packages/static-renderer/src/pm/markdown.example.ts +++ b/packages/static-renderer/src/pm/markdown.example.ts @@ -46,12 +46,20 @@ const renderToMarkdown = ({ content }: { content: JSONContent | Node }) => rende return `${new Array(level).fill('#').join('')} ${children}\n` }, codeBlock({ node, children }) { - return `\n\`\`\`${node.attrs.language}\n${serializeChildrenToHTMLString(children)}\n\`\`\`\n` + return `\n\`\`\`${node.attrs.language}\n${serializeChildrenToHTMLString( + children, + )}\n\`\`\`\n` }, blockquote({ children }) { - return `\n${serializeChildrenToHTMLString(children).trim().split('\n').map(a => `> ${a}`) + return `\n${serializeChildrenToHTMLString(children) + .trim() + .split('\n') + .map(a => `> ${a}`) .join('\n')}` }, + image({ node }) { + return `![${node.attrs.alt}](${node.attrs.src})` + }, hardBreak() { return '\n' }, @@ -60,8 +68,23 @@ const renderToMarkdown = ({ content }: { content: JSONContent | Node }) => rende bold({ children }) { return `**${serializeChildrenToHTMLString(children)}**` }, - italic({ children }) { - return `*${serializeChildrenToHTMLString(children)}*` + italic({ children, node }) { + let isBoldToo = false + + // Check if the node being wrapped also has a bold mark, if so, we need to use the bold markdown syntax + if (node?.marks.some(m => m.type.name === 'bold')) { + isBoldToo = true + } + + if (isBoldToo) { + // If the content is bold, just wrap the bold content in italic markdown syntax with another set of asterisks + return `*${serializeChildrenToHTMLString(children)}*` + } + + return `_${serializeChildrenToHTMLString(children)}_` + }, + code({ children }) { + return `\`${serializeChildrenToHTMLString(children)}\`` }, }, }, @@ -127,6 +150,9 @@ console.log( { type: 'bold', }, + { + type: 'italic', + }, ], text: 'Tiptap', },