@tiptap/static-renderer 3.24.0 → 3.26.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.
- package/dist/index.cjs +5 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -14
- package/dist/index.d.ts +42 -14
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/json/html-string/index.cjs +3 -3
- package/dist/json/html-string/index.cjs.map +1 -1
- package/dist/json/html-string/index.d.cts +39 -11
- package/dist/json/html-string/index.d.ts +39 -11
- package/dist/json/html-string/index.js +3 -3
- package/dist/json/html-string/index.js.map +1 -1
- package/dist/json/react/index.cjs +3 -3
- package/dist/json/react/index.cjs.map +1 -1
- package/dist/json/react/index.d.cts +39 -11
- package/dist/json/react/index.d.ts +39 -11
- package/dist/json/react/index.js +3 -3
- package/dist/json/react/index.js.map +1 -1
- package/dist/json/renderer.cjs +3 -3
- package/dist/json/renderer.cjs.map +1 -1
- package/dist/json/renderer.d.cts +36 -8
- package/dist/json/renderer.d.ts +36 -8
- package/dist/json/renderer.js +3 -3
- package/dist/json/renderer.js.map +1 -1
- package/dist/pm/html-string/index.cjs +3 -3
- package/dist/pm/html-string/index.cjs.map +1 -1
- package/dist/pm/html-string/index.d.cts +32 -4
- package/dist/pm/html-string/index.d.ts +32 -4
- package/dist/pm/html-string/index.js +3 -3
- package/dist/pm/html-string/index.js.map +1 -1
- package/dist/pm/markdown/index.cjs +5 -4
- package/dist/pm/markdown/index.cjs.map +1 -1
- package/dist/pm/markdown/index.d.cts +32 -4
- package/dist/pm/markdown/index.d.ts +32 -4
- package/dist/pm/markdown/index.js +5 -4
- package/dist/pm/markdown/index.js.map +1 -1
- package/dist/pm/react/index.cjs +3 -3
- package/dist/pm/react/index.cjs.map +1 -1
- package/dist/pm/react/index.d.cts +32 -4
- package/dist/pm/react/index.d.ts +32 -4
- package/dist/pm/react/index.js +3 -3
- package/dist/pm/react/index.js.map +1 -1
- package/package.json +5 -5
- package/src/json/html-string/string.ts +4 -6
- package/src/json/react/react.ts +4 -5
- package/src/json/renderer.ts +34 -8
- package/src/pm/markdown/markdown.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/json/renderer.ts","../../../src/json/html-string/string.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type { MarkType, NodeType } from '@tiptap/core'\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : content.type.name\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\nimport type { MarkType, NodeType } from '@tiptap/core'\n\nimport type { TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToString<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n>(options: TiptapStaticRendererOptions<string, TMarkType, TNodeType>) {\n return TiptapStaticRenderer(ctx => {\n return ctx.component(ctx.props as any)\n }, options)\n}\n\n/**\n * Escape text for HTML text content.\n * @param value The text to escape\n * @returns The escaped text\n */\nexport function escapeHTML(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\n}\n\n/**\n * Escape values for quoted HTML attributes.\n * @param value The attribute value to escape\n * @returns The escaped attribute value\n */\nexport function escapeHTMLAttribute(value: string): string {\n return escapeHTML(value).replace(/\"/g, '"')\n}\n\n/**\n * Serialize the attributes of a node or mark to a string\n * @param attrs The attributes to serialize\n * @returns The serialized attributes as a string\n */\nexport function serializeAttrsToHTMLString(attrs: Record<string, any> | undefined | null): string {\n // Match ProseMirror's DOMSerializer.renderSpec, which omits null/undefined attribute\n // values rather than stringifying them — otherwise we emit attrs like class=\"null\".\n const output = Object.entries(attrs || {})\n .filter(([, value]) => value != null)\n .map(([key, value]) => `${key.split(' ').at(-1)}=\"${escapeHTMLAttribute(String(value))}\"`)\n .join(' ')\n\n return output ? ` ${output}` : ''\n}\n\n/**\n * Serialize the children of a node or mark to a string\n * @param children The children to serialize\n * @returns The serialized children as a string\n */\nexport function serializeChildrenToHTMLString(children?: string | string[]): string {\n return ([] as string[])\n .concat(children || '')\n .filter(Boolean)\n .join('')\n}\n"],"mappings":";AAqHO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAzLlB;AA0LI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,QAAQ,KAAK;AAChF,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AA9N5C,UAAAA;AA+NU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;AC9OO,SAAS,0BAad,SAAoE;AACpE,SAAO,qBAAqB,SAAO;AACjC,WAAO,IAAI,UAAU,IAAI,KAAY;AAAA,EACvC,GAAG,OAAO;AACZ;AAOO,SAAS,WAAW,OAAuB;AAChD,SAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAChF;AAOO,SAAS,oBAAoB,OAAuB;AACzD,SAAO,WAAW,KAAK,EAAE,QAAQ,MAAM,QAAQ;AACjD;AAOO,SAAS,2BAA2B,OAAuD;AAGhG,QAAM,SAAS,OAAO,QAAQ,SAAS,CAAC,CAAC,EACtC,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,SAAS,IAAI,EACnC,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,oBAAoB,OAAO,KAAK,CAAC,CAAC,GAAG,EACxF,KAAK,GAAG;AAEX,SAAO,SAAS,IAAI,MAAM,KAAK;AACjC;AAOO,SAAS,8BAA8B,UAAsC;AAClF,SAAQ,CAAC,EACN,OAAO,YAAY,EAAE,EACrB,OAAO,OAAO,EACd,KAAK,EAAE;AACZ;","names":["_a"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/json/renderer.ts","../../../src/json/html-string/string.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type { JSONContent } from '@tiptap/core'\n\n/**\n * A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).\n */\nexport type JSONMarkType = NonNullable<JSONContent['marks']>[number]\n\n/**\n * A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).\n *\n * `marks` is tied to the `TMark` type parameter so the node<->mark relationship\n * stays sound. This is also why we cannot simply default `TNodeType` to\n * `JSONContent`: the generic constraint references `TMarkType` via\n * `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,\n * which TypeScript rejects (\"TMarkType could be instantiated with a different\n * subtype of constraint\"). Parameterizing the node type by the same `TMark`\n * avoids that bivariance error. Please don't \"simplify\" this back to\n * `JSONContent` — it won't type-check.\n */\nexport type JSONNodeType<TMark extends { type: string | { name: string } } = JSONMarkType> = {\n type?: string\n attrs?: Record<string, any>\n content?: JSONNodeType<TMark>[]\n marks?: readonly TMark[]\n text?: string\n [key: string]: any\n}\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : (content.type?.name ?? '')\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\nimport type { JSONMarkType, JSONNodeType, TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToString<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n>(options: TiptapStaticRendererOptions<string, TMarkType, TNodeType>) {\n return TiptapStaticRenderer(ctx => {\n return ctx.component(ctx.props as any)\n }, options)\n}\n\n/**\n * Escape text for HTML text content.\n * @param value The text to escape\n * @returns The escaped text\n */\nexport function escapeHTML(value: string): string {\n return value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\n}\n\n/**\n * Escape values for quoted HTML attributes.\n * @param value The attribute value to escape\n * @returns The escaped attribute value\n */\nexport function escapeHTMLAttribute(value: string): string {\n return escapeHTML(value).replace(/\"/g, '"')\n}\n\n/**\n * Serialize the attributes of a node or mark to a string\n * @param attrs The attributes to serialize\n * @returns The serialized attributes as a string\n */\nexport function serializeAttrsToHTMLString(attrs: Record<string, any> | undefined | null): string {\n // Match ProseMirror's DOMSerializer.renderSpec, which omits null/undefined attribute\n // values rather than stringifying them — otherwise we emit attrs like class=\"null\".\n const output = Object.entries(attrs || {})\n .filter(([, value]) => value != null)\n .map(([key, value]) => `${key.split(' ').at(-1)}=\"${escapeHTMLAttribute(String(value))}\"`)\n .join(' ')\n\n return output ? ` ${output}` : ''\n}\n\n/**\n * Serialize the children of a node or mark to a string\n * @param children The children to serialize\n * @returns The serialized children as a string\n */\nexport function serializeChildrenToHTMLString(children?: string | string[]): string {\n return ([] as string[])\n .concat(children || '')\n .filter(Boolean)\n .join('')\n}\n"],"mappings":";AA+IO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAnNlB;AAoNI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,mBAAQ,SAAR,mBAAc,SAAd,YAAsB;AAC1F,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AAxP5C,UAAAA;AAyPU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;AC1QO,SAAS,0BAad,SAAoE;AACpE,SAAO,qBAAqB,SAAO;AACjC,WAAO,IAAI,UAAU,IAAI,KAAY;AAAA,EACvC,GAAG,OAAO;AACZ;AAOO,SAAS,WAAW,OAAuB;AAChD,SAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAChF;AAOO,SAAS,oBAAoB,OAAuB;AACzD,SAAO,WAAW,KAAK,EAAE,QAAQ,MAAM,QAAQ;AACjD;AAOO,SAAS,2BAA2B,OAAuD;AAGhG,QAAM,SAAS,OAAO,QAAQ,SAAS,CAAC,CAAC,EACtC,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,SAAS,IAAI,EACnC,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,IAAI,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,oBAAoB,OAAO,KAAK,CAAC,CAAC,GAAG,EACxF,KAAK,GAAG;AAEX,SAAO,SAAS,IAAI,MAAM,KAAK;AACjC;AAOO,SAAS,8BAA8B,UAAsC;AAClF,SAAQ,CAAC,EACN,OAAO,YAAY,EAAE,EACrB,OAAO,OAAO,EACd,KAAK,EAAE;AACZ;","names":["_a"]}
|
|
@@ -46,9 +46,9 @@ function TiptapStaticRenderer(renderComponent, {
|
|
|
46
46
|
content,
|
|
47
47
|
parent
|
|
48
48
|
}) {
|
|
49
|
-
var _a;
|
|
50
|
-
const nodeType = typeof content.type === "string" ? content.type : content.type.name;
|
|
51
|
-
const NodeHandler = (
|
|
49
|
+
var _a, _b, _c;
|
|
50
|
+
const nodeType = typeof content.type === "string" ? content.type : (_b = (_a = content.type) == null ? void 0 : _a.name) != null ? _b : "";
|
|
51
|
+
const NodeHandler = (_c = nodeMapping[nodeType]) != null ? _c : unhandledNode;
|
|
52
52
|
if (!NodeHandler) {
|
|
53
53
|
throw new Error(`missing handler for node type ${nodeType}`);
|
|
54
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/json/react/index.ts","../../../src/json/renderer.ts","../../../src/json/react/react.ts"],"sourcesContent":["export * from '../renderer.js'\nexport * from './react.js'\n","/* oslint-disableno-explicit-any */\nimport type { MarkType, NodeType } from '@tiptap/core'\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : content.type.name\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\n\nimport type { MarkType, NodeType } from '@tiptap/core'\nimport React from 'react'\n\nimport type { TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToReactElement<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>) {\n let key = 0\n\n return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(\n ({ component, props: { children, ...props } }) => {\n return React.createElement(\n component as React.FC<typeof props>,\n // oxlint-disable-next-line no-plusplus\n Object.assign(props, { key: key++ }),\n ([] as React.ReactNode[]).concat(children),\n )\n },\n options,\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqHO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAzLlB;AA0LI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,QAAQ,KAAK;AAChF,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AA9N5C,UAAAA;AA+NU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;ACjPA,mBAAkB;AAKX,SAAS,gCAad,SAA6E;AAC7E,MAAI,MAAM;AAEV,SAAO;AAAA,IACL,CAAC,EAAE,WAAW,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM;AAChD,aAAO,aAAAC,QAAM;AAAA,QACX;AAAA;AAAA,QAEA,OAAO,OAAO,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,QAClC,CAAC,EAAwB,OAAO,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":["_a","React"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/json/react/index.ts","../../../src/json/renderer.ts","../../../src/json/react/react.ts"],"sourcesContent":["export * from '../renderer.js'\nexport * from './react.js'\n","/* oslint-disableno-explicit-any */\nimport type { JSONContent } from '@tiptap/core'\n\n/**\n * A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).\n */\nexport type JSONMarkType = NonNullable<JSONContent['marks']>[number]\n\n/**\n * A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).\n *\n * `marks` is tied to the `TMark` type parameter so the node<->mark relationship\n * stays sound. This is also why we cannot simply default `TNodeType` to\n * `JSONContent`: the generic constraint references `TMarkType` via\n * `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,\n * which TypeScript rejects (\"TMarkType could be instantiated with a different\n * subtype of constraint\"). Parameterizing the node type by the same `TMark`\n * avoids that bivariance error. Please don't \"simplify\" this back to\n * `JSONContent` — it won't type-check.\n */\nexport type JSONNodeType<TMark extends { type: string | { name: string } } = JSONMarkType> = {\n type?: string\n attrs?: Record<string, any>\n content?: JSONNodeType<TMark>[]\n marks?: readonly TMark[]\n text?: string\n [key: string]: any\n}\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : (content.type?.name ?? '')\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\n\nimport React from 'react'\n\nimport type { JSONMarkType, JSONNodeType, TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToReactElement<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>) {\n let key = 0\n\n return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(\n ({ component, props: { children, ...props } }) => {\n return React.createElement(\n component as React.FC<typeof props>,\n // oxlint-disable-next-line no-plusplus\n Object.assign(props, { key: key++ }),\n ([] as React.ReactNode[]).concat(children),\n )\n },\n options,\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC+IO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAnNlB;AAoNI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,mBAAQ,SAAR,mBAAc,SAAd,YAAsB;AAC1F,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AAxP5C,UAAAA;AAyPU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;AC5QA,mBAAkB;AAKX,SAAS,gCAad,SAA6E;AAC7E,MAAI,MAAM;AAEV,SAAO;AAAA,IACL,CAAC,EAAE,WAAW,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM;AAChD,aAAO,aAAAC,QAAM;AAAA,QACX;AAAA;AAAA,QAEA,OAAO,OAAO,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,QAClC,CAAC,EAAwB,OAAO,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":["_a","React"]}
|
|
@@ -1,6 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).
|
|
6
|
+
*/
|
|
7
|
+
type JSONMarkType = NonNullable<JSONContent['marks']>[number];
|
|
8
|
+
/**
|
|
9
|
+
* A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).
|
|
10
|
+
*
|
|
11
|
+
* `marks` is tied to the `TMark` type parameter so the node<->mark relationship
|
|
12
|
+
* stays sound. This is also why we cannot simply default `TNodeType` to
|
|
13
|
+
* `JSONContent`: the generic constraint references `TMarkType` via
|
|
14
|
+
* `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,
|
|
15
|
+
* which TypeScript rejects ("TMarkType could be instantiated with a different
|
|
16
|
+
* subtype of constraint"). Parameterizing the node type by the same `TMark`
|
|
17
|
+
* avoids that bivariance error. Please don't "simplify" this back to
|
|
18
|
+
* `JSONContent` — it won't type-check.
|
|
19
|
+
*/
|
|
20
|
+
type JSONNodeType<TMark extends {
|
|
21
|
+
type: string | {
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
} = JSONMarkType> = {
|
|
25
|
+
type?: string;
|
|
26
|
+
attrs?: Record<string, any>;
|
|
27
|
+
content?: JSONNodeType<TMark>[];
|
|
28
|
+
marks?: readonly TMark[];
|
|
29
|
+
text?: string;
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
};
|
|
4
32
|
/**
|
|
5
33
|
* Props for a node renderer
|
|
6
34
|
*/
|
|
@@ -62,7 +90,7 @@ TReturnType,
|
|
|
62
90
|
*/
|
|
63
91
|
TMarkType extends {
|
|
64
92
|
type: any;
|
|
65
|
-
} =
|
|
93
|
+
} = JSONMarkType,
|
|
66
94
|
/**
|
|
67
95
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
68
96
|
*/
|
|
@@ -71,10 +99,10 @@ TNodeType extends {
|
|
|
71
99
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
72
100
|
};
|
|
73
101
|
marks?: readonly TMarkType[];
|
|
74
|
-
type
|
|
102
|
+
type?: string | {
|
|
75
103
|
name: string;
|
|
76
104
|
};
|
|
77
|
-
} =
|
|
105
|
+
} = JSONNodeType<TMarkType>,
|
|
78
106
|
/**
|
|
79
107
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
80
108
|
*/
|
|
@@ -123,7 +151,7 @@ TMarkType extends {
|
|
|
123
151
|
type: string | {
|
|
124
152
|
name: string;
|
|
125
153
|
};
|
|
126
|
-
} =
|
|
154
|
+
} = JSONMarkType,
|
|
127
155
|
/**
|
|
128
156
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
129
157
|
*/
|
|
@@ -132,10 +160,10 @@ TNodeType extends {
|
|
|
132
160
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
133
161
|
};
|
|
134
162
|
marks?: readonly TMarkType[];
|
|
135
|
-
type
|
|
163
|
+
type?: string | {
|
|
136
164
|
name: string;
|
|
137
165
|
};
|
|
138
|
-
} =
|
|
166
|
+
} = JSONNodeType<TMarkType>,
|
|
139
167
|
/**
|
|
140
168
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
141
169
|
*/
|
|
@@ -170,7 +198,7 @@ declare function renderJSONContentToReactElement<
|
|
|
170
198
|
*/
|
|
171
199
|
TMarkType extends {
|
|
172
200
|
type: any;
|
|
173
|
-
} =
|
|
201
|
+
} = JSONMarkType,
|
|
174
202
|
/**
|
|
175
203
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
176
204
|
*/
|
|
@@ -179,12 +207,12 @@ TNodeType extends {
|
|
|
179
207
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
180
208
|
};
|
|
181
209
|
marks?: readonly TMarkType[];
|
|
182
|
-
type
|
|
210
|
+
type?: string | {
|
|
183
211
|
name: string;
|
|
184
212
|
};
|
|
185
|
-
} =
|
|
213
|
+
} = JSONNodeType<TMarkType>>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>): ({ content, parent, }: {
|
|
186
214
|
content: TNodeType;
|
|
187
215
|
parent?: TNodeType | undefined;
|
|
188
216
|
}) => React.ReactNode;
|
|
189
217
|
|
|
190
|
-
export { type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions, renderJSONContentToReactElement };
|
|
218
|
+
export { type JSONMarkType, type JSONNodeType, type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions, renderJSONContentToReactElement };
|
|
@@ -1,6 +1,34 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).
|
|
6
|
+
*/
|
|
7
|
+
type JSONMarkType = NonNullable<JSONContent['marks']>[number];
|
|
8
|
+
/**
|
|
9
|
+
* A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).
|
|
10
|
+
*
|
|
11
|
+
* `marks` is tied to the `TMark` type parameter so the node<->mark relationship
|
|
12
|
+
* stays sound. This is also why we cannot simply default `TNodeType` to
|
|
13
|
+
* `JSONContent`: the generic constraint references `TMarkType` via
|
|
14
|
+
* `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,
|
|
15
|
+
* which TypeScript rejects ("TMarkType could be instantiated with a different
|
|
16
|
+
* subtype of constraint"). Parameterizing the node type by the same `TMark`
|
|
17
|
+
* avoids that bivariance error. Please don't "simplify" this back to
|
|
18
|
+
* `JSONContent` — it won't type-check.
|
|
19
|
+
*/
|
|
20
|
+
type JSONNodeType<TMark extends {
|
|
21
|
+
type: string | {
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
} = JSONMarkType> = {
|
|
25
|
+
type?: string;
|
|
26
|
+
attrs?: Record<string, any>;
|
|
27
|
+
content?: JSONNodeType<TMark>[];
|
|
28
|
+
marks?: readonly TMark[];
|
|
29
|
+
text?: string;
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
};
|
|
4
32
|
/**
|
|
5
33
|
* Props for a node renderer
|
|
6
34
|
*/
|
|
@@ -62,7 +90,7 @@ TReturnType,
|
|
|
62
90
|
*/
|
|
63
91
|
TMarkType extends {
|
|
64
92
|
type: any;
|
|
65
|
-
} =
|
|
93
|
+
} = JSONMarkType,
|
|
66
94
|
/**
|
|
67
95
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
68
96
|
*/
|
|
@@ -71,10 +99,10 @@ TNodeType extends {
|
|
|
71
99
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
72
100
|
};
|
|
73
101
|
marks?: readonly TMarkType[];
|
|
74
|
-
type
|
|
102
|
+
type?: string | {
|
|
75
103
|
name: string;
|
|
76
104
|
};
|
|
77
|
-
} =
|
|
105
|
+
} = JSONNodeType<TMarkType>,
|
|
78
106
|
/**
|
|
79
107
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
80
108
|
*/
|
|
@@ -123,7 +151,7 @@ TMarkType extends {
|
|
|
123
151
|
type: string | {
|
|
124
152
|
name: string;
|
|
125
153
|
};
|
|
126
|
-
} =
|
|
154
|
+
} = JSONMarkType,
|
|
127
155
|
/**
|
|
128
156
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
129
157
|
*/
|
|
@@ -132,10 +160,10 @@ TNodeType extends {
|
|
|
132
160
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
133
161
|
};
|
|
134
162
|
marks?: readonly TMarkType[];
|
|
135
|
-
type
|
|
163
|
+
type?: string | {
|
|
136
164
|
name: string;
|
|
137
165
|
};
|
|
138
|
-
} =
|
|
166
|
+
} = JSONNodeType<TMarkType>,
|
|
139
167
|
/**
|
|
140
168
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
141
169
|
*/
|
|
@@ -170,7 +198,7 @@ declare function renderJSONContentToReactElement<
|
|
|
170
198
|
*/
|
|
171
199
|
TMarkType extends {
|
|
172
200
|
type: any;
|
|
173
|
-
} =
|
|
201
|
+
} = JSONMarkType,
|
|
174
202
|
/**
|
|
175
203
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
176
204
|
*/
|
|
@@ -179,12 +207,12 @@ TNodeType extends {
|
|
|
179
207
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
180
208
|
};
|
|
181
209
|
marks?: readonly TMarkType[];
|
|
182
|
-
type
|
|
210
|
+
type?: string | {
|
|
183
211
|
name: string;
|
|
184
212
|
};
|
|
185
|
-
} =
|
|
213
|
+
} = JSONNodeType<TMarkType>>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>): ({ content, parent, }: {
|
|
186
214
|
content: TNodeType;
|
|
187
215
|
parent?: TNodeType | undefined;
|
|
188
216
|
}) => React.ReactNode;
|
|
189
217
|
|
|
190
|
-
export { type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions, renderJSONContentToReactElement };
|
|
218
|
+
export { type JSONMarkType, type JSONNodeType, type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions, renderJSONContentToReactElement };
|
package/dist/json/react/index.js
CHANGED
|
@@ -9,9 +9,9 @@ function TiptapStaticRenderer(renderComponent, {
|
|
|
9
9
|
content,
|
|
10
10
|
parent
|
|
11
11
|
}) {
|
|
12
|
-
var _a;
|
|
13
|
-
const nodeType = typeof content.type === "string" ? content.type : content.type.name;
|
|
14
|
-
const NodeHandler = (
|
|
12
|
+
var _a, _b, _c;
|
|
13
|
+
const nodeType = typeof content.type === "string" ? content.type : (_b = (_a = content.type) == null ? void 0 : _a.name) != null ? _b : "";
|
|
14
|
+
const NodeHandler = (_c = nodeMapping[nodeType]) != null ? _c : unhandledNode;
|
|
15
15
|
if (!NodeHandler) {
|
|
16
16
|
throw new Error(`missing handler for node type ${nodeType}`);
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/json/renderer.ts","../../../src/json/react/react.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type { MarkType, NodeType } from '@tiptap/core'\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : content.type.name\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\n\nimport type { MarkType, NodeType } from '@tiptap/core'\nimport React from 'react'\n\nimport type { TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToReactElement<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = MarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type: string | { name: string }\n } = NodeType,\n>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>) {\n let key = 0\n\n return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(\n ({ component, props: { children, ...props } }) => {\n return React.createElement(\n component as React.FC<typeof props>,\n // oxlint-disable-next-line no-plusplus\n Object.assign(props, { key: key++ }),\n ([] as React.ReactNode[]).concat(children),\n )\n },\n options,\n )\n}\n"],"mappings":";AAqHO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAzLlB;AA0LI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,QAAQ,KAAK;AAChF,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AA9N5C,UAAAA;AA+NU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;ACjPA,OAAO,WAAW;AAKX,SAAS,gCAad,SAA6E;AAC7E,MAAI,MAAM;AAEV,SAAO;AAAA,IACL,CAAC,EAAE,WAAW,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM;AAChD,aAAO,MAAM;AAAA,QACX;AAAA;AAAA,QAEA,OAAO,OAAO,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,QAClC,CAAC,EAAwB,OAAO,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":["_a"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/json/renderer.ts","../../../src/json/react/react.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type { JSONContent } from '@tiptap/core'\n\n/**\n * A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).\n */\nexport type JSONMarkType = NonNullable<JSONContent['marks']>[number]\n\n/**\n * A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).\n *\n * `marks` is tied to the `TMark` type parameter so the node<->mark relationship\n * stays sound. This is also why we cannot simply default `TNodeType` to\n * `JSONContent`: the generic constraint references `TMarkType` via\n * `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,\n * which TypeScript rejects (\"TMarkType could be instantiated with a different\n * subtype of constraint\"). Parameterizing the node type by the same `TMark`\n * avoids that bivariance error. Please don't \"simplify\" this back to\n * `JSONContent` — it won't type-check.\n */\nexport type JSONNodeType<TMark extends { type: string | { name: string } } = JSONMarkType> = {\n type?: string\n attrs?: Record<string, any>\n content?: JSONNodeType<TMark>[]\n marks?: readonly TMark[]\n text?: string\n [key: string]: any\n}\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : (content.type?.name ?? '')\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n","/* oslint-disableno-explicit-any */\n\nimport React from 'react'\n\nimport type { JSONMarkType, JSONNodeType, TiptapStaticRendererOptions } from '../renderer.js'\nimport { TiptapStaticRenderer } from '../renderer.js'\n\nexport function renderJSONContentToReactElement<\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>) {\n let key = 0\n\n return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(\n ({ component, props: { children, ...props } }) => {\n return React.createElement(\n component as React.FC<typeof props>,\n // oxlint-disable-next-line no-plusplus\n Object.assign(props, { key: key++ }),\n ([] as React.ReactNode[]).concat(children),\n )\n },\n options,\n )\n}\n"],"mappings":";AA+IO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAnNlB;AAoNI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,mBAAQ,SAAR,mBAAc,SAAd,YAAsB;AAC1F,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AAxP5C,UAAAA;AAyPU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;;;AC5QA,OAAO,WAAW;AAKX,SAAS,gCAad,SAA6E;AAC7E,MAAI,MAAM;AAEV,SAAO;AAAA,IACL,CAAC,EAAE,WAAW,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,MAAM;AAChD,aAAO,MAAM;AAAA,QACX;AAAA;AAAA,QAEA,OAAO,OAAO,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,QAClC,CAAC,EAAwB,OAAO,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;","names":["_a"]}
|
package/dist/json/renderer.cjs
CHANGED
|
@@ -33,9 +33,9 @@ function TiptapStaticRenderer(renderComponent, {
|
|
|
33
33
|
content,
|
|
34
34
|
parent
|
|
35
35
|
}) {
|
|
36
|
-
var _a;
|
|
37
|
-
const nodeType = typeof content.type === "string" ? content.type : content.type.name;
|
|
38
|
-
const NodeHandler = (
|
|
36
|
+
var _a, _b, _c;
|
|
37
|
+
const nodeType = typeof content.type === "string" ? content.type : (_b = (_a = content.type) == null ? void 0 : _a.name) != null ? _b : "";
|
|
38
|
+
const NodeHandler = (_c = nodeMapping[nodeType]) != null ? _c : unhandledNode;
|
|
39
39
|
if (!NodeHandler) {
|
|
40
40
|
throw new Error(`missing handler for node type ${nodeType}`);
|
|
41
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/json/renderer.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type {
|
|
1
|
+
{"version":3,"sources":["../../src/json/renderer.ts"],"sourcesContent":["/* oslint-disableno-explicit-any */\nimport type { JSONContent } from '@tiptap/core'\n\n/**\n * A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).\n */\nexport type JSONMarkType = NonNullable<JSONContent['marks']>[number]\n\n/**\n * A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).\n *\n * `marks` is tied to the `TMark` type parameter so the node<->mark relationship\n * stays sound. This is also why we cannot simply default `TNodeType` to\n * `JSONContent`: the generic constraint references `TMarkType` via\n * `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,\n * which TypeScript rejects (\"TMarkType could be instantiated with a different\n * subtype of constraint\"). Parameterizing the node type by the same `TMark`\n * avoids that bivariance error. Please don't \"simplify\" this back to\n * `JSONContent` — it won't type-check.\n */\nexport type JSONNodeType<TMark extends { type: string | { name: string } } = JSONMarkType> = {\n type?: string\n attrs?: Record<string, any>\n content?: JSONNodeType<TMark>[]\n marks?: readonly TMark[]\n text?: string\n [key: string]: any\n}\n\n/**\n * Props for a node renderer\n */\nexport type NodeProps<TNodeType = any, TChildren = any> = {\n /**\n * The current node to render\n */\n node: TNodeType\n /**\n * Unless the node is the root node, this will always be defined\n */\n parent?: TNodeType\n /**\n * The children of the current node\n */\n children?: TChildren\n /**\n * Render a child element\n */\n renderElement: (props: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }) => TChildren\n}\n\n/**\n * Props for a mark renderer\n */\nexport type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {\n /**\n * The current mark to render\n */\n mark: TMarkType\n /**\n * The children of the current mark\n */\n children?: TChildren\n /**\n * The node the current mark is applied to\n */\n node: TNodeType\n /**\n * The node the current mark is applied to\n */\n parent?: TNodeType\n}\n\nexport type TiptapStaticRendererOptions<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: any } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n> = {\n /**\n * Mapping of node types to react components\n */\n nodeMapping: Record<string, NoInfer<TNodeRender>>\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, NoInfer<TMarkRender>>\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: NoInfer<TMarkRender>\n}\n\n/**\n * Tiptap Static Renderer\n * ----------------------\n *\n * This function is a basis to allow for different renderers to be created.\n * Generic enough to be able to statically render Prosemirror JSON or Prosemirror Nodes.\n *\n * Using this function, you can create a renderer that takes a JSON representation of a Prosemirror document\n * and renders it using a mapping of node types to React components or even to a string.\n * This function is used as the basis to create the `reactRenderer` and `stringRenderer` functions.\n */\nexport function TiptapStaticRenderer<\n /**\n * The return type of the render function (e.g. React.ReactNode, string)\n */\n TReturnType,\n /**\n * A mark type is either a JSON representation of a mark or a Prosemirror mark instance\n */\n TMarkType extends { type: string | { name: string } } = JSONMarkType,\n /**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\n TNodeType extends {\n content?: { forEach: (cb: (node: TNodeType) => void) => void }\n marks?: readonly TMarkType[]\n type?: string | { name: string }\n } = JSONNodeType<TMarkType>,\n /**\n * A node renderer is a function that takes a node and its children and returns the rendered output\n */\n TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (\n ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,\n ) => TReturnType,\n /**\n * A mark renderer is a function that takes a mark and its children and returns the rendered output\n */\n TMarkRender extends (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType = (\n ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,\n ) => TReturnType,\n>(\n /**\n * The function that actually renders the component\n */\n renderComponent: (\n ctx:\n | {\n component: TNodeRender\n props: NodeProps<TNodeType, TReturnType | TReturnType[]>\n }\n | {\n component: TMarkRender\n props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>\n },\n ) => TReturnType,\n {\n nodeMapping,\n markMapping,\n unhandledNode,\n unhandledMark,\n }: TiptapStaticRendererOptions<TReturnType, TMarkType, TNodeType, TNodeRender, TMarkRender>,\n) {\n /**\n * Render Tiptap JSON and all its children using the provided node and mark mappings.\n */\n return function renderContent({\n content,\n parent,\n }: {\n /**\n * Tiptap JSON content to render\n */\n content: TNodeType\n /**\n * The parent node of the current node\n */\n parent?: TNodeType\n }): TReturnType {\n const nodeType = typeof content.type === 'string' ? content.type : (content.type?.name ?? '')\n const NodeHandler = nodeMapping[nodeType] ?? unhandledNode\n\n if (!NodeHandler) {\n throw new Error(`missing handler for node type ${nodeType}`)\n }\n\n const nodeContent = renderComponent({\n component: NodeHandler,\n props: {\n node: content,\n parent,\n renderElement: renderContent,\n // Lazily compute the children to avoid unnecessary recursion\n get children() {\n // recursively render child content nodes\n const children: TReturnType[] = []\n\n if (content.content) {\n content.content.forEach(child => {\n children.push(\n renderContent({\n content: child,\n parent: content,\n }),\n )\n })\n }\n\n return children\n },\n },\n })\n\n // apply marks to the content\n const markedContent = content.marks\n ? content.marks.reduce((acc, mark) => {\n const markType = typeof mark.type === 'string' ? mark.type : mark.type.name\n const MarkHandler = markMapping[markType] ?? unhandledMark\n\n if (!MarkHandler) {\n throw new Error(`missing handler for mark type ${markType}`)\n }\n\n return renderComponent({\n component: MarkHandler,\n props: {\n mark,\n parent,\n node: content,\n children: acc,\n },\n })\n }, nodeContent)\n : nodeContent\n\n return markedContent\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+IO,SAAS,qBAmCd,iBAWA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA;AAIA,SAAO,SAAS,cAAc;AAAA,IAC5B;AAAA,IACA;AAAA,EACF,GASgB;AAnNlB;AAoNI,UAAM,WAAW,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,mBAAQ,SAAR,mBAAc,SAAd,YAAsB;AAC1F,UAAM,eAAc,iBAAY,QAAQ,MAApB,YAAyB;AAE7C,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,IAC7D;AAEA,UAAM,cAAc,gBAAgB;AAAA,MAClC,WAAW;AAAA,MACX,OAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,eAAe;AAAA;AAAA,QAEf,IAAI,WAAW;AAEb,gBAAM,WAA0B,CAAC;AAEjC,cAAI,QAAQ,SAAS;AACnB,oBAAQ,QAAQ,QAAQ,WAAS;AAC/B,uBAAS;AAAA,gBACP,cAAc;AAAA,kBACZ,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,UACH;AAEA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,QAAQ,QAC1B,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS;AAxP5C,UAAAA;AAyPU,YAAM,WAAW,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,KAAK,KAAK;AACvE,YAAM,eAAcA,MAAA,YAAY,QAAQ,MAApB,OAAAA,MAAyB;AAE7C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,iCAAiC,QAAQ,EAAE;AAAA,MAC7D;AAEA,aAAO,gBAAgB;AAAA,QACrB,WAAW;AAAA,QACX,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,GAAG,WAAW,IACd;AAEJ,WAAO;AAAA,EACT;AACF;","names":["_a"]}
|
package/dist/json/renderer.d.cts
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).
|
|
5
|
+
*/
|
|
6
|
+
type JSONMarkType = NonNullable<JSONContent['marks']>[number];
|
|
7
|
+
/**
|
|
8
|
+
* A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).
|
|
9
|
+
*
|
|
10
|
+
* `marks` is tied to the `TMark` type parameter so the node<->mark relationship
|
|
11
|
+
* stays sound. This is also why we cannot simply default `TNodeType` to
|
|
12
|
+
* `JSONContent`: the generic constraint references `TMarkType` via
|
|
13
|
+
* `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,
|
|
14
|
+
* which TypeScript rejects ("TMarkType could be instantiated with a different
|
|
15
|
+
* subtype of constraint"). Parameterizing the node type by the same `TMark`
|
|
16
|
+
* avoids that bivariance error. Please don't "simplify" this back to
|
|
17
|
+
* `JSONContent` — it won't type-check.
|
|
18
|
+
*/
|
|
19
|
+
type JSONNodeType<TMark extends {
|
|
20
|
+
type: string | {
|
|
21
|
+
name: string;
|
|
22
|
+
};
|
|
23
|
+
} = JSONMarkType> = {
|
|
24
|
+
type?: string;
|
|
25
|
+
attrs?: Record<string, any>;
|
|
26
|
+
content?: JSONNodeType<TMark>[];
|
|
27
|
+
marks?: readonly TMark[];
|
|
28
|
+
text?: string;
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
3
31
|
/**
|
|
4
32
|
* Props for a node renderer
|
|
5
33
|
*/
|
|
@@ -61,7 +89,7 @@ TReturnType,
|
|
|
61
89
|
*/
|
|
62
90
|
TMarkType extends {
|
|
63
91
|
type: any;
|
|
64
|
-
} =
|
|
92
|
+
} = JSONMarkType,
|
|
65
93
|
/**
|
|
66
94
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
67
95
|
*/
|
|
@@ -70,10 +98,10 @@ TNodeType extends {
|
|
|
70
98
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
71
99
|
};
|
|
72
100
|
marks?: readonly TMarkType[];
|
|
73
|
-
type
|
|
101
|
+
type?: string | {
|
|
74
102
|
name: string;
|
|
75
103
|
};
|
|
76
|
-
} =
|
|
104
|
+
} = JSONNodeType<TMarkType>,
|
|
77
105
|
/**
|
|
78
106
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
79
107
|
*/
|
|
@@ -122,7 +150,7 @@ TMarkType extends {
|
|
|
122
150
|
type: string | {
|
|
123
151
|
name: string;
|
|
124
152
|
};
|
|
125
|
-
} =
|
|
153
|
+
} = JSONMarkType,
|
|
126
154
|
/**
|
|
127
155
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
128
156
|
*/
|
|
@@ -131,10 +159,10 @@ TNodeType extends {
|
|
|
131
159
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
132
160
|
};
|
|
133
161
|
marks?: readonly TMarkType[];
|
|
134
|
-
type
|
|
162
|
+
type?: string | {
|
|
135
163
|
name: string;
|
|
136
164
|
};
|
|
137
|
-
} =
|
|
165
|
+
} = JSONNodeType<TMarkType>,
|
|
138
166
|
/**
|
|
139
167
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
140
168
|
*/
|
|
@@ -163,4 +191,4 @@ renderComponent: (ctx: {
|
|
|
163
191
|
parent?: TNodeType;
|
|
164
192
|
}) => TReturnType;
|
|
165
193
|
|
|
166
|
-
export { type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions };
|
|
194
|
+
export { type JSONMarkType, type JSONNodeType, type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions };
|
package/dist/json/renderer.d.ts
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* A JSON representation of a mark (a Tiptap/ProseMirror mark serialized to JSON).
|
|
5
|
+
*/
|
|
6
|
+
type JSONMarkType = NonNullable<JSONContent['marks']>[number];
|
|
7
|
+
/**
|
|
8
|
+
* A JSON representation of a node (a Tiptap/ProseMirror node serialized to JSON).
|
|
9
|
+
*
|
|
10
|
+
* `marks` is tied to the `TMark` type parameter so the node<->mark relationship
|
|
11
|
+
* stays sound. This is also why we cannot simply default `TNodeType` to
|
|
12
|
+
* `JSONContent`: the generic constraint references `TMarkType` via
|
|
13
|
+
* `marks?: readonly TMarkType[]`, and `JSONContent.marks` is a *concrete* array,
|
|
14
|
+
* which TypeScript rejects ("TMarkType could be instantiated with a different
|
|
15
|
+
* subtype of constraint"). Parameterizing the node type by the same `TMark`
|
|
16
|
+
* avoids that bivariance error. Please don't "simplify" this back to
|
|
17
|
+
* `JSONContent` — it won't type-check.
|
|
18
|
+
*/
|
|
19
|
+
type JSONNodeType<TMark extends {
|
|
20
|
+
type: string | {
|
|
21
|
+
name: string;
|
|
22
|
+
};
|
|
23
|
+
} = JSONMarkType> = {
|
|
24
|
+
type?: string;
|
|
25
|
+
attrs?: Record<string, any>;
|
|
26
|
+
content?: JSONNodeType<TMark>[];
|
|
27
|
+
marks?: readonly TMark[];
|
|
28
|
+
text?: string;
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
};
|
|
3
31
|
/**
|
|
4
32
|
* Props for a node renderer
|
|
5
33
|
*/
|
|
@@ -61,7 +89,7 @@ TReturnType,
|
|
|
61
89
|
*/
|
|
62
90
|
TMarkType extends {
|
|
63
91
|
type: any;
|
|
64
|
-
} =
|
|
92
|
+
} = JSONMarkType,
|
|
65
93
|
/**
|
|
66
94
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
67
95
|
*/
|
|
@@ -70,10 +98,10 @@ TNodeType extends {
|
|
|
70
98
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
71
99
|
};
|
|
72
100
|
marks?: readonly TMarkType[];
|
|
73
|
-
type
|
|
101
|
+
type?: string | {
|
|
74
102
|
name: string;
|
|
75
103
|
};
|
|
76
|
-
} =
|
|
104
|
+
} = JSONNodeType<TMarkType>,
|
|
77
105
|
/**
|
|
78
106
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
79
107
|
*/
|
|
@@ -122,7 +150,7 @@ TMarkType extends {
|
|
|
122
150
|
type: string | {
|
|
123
151
|
name: string;
|
|
124
152
|
};
|
|
125
|
-
} =
|
|
153
|
+
} = JSONMarkType,
|
|
126
154
|
/**
|
|
127
155
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
128
156
|
*/
|
|
@@ -131,10 +159,10 @@ TNodeType extends {
|
|
|
131
159
|
forEach: (cb: (node: TNodeType) => void) => void;
|
|
132
160
|
};
|
|
133
161
|
marks?: readonly TMarkType[];
|
|
134
|
-
type
|
|
162
|
+
type?: string | {
|
|
135
163
|
name: string;
|
|
136
164
|
};
|
|
137
|
-
} =
|
|
165
|
+
} = JSONNodeType<TMarkType>,
|
|
138
166
|
/**
|
|
139
167
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
140
168
|
*/
|
|
@@ -163,4 +191,4 @@ renderComponent: (ctx: {
|
|
|
163
191
|
parent?: TNodeType;
|
|
164
192
|
}) => TReturnType;
|
|
165
193
|
|
|
166
|
-
export { type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions };
|
|
194
|
+
export { type JSONMarkType, type JSONNodeType, type MarkProps, type NodeProps, TiptapStaticRenderer, type TiptapStaticRendererOptions };
|