@tiptap/static-renderer 3.0.0-next.1 → 3.0.0-next.5

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.
Files changed (60) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +1 -1
  3. package/dist/index.cjs +573 -6
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +307 -32
  6. package/dist/index.d.ts +307 -32
  7. package/dist/index.js +552 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/json/html-string/index.cjs +16 -5
  10. package/dist/json/html-string/index.cjs.map +1 -1
  11. package/dist/json/html-string/index.d.cts +18 -22
  12. package/dist/json/html-string/index.d.ts +18 -22
  13. package/dist/json/html-string/index.js +10 -1
  14. package/dist/json/html-string/index.js.map +1 -1
  15. package/dist/json/react/index.cjs +13 -2202
  16. package/dist/json/react/index.cjs.map +1 -1
  17. package/dist/json/react/index.d.cts +5 -22
  18. package/dist/json/react/index.d.ts +5 -22
  19. package/dist/json/react/index.js +10 -2222
  20. package/dist/json/react/index.js.map +1 -1
  21. package/dist/json/renderer.cjs.map +1 -1
  22. package/dist/json/renderer.d.cts +5 -21
  23. package/dist/json/renderer.d.ts +5 -21
  24. package/dist/json/renderer.js.map +1 -1
  25. package/dist/pm/html-string/index.cjs +22 -37
  26. package/dist/pm/html-string/index.cjs.map +1 -1
  27. package/dist/pm/html-string/index.d.cts +7 -24
  28. package/dist/pm/html-string/index.d.ts +7 -24
  29. package/dist/pm/html-string/index.js +19 -34
  30. package/dist/pm/html-string/index.js.map +1 -1
  31. package/dist/pm/markdown/index.cjs +473 -0
  32. package/dist/pm/markdown/index.cjs.map +1 -0
  33. package/dist/pm/markdown/index.d.cts +153 -0
  34. package/dist/pm/markdown/index.d.ts +153 -0
  35. package/dist/pm/markdown/index.js +449 -0
  36. package/dist/pm/markdown/index.js.map +1 -0
  37. package/dist/pm/react/index.cjs +46 -2235
  38. package/dist/pm/react/index.cjs.map +1 -1
  39. package/dist/pm/react/index.d.cts +5 -23
  40. package/dist/pm/react/index.d.ts +5 -23
  41. package/dist/pm/react/index.js +51 -2263
  42. package/dist/pm/react/index.js.map +1 -1
  43. package/package.json +27 -8
  44. package/src/helpers.ts +5 -16
  45. package/src/index.ts +5 -1
  46. package/src/json/html-string/string.ts +39 -13
  47. package/src/json/react/{react.tsx → react.ts} +12 -15
  48. package/src/json/renderer.ts +50 -51
  49. package/src/pm/extensionRenderer.ts +16 -34
  50. package/src/pm/html-string/html-string.ts +29 -45
  51. package/src/pm/markdown/index.ts +2 -0
  52. package/src/pm/markdown/markdown.ts +142 -0
  53. package/src/pm/react/{react.tsx → react.ts} +50 -31
  54. package/src/helpers.example.ts +0 -35
  55. package/src/json/html-string/string.example.ts +0 -46
  56. package/src/json/react/react.example.ts +0 -45
  57. package/src/pm/html-string/html-string.example.ts +0 -225
  58. package/src/pm/markdown/markdown.example.ts +0 -296
  59. package/src/pm/react/react.example.tsx +0 -306
  60. package/src/types.ts +0 -57
@@ -18,8 +18,8 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/pm/html-string/index.ts
21
- var html_string_exports = {};
22
- __export(html_string_exports, {
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
23
  domOutputSpecToHTMLString: () => domOutputSpecToHTMLString,
24
24
  mapMarkExtensionToReactNode: () => mapMarkExtensionToReactNode,
25
25
  mapNodeExtensionToReactNode: () => mapNodeExtensionToReactNode,
@@ -28,7 +28,7 @@ __export(html_string_exports, {
28
28
  serializeAttrsToHTMLString: () => serializeAttrsToHTMLString,
29
29
  serializeChildrenToHTMLString: () => serializeChildrenToHTMLString
30
30
  });
31
- module.exports = __toCommonJS(html_string_exports);
31
+ module.exports = __toCommonJS(index_exports);
32
32
 
33
33
  // src/pm/extensionRenderer.ts
34
34
  var import_core2 = require("@tiptap/core");
@@ -42,7 +42,7 @@ function getAttributes(nodeOrMark, extensionAttributes, onlyRenderedAttributes)
42
42
  return {};
43
43
  }
44
44
  return extensionAttributes.filter((item) => {
45
- if (item.type !== nodeOrMark.type) {
45
+ if (item.type !== (typeof nodeOrMark.type === "string" ? nodeOrMark.type : nodeOrMark.type.name)) {
46
46
  return false;
47
47
  }
48
48
  if (onlyRenderedAttributes) {
@@ -72,11 +72,7 @@ function mapNodeExtensionToReactNode(domOutputSpecToElement, extension, extensio
72
72
  storage: extension.storage,
73
73
  parent: extension.parent
74
74
  };
75
- const renderToHTML = (0, import_core2.getExtensionField)(
76
- extension,
77
- "renderHTML",
78
- context
79
- );
75
+ const renderToHTML = (0, import_core2.getExtensionField)(extension, "renderHTML", context);
80
76
  if (!renderToHTML) {
81
77
  if (options == null ? void 0 : options.unhandledNode) {
82
78
  return [extension.name, options.unhandledNode];
@@ -116,11 +112,7 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
116
112
  storage: extension.storage,
117
113
  parent: extension.parent
118
114
  };
119
- const renderToHTML = (0, import_core2.getExtensionField)(
120
- extension,
121
- "renderHTML",
122
- context
123
- );
115
+ const renderToHTML = (0, import_core2.getExtensionField)(extension, "renderHTML", context);
124
116
  if (!renderToHTML) {
125
117
  if (options == null ? void 0 : options.unhandledMark) {
126
118
  return [extension.name, options.unhandledMark];
@@ -128,9 +120,7 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
128
120
  return [
129
121
  extension.name,
130
122
  () => {
131
- throw new Error(
132
- `Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`
133
- );
123
+ throw new Error(`Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`);
134
124
  }
135
125
  ];
136
126
  }
@@ -179,12 +169,9 @@ function renderToElement({
179
169
  return !(e.name in options.nodeMapping);
180
170
  }
181
171
  return true;
182
- }).map((nodeExtension) => mapNodeExtensionToReactNode(
183
- domOutputSpecToElement,
184
- nodeExtension,
185
- extensionAttributes,
186
- options
187
- ))
172
+ }).map(
173
+ (nodeExtension) => mapNodeExtensionToReactNode(domOutputSpecToElement, nodeExtension, extensionAttributes, options)
174
+ )
188
175
  ),
189
176
  ...mapDefinedTypes,
190
177
  ...options == null ? void 0 : options.nodeMapping
@@ -196,12 +183,7 @@ function renderToElement({
196
183
  return !(e.name in options.markMapping);
197
184
  }
198
185
  return true;
199
- }).map((mark) => mapMarkExtensionToReactNode(
200
- domOutputSpecToElement,
201
- mark,
202
- extensionAttributes,
203
- options
204
- ))
186
+ }).map((mark) => mapMarkExtensionToReactNode(domOutputSpecToElement, mark, extensionAttributes, options))
205
187
  ),
206
188
  ...options == null ? void 0 : options.markMapping
207
189
  }
@@ -275,21 +257,26 @@ function renderJSONContentToString(options) {
275
257
  return ctx.component(ctx.props);
276
258
  }, options);
277
259
  }
278
-
279
- // src/pm/html-string/html-string.ts
280
260
  function serializeAttrsToHTMLString(attrs) {
281
- const output = Object.entries(attrs).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" ");
261
+ const output = Object.entries(attrs || {}).map(([key, value]) => `${key.split(" ").at(-1)}=${JSON.stringify(value)}`).join(" ");
282
262
  return output ? ` ${output}` : "";
283
263
  }
284
264
  function serializeChildrenToHTMLString(children) {
285
265
  return [].concat(children || "").filter(Boolean).join("");
286
266
  }
267
+
268
+ // src/pm/html-string/html-string.ts
287
269
  function domOutputSpecToHTMLString(content) {
288
270
  if (typeof content === "string") {
289
271
  return () => content;
290
272
  }
291
273
  if (typeof content === "object" && "length" in content) {
292
- const [tag, attrs, children, ...rest] = content;
274
+ const [_tag, attrs, children, ...rest] = content;
275
+ let tag = _tag;
276
+ const parts = tag.split(" ");
277
+ if (parts.length > 1) {
278
+ tag = `${parts[1]} xmlns="${parts[0]}"`;
279
+ }
293
280
  if (attrs === void 0) {
294
281
  return () => `<${tag}/>`;
295
282
  }
@@ -310,15 +297,13 @@ function domOutputSpecToHTMLString(content) {
310
297
  return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`;
311
298
  }
312
299
  if (children === 0) {
313
- return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(
314
- child
315
- )}</${tag}>`;
300
+ return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`;
316
301
  }
317
302
  return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${[children].concat(rest).map((a) => domOutputSpecToHTMLString(a)(child)).join("")}</${tag}>`;
318
303
  }
319
304
  }
320
305
  throw new Error(
321
- "[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output",
306
+ "[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output or implement a node mapping",
322
307
  {
323
308
  cause: content
324
309
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/pm/html-string/index.ts","../../../src/pm/extensionRenderer.ts","../../../src/helpers.ts","../../../src/json/renderer.ts","../../../src/json/html-string/string.ts","../../../src/pm/html-string/html-string.ts"],"sourcesContent":["export * from '../extensionRenderer.js'\nexport * from './html-string.js'\n","/* eslint-disable no-plusplus */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport {\n ExtensionAttribute,\n Extensions,\n getAttributesFromExtensions,\n getExtensionField,\n getSchemaByResolvedExtensions,\n JSONContent,\n Mark as MarkExtension,\n MarkConfig,\n Node as NodeExtension,\n NodeConfig,\n resolveExtensions,\n splitExtensions,\n} from '@tiptap/core'\nimport { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\n\nimport { getHTMLAttributes } from '../helpers.js'\nimport { MarkProps, NodeProps, TiptapStaticRendererOptions } from '../json/renderer.js'\n\nexport type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T;\n\n/**\n * This takes a NodeExtension and maps it to a React component\n * @param extension The node extension to map to a React component\n * @param extensionAttributes All available extension attributes\n * @returns A tuple with the name of the extension and a React component that renders the extension\n */\nexport function mapNodeExtensionToReactNode<T>(\n domOutputSpecToElement: DomOutputSpecToElement<T>,\n extension: NodeExtension,\n extensionAttributes: ExtensionAttribute[],\n options?: Partial<Pick<TiptapStaticRendererOptions<T, Mark, Node>, 'unhandledNode'>>,\n): [string, (props: NodeProps<Node, T | T[]>) => T] {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n parent: extension.parent,\n }\n\n const renderToHTML = getExtensionField<NodeConfig['renderHTML']>(\n extension,\n 'renderHTML',\n context,\n )\n\n if (!renderToHTML) {\n if (options?.unhandledNode) {\n return [extension.name, options.unhandledNode]\n }\n return [\n extension.name,\n () => {\n throw new Error(\n `[tiptap error]: Node ${extension.name} cannot be rendered, it is missing a \"renderToHTML\" method, please implement it or override the corresponding \"nodeMapping\" method to have a custom rendering`,\n )\n },\n ]\n }\n\n return [\n extension.name,\n ({ node, children }) => {\n try {\n return domOutputSpecToElement(\n renderToHTML({\n node,\n HTMLAttributes: getHTMLAttributes(node, extensionAttributes),\n }),\n )(children)\n } catch (e) {\n throw new Error(\n `[tiptap error]: Node ${\n extension.name\n } cannot be rendered, it's \"renderToHTML\" method threw an error: ${(e as Error).message}`,\n { cause: e },\n )\n }\n },\n ]\n}\n\n/**\n * This takes a MarkExtension and maps it to a React component\n * @param extension The mark extension to map to a React component\n * @param extensionAttributes All available extension attributes\n * @returns A tuple with the name of the extension and a React component that renders the extension\n */\nexport function mapMarkExtensionToReactNode<T>(\n domOutputSpecToElement: DomOutputSpecToElement<T>,\n extension: MarkExtension,\n extensionAttributes: ExtensionAttribute[],\n options?: Partial<Pick<TiptapStaticRendererOptions<T, Mark, Node>, 'unhandledMark'>>,\n): [string, (props: MarkProps<Mark, T | T[]>) => T] {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n parent: extension.parent,\n }\n\n const renderToHTML = getExtensionField<MarkConfig['renderHTML']>(\n extension,\n 'renderHTML',\n context,\n )\n\n if (!renderToHTML) {\n if (options?.unhandledMark) {\n return [extension.name, options.unhandledMark]\n }\n return [\n extension.name,\n () => {\n throw new Error(\n `Node ${extension.name} cannot be rendered, it is missing a \"renderToHTML\" method`,\n )\n },\n ]\n }\n\n return [\n extension.name,\n ({ mark, children }) => {\n try {\n return domOutputSpecToElement(\n renderToHTML({\n mark,\n HTMLAttributes: getHTMLAttributes(mark, extensionAttributes),\n }),\n )(children)\n } catch (e) {\n throw new Error(\n `[tiptap error]: Mark ${\n extension.name\n } cannot be rendered, it's \"renderToHTML\" method threw an error: ${(e as Error).message}`,\n { cause: e },\n )\n }\n },\n ]\n}\n\n/**\n * This function will statically render a Prosemirror Node to a target element type using the given extensions\n * @param renderer The renderer to use to render the Prosemirror Node to the target element type\n * @param domOutputSpecToElement A function that takes a Prosemirror DOMOutputSpec and returns a function that takes children and returns the target element type\n * @param mapDefinedTypes An object with functions to map the doc and text types to the target element type\n * @param content The Prosemirror Node to render\n * @param extensions The extensions to use to render the Prosemirror Node\n * @param options Additional options to pass to the renderer that can override the default behavior\n * @returns The rendered target element type\n */\nexport function renderToElement<T>({\n renderer,\n domOutputSpecToElement,\n mapDefinedTypes,\n content,\n extensions,\n options,\n}: {\n renderer: (options: TiptapStaticRendererOptions<T, Mark, Node>) => (ctx: { content: Node }) => T;\n domOutputSpecToElement: DomOutputSpecToElement<T>;\n mapDefinedTypes: {\n doc: (props: NodeProps<Node, T | T[]>) => T;\n text: (props: NodeProps<Node, T | T[]>) => T;\n };\n content: Node | JSONContent;\n extensions: Extensions;\n options?: Partial<TiptapStaticRendererOptions<T, Mark, Node>>;\n}): T {\n // get all extensions in order & split them into nodes and marks\n extensions = resolveExtensions(extensions)\n const extensionAttributes = getAttributesFromExtensions(extensions)\n const { nodeExtensions, markExtensions } = splitExtensions(extensions)\n\n if (!(content instanceof Node)) {\n content = Node.fromJSON(getSchemaByResolvedExtensions(extensions), content)\n }\n\n return renderer({\n ...options,\n nodeMapping: {\n ...Object.fromEntries(\n nodeExtensions\n .filter(e => {\n if (e.name in mapDefinedTypes) {\n // These are predefined types that we don't need to map\n return false\n }\n // No need to generate mappings for nodes that are already mapped\n if (options?.nodeMapping) {\n return !(e.name in options.nodeMapping)\n }\n return true\n })\n .map(nodeExtension => mapNodeExtensionToReactNode<T>(\n domOutputSpecToElement,\n nodeExtension,\n extensionAttributes,\n options,\n )),\n ),\n ...mapDefinedTypes,\n ...options?.nodeMapping,\n },\n markMapping: {\n ...Object.fromEntries(\n markExtensions\n .filter(e => {\n // No need to generate mappings for marks that are already mapped\n if (options?.markMapping) {\n return !(e.name in options.markMapping)\n }\n return true\n })\n .map(mark => mapMarkExtensionToReactNode<T>(\n domOutputSpecToElement,\n mark,\n extensionAttributes,\n options,\n )),\n ),\n ...options?.markMapping,\n },\n })({ content })\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ExtensionAttribute, mergeAttributes } from '@tiptap/core'\n\nimport type { MarkType, NodeType } from './types'\n\n/**\n * This function returns the attributes of a node or mark that are defined by the given extension attributes.\n * @param nodeOrMark The node or mark to get the attributes from\n * @param extensionAttributes The extension attributes to use\n * @param onlyRenderedAttributes If true, only attributes that are rendered in the HTML are returned\n */\nexport function getAttributes(\n nodeOrMark: NodeType | MarkType,\n extensionAttributes: ExtensionAttribute[],\n onlyRenderedAttributes?: boolean,\n): Record<string, any> {\n const nodeOrMarkAttributes = nodeOrMark.attrs\n\n if (!nodeOrMarkAttributes) {\n return {}\n }\n\n return extensionAttributes\n .filter(item => {\n if (item.type !== nodeOrMark.type) {\n return false\n }\n if (onlyRenderedAttributes) {\n return item.attribute.rendered\n }\n return true\n })\n .map(item => {\n if (!item.attribute.renderHTML) {\n return {\n [item.name]:\n item.name in nodeOrMarkAttributes\n ? nodeOrMarkAttributes[item.name]\n : item.attribute.default,\n }\n }\n\n return (\n item.attribute.renderHTML(nodeOrMarkAttributes) || {\n [item.name]:\n item.name in nodeOrMarkAttributes\n ? nodeOrMarkAttributes[item.name]\n : item.attribute.default,\n }\n )\n })\n .reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {})\n}\n\n/**\n * This function returns the HTML attributes of a node or mark that are defined by the given extension attributes.\n * @param nodeOrMark The node or mark to get the attributes from\n * @param extensionAttributes The extension attributes to use\n */\nexport function getHTMLAttributes(\n nodeOrMark: NodeType | MarkType,\n extensionAttributes: ExtensionAttribute[],\n) {\n return getAttributes(nodeOrMark, extensionAttributes, true)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { MarkType, NodeType } from '../types'\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 (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => 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, TNodeRender>;\n /**\n * Mapping of mark types to react components\n */\n markMapping: Record<string, TMarkRender>;\n /**\n * Component to render if a node type is not handled\n */\n unhandledNode?: TNodeRender;\n /**\n * Component to render if a mark type is not handled\n */\n unhandledMark?: 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:(\ncb: (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 (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => 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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { MarkType, NodeType } from '../../types.js'\nimport { TiptapStaticRenderer, TiptapStaticRendererOptions } 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 */\nTMarkType extends { type: any } = MarkType,\n/**\n * A node type is either a JSON representation of a node or a Prosemirror node instance\n */\nTNodeType 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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Extensions, JSONContent } from '@tiptap/core'\nimport type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\n\nimport { renderJSONContentToString } from '../../json/html-string/string.js'\nimport { TiptapStaticRendererOptions } from '../../json/renderer.js'\nimport type { DOMOutputSpecArray } from '../../types.js'\nimport { renderToElement } from '../extensionRenderer.js'\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>): string {\n const output = Object.entries(attrs)\n .map(([key, value]) => `${key}=${JSON.stringify(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\n/**\n * Take a DOMOutputSpec and return a function that can render it to a string\n * @param content The DOMOutputSpec to convert to a string\n * @returns A function that can render the DOMOutputSpec to a string\n */\nexport function domOutputSpecToHTMLString(\n content: DOMOutputSpec,\n): (children?: string | string[]) => string {\n if (typeof content === 'string') {\n return () => content\n }\n if (typeof content === 'object' && 'length' in content) {\n const [tag, attrs, children, ...rest] = content as DOMOutputSpecArray\n\n if (attrs === undefined) {\n return () => `<${tag}/>`\n }\n if (attrs === 0) {\n return child => `<${tag}>${serializeChildrenToHTMLString(child)}</${tag}>`\n }\n if (typeof attrs === 'object') {\n if (Array.isArray(attrs)) {\n if (children === undefined) {\n return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`\n }\n if (children === 0) {\n return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`\n }\n return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}${[children]\n .concat(rest)\n .map(a => domOutputSpecToHTMLString(a)(child))}</${tag}>`\n }\n if (children === undefined) {\n return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`\n }\n if (children === 0) {\n return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(\n child,\n )}</${tag}>`\n }\n\n return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${[children]\n .concat(rest)\n .map(a => domOutputSpecToHTMLString(a)(child))\n .join('')}</${tag}>`\n }\n }\n\n // TODO support DOM elements? How to handle them?\n throw new Error(\n '[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output',\n {\n cause: content,\n },\n )\n}\n\n/**\n * This function will statically render a Prosemirror Node to HTML using the provided extensions and options\n * @param content The content to render to HTML\n * @param extensions The extensions to use for rendering\n * @param options The options to use for rendering\n * @returns The rendered HTML string\n */\nexport function renderToHTMLString({\n content,\n extensions,\n options,\n}: {\n content: Node | JSONContent;\n extensions: Extensions;\n options?: Partial<TiptapStaticRendererOptions<string, Mark, Node>>;\n}): string {\n return renderToElement<string>({\n renderer: renderJSONContentToString,\n domOutputSpecToElement: domOutputSpecToHTMLString,\n mapDefinedTypes: {\n // Map a doc node to concatenated children\n doc: ({ children }) => serializeChildrenToHTMLString(children),\n // Map a text node to its text content\n text: ({ node }) => node.text ?? '',\n },\n content,\n extensions,\n options,\n })\n}\n"],"mappings":"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","names":["import_core","_a"]}
1
+ {"version":3,"sources":["../../../src/pm/html-string/index.ts","../../../src/pm/extensionRenderer.ts","../../../src/helpers.ts","../../../src/json/renderer.ts","../../../src/json/html-string/string.ts","../../../src/pm/html-string/html-string.ts"],"sourcesContent":["export * from '../extensionRenderer.js'\nexport * from './html-string.js'\n","/* eslint-disable no-plusplus */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport {\n ExtensionAttribute,\n Extensions,\n getAttributesFromExtensions,\n getExtensionField,\n getSchemaByResolvedExtensions,\n JSONContent,\n Mark as MarkExtension,\n MarkConfig,\n Node as NodeExtension,\n NodeConfig,\n resolveExtensions,\n splitExtensions,\n} from '@tiptap/core'\nimport { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\n\nimport { getHTMLAttributes } from '../helpers.js'\nimport { MarkProps, NodeProps, TiptapStaticRendererOptions } from '../json/renderer.js'\n\nexport type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T\n\n/**\n * This takes a NodeExtension and maps it to a React component\n * @param extension The node extension to map to a React component\n * @param extensionAttributes All available extension attributes\n * @returns A tuple with the name of the extension and a React component that renders the extension\n */\nexport function mapNodeExtensionToReactNode<T>(\n domOutputSpecToElement: DomOutputSpecToElement<T>,\n extension: NodeExtension,\n extensionAttributes: ExtensionAttribute[],\n options?: Partial<Pick<TiptapStaticRendererOptions<T, Mark, Node>, 'unhandledNode'>>,\n): [string, (props: NodeProps<Node, T | T[]>) => T] {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n parent: extension.parent,\n }\n\n const renderToHTML = getExtensionField<NodeConfig['renderHTML']>(extension, 'renderHTML', context)\n\n if (!renderToHTML) {\n if (options?.unhandledNode) {\n return [extension.name, options.unhandledNode]\n }\n return [\n extension.name,\n () => {\n throw new Error(\n `[tiptap error]: Node ${extension.name} cannot be rendered, it is missing a \"renderToHTML\" method, please implement it or override the corresponding \"nodeMapping\" method to have a custom rendering`,\n )\n },\n ]\n }\n\n return [\n extension.name,\n ({ node, children }) => {\n try {\n return domOutputSpecToElement(\n renderToHTML({\n node,\n HTMLAttributes: getHTMLAttributes(node, extensionAttributes),\n }),\n )(children)\n } catch (e) {\n throw new Error(\n `[tiptap error]: Node ${\n extension.name\n } cannot be rendered, it's \"renderToHTML\" method threw an error: ${(e as Error).message}`,\n { cause: e },\n )\n }\n },\n ]\n}\n\n/**\n * This takes a MarkExtension and maps it to a React component\n * @param extension The mark extension to map to a React component\n * @param extensionAttributes All available extension attributes\n * @returns A tuple with the name of the extension and a React component that renders the extension\n */\nexport function mapMarkExtensionToReactNode<T>(\n domOutputSpecToElement: DomOutputSpecToElement<T>,\n extension: MarkExtension,\n extensionAttributes: ExtensionAttribute[],\n options?: Partial<Pick<TiptapStaticRendererOptions<T, Mark, Node>, 'unhandledMark'>>,\n): [string, (props: MarkProps<Mark, T | T[]>) => T] {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n parent: extension.parent,\n }\n\n const renderToHTML = getExtensionField<MarkConfig['renderHTML']>(extension, 'renderHTML', context)\n\n if (!renderToHTML) {\n if (options?.unhandledMark) {\n return [extension.name, options.unhandledMark]\n }\n return [\n extension.name,\n () => {\n throw new Error(`Node ${extension.name} cannot be rendered, it is missing a \"renderToHTML\" method`)\n },\n ]\n }\n\n return [\n extension.name,\n ({ mark, children }) => {\n try {\n return domOutputSpecToElement(\n renderToHTML({\n mark,\n HTMLAttributes: getHTMLAttributes(mark, extensionAttributes),\n }),\n )(children)\n } catch (e) {\n throw new Error(\n `[tiptap error]: Mark ${\n extension.name\n } cannot be rendered, it's \"renderToHTML\" method threw an error: ${(e as Error).message}`,\n { cause: e },\n )\n }\n },\n ]\n}\n\n/**\n * This function will statically render a Prosemirror Node to a target element type using the given extensions\n * @param renderer The renderer to use to render the Prosemirror Node to the target element type\n * @param domOutputSpecToElement A function that takes a Prosemirror DOMOutputSpec and returns a function that takes children and returns the target element type\n * @param mapDefinedTypes An object with functions to map the doc and text types to the target element type\n * @param content The Prosemirror Node to render\n * @param extensions The extensions to use to render the Prosemirror Node\n * @param options Additional options to pass to the renderer that can override the default behavior\n * @returns The rendered target element type\n */\nexport function renderToElement<T>({\n renderer,\n domOutputSpecToElement,\n mapDefinedTypes,\n content,\n extensions,\n options,\n}: {\n renderer: (options: TiptapStaticRendererOptions<T, Mark, Node>) => (ctx: { content: Node }) => T\n domOutputSpecToElement: DomOutputSpecToElement<T>\n mapDefinedTypes: {\n doc: (props: NodeProps<Node, T | T[]>) => T\n text: (props: NodeProps<Node, T | T[]>) => T\n }\n content: Node | JSONContent\n extensions: Extensions\n options?: Partial<TiptapStaticRendererOptions<T, Mark, Node>>\n}): T {\n // get all extensions in order & split them into nodes and marks\n extensions = resolveExtensions(extensions)\n const extensionAttributes = getAttributesFromExtensions(extensions)\n const { nodeExtensions, markExtensions } = splitExtensions(extensions)\n\n if (!(content instanceof Node)) {\n content = Node.fromJSON(getSchemaByResolvedExtensions(extensions), content)\n }\n\n return renderer({\n ...options,\n nodeMapping: {\n ...Object.fromEntries(\n nodeExtensions\n .filter(e => {\n if (e.name in mapDefinedTypes) {\n // These are predefined types that we don't need to map\n return false\n }\n // No need to generate mappings for nodes that are already mapped\n if (options?.nodeMapping) {\n return !(e.name in options.nodeMapping)\n }\n return true\n })\n .map(nodeExtension =>\n mapNodeExtensionToReactNode<T>(domOutputSpecToElement, nodeExtension, extensionAttributes, options),\n ),\n ),\n ...mapDefinedTypes,\n ...options?.nodeMapping,\n },\n markMapping: {\n ...Object.fromEntries(\n markExtensions\n .filter(e => {\n // No need to generate mappings for marks that are already mapped\n if (options?.markMapping) {\n return !(e.name in options.markMapping)\n }\n return true\n })\n .map(mark => mapMarkExtensionToReactNode<T>(domOutputSpecToElement, mark, extensionAttributes, options)),\n ),\n ...options?.markMapping,\n },\n })({ content })\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { type ExtensionAttribute, type MarkType, type NodeType, mergeAttributes } from '@tiptap/core'\n\n/**\n * This function returns the attributes of a node or mark that are defined by the given extension attributes.\n * @param nodeOrMark The node or mark to get the attributes from\n * @param extensionAttributes The extension attributes to use\n * @param onlyRenderedAttributes If true, only attributes that are rendered in the HTML are returned\n */\nexport function getAttributes(\n nodeOrMark: NodeType | MarkType,\n extensionAttributes: ExtensionAttribute[],\n onlyRenderedAttributes?: boolean,\n): Record<string, any> {\n const nodeOrMarkAttributes = nodeOrMark.attrs\n\n if (!nodeOrMarkAttributes) {\n return {}\n }\n\n return extensionAttributes\n .filter(item => {\n if (item.type !== (typeof nodeOrMark.type === 'string' ? nodeOrMark.type : nodeOrMark.type.name)) {\n return false\n }\n if (onlyRenderedAttributes) {\n return item.attribute.rendered\n }\n return true\n })\n .map(item => {\n if (!item.attribute.renderHTML) {\n return {\n [item.name]: item.name in nodeOrMarkAttributes ? nodeOrMarkAttributes[item.name] : item.attribute.default,\n }\n }\n\n return (\n item.attribute.renderHTML(nodeOrMarkAttributes) || {\n [item.name]: item.name in nodeOrMarkAttributes ? nodeOrMarkAttributes[item.name] : item.attribute.default,\n }\n )\n })\n .reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {})\n}\n\n/**\n * This function returns the HTML attributes of a node or mark that are defined by the given extension attributes.\n * @param nodeOrMark The node or mark to get the attributes from\n * @param extensionAttributes The extension attributes to use\n */\nexport function getHTMLAttributes(nodeOrMark: NodeType | MarkType, extensionAttributes: ExtensionAttribute[]) {\n return getAttributes(nodeOrMark, extensionAttributes, true)\n}\n","/* eslint-disable @typescript-eslint/no-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 (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => 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 (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => 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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { MarkType, NodeType } from '@tiptap/core'\n\nimport { TiptapStaticRenderer, TiptapStaticRendererOptions } 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 * 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 const output = Object.entries(attrs || {})\n .map(([key, value]) => `${key.split(' ').at(-1)}=${JSON.stringify(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","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'\nimport type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\n\nimport {\n renderJSONContentToString,\n serializeAttrsToHTMLString,\n serializeChildrenToHTMLString,\n} from '../../json/html-string/string.js'\nimport { TiptapStaticRendererOptions } from '../../json/renderer.js'\nimport { renderToElement } from '../extensionRenderer.js'\n\nexport { serializeAttrsToHTMLString, serializeChildrenToHTMLString } from '../../json/html-string/string.js'\n\n/**\n * Take a DOMOutputSpec and return a function that can render it to a string\n * @param content The DOMOutputSpec to convert to a string\n * @returns A function that can render the DOMOutputSpec to a string\n */\nexport function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: string | string[]) => string {\n if (typeof content === 'string') {\n return () => content\n }\n if (typeof content === 'object' && 'length' in content) {\n const [_tag, attrs, children, ...rest] = content as DOMOutputSpecArray\n let tag = _tag\n const parts = tag.split(' ')\n\n if (parts.length > 1) {\n tag = `${parts[1]} xmlns=\"${parts[0]}\"`\n }\n\n if (attrs === undefined) {\n return () => `<${tag}/>`\n }\n if (attrs === 0) {\n return child => `<${tag}>${serializeChildrenToHTMLString(child)}</${tag}>`\n }\n if (typeof attrs === 'object') {\n if (Array.isArray(attrs)) {\n if (children === undefined) {\n return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`\n }\n if (children === 0) {\n return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`\n }\n return child =>\n `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}${[children]\n .concat(rest)\n .map(a => domOutputSpecToHTMLString(a)(child))}</${tag}>`\n }\n if (children === undefined) {\n return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`\n }\n if (children === 0) {\n return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`\n }\n\n return child =>\n `<${tag}${serializeAttrsToHTMLString(attrs)}>${[children]\n .concat(rest)\n .map(a => domOutputSpecToHTMLString(a)(child))\n .join('')}</${tag}>`\n }\n }\n\n // TODO support DOM elements? How to handle them?\n throw new Error(\n '[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output or implement a node mapping',\n {\n cause: content,\n },\n )\n}\n\n/**\n * This function will statically render a Prosemirror Node to HTML using the provided extensions and options\n * @param content The content to render to HTML\n * @param extensions The extensions to use for rendering\n * @param options The options to use for rendering\n * @returns The rendered HTML string\n */\nexport function renderToHTMLString({\n content,\n extensions,\n options,\n}: {\n content: Node | JSONContent\n extensions: Extensions\n options?: Partial<TiptapStaticRendererOptions<string, Mark, Node>>\n}): string {\n return renderToElement<string>({\n renderer: renderJSONContentToString,\n domOutputSpecToElement: domOutputSpecToHTMLString,\n mapDefinedTypes: {\n // Map a doc node to concatenated children\n doc: ({ children }) => serializeChildrenToHTMLString(children),\n // Map a text node to its text content\n text: ({ node }) => node.text ?? '',\n },\n content,\n extensions,\n options,\n })\n}\n"],"mappings":"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","names":["import_core","_a"]}
@@ -1,24 +1,6 @@
1
- import { Node, ExtensionAttribute, Mark as Mark$1, JSONContent, Extensions } from '@tiptap/core';
1
+ import { MarkType, NodeType, Node, ExtensionAttribute, Mark as Mark$1, JSONContent, Extensions } from '@tiptap/core';
2
2
  import { DOMOutputSpec, Mark, Node as Node$1 } from '@tiptap/pm/model';
3
3
 
4
- /**
5
- * A mark type is either a JSON representation of a mark or a Prosemirror mark instance
6
- */
7
- type MarkType<Type extends string = any, Attributes extends undefined | Record<string, any> = any> = {
8
- type: Type;
9
- attrs: Attributes;
10
- };
11
- /**
12
- * A node type is either a JSON representation of a node or a Prosemirror node instance
13
- */
14
- type NodeType<Type extends string = any, Attributes extends undefined | Record<string, any> = any, NodeMarkType extends MarkType = any, Content extends NodeType[] = any> = {
15
- type: Type;
16
- attrs: Attributes;
17
- content?: Content;
18
- marks?: NodeMarkType[];
19
- text?: string;
20
- };
21
-
22
4
  /**
23
5
  * Props for a node renderer
24
6
  */
@@ -104,19 +86,19 @@ TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNod
104
86
  /**
105
87
  * Mapping of node types to react components
106
88
  */
107
- nodeMapping: Record<string, TNodeRender>;
89
+ nodeMapping: Record<string, NoInfer<TNodeRender>>;
108
90
  /**
109
91
  * Mapping of mark types to react components
110
92
  */
111
- markMapping: Record<string, TMarkRender>;
93
+ markMapping: Record<string, NoInfer<TMarkRender>>;
112
94
  /**
113
95
  * Component to render if a node type is not handled
114
96
  */
115
- unhandledNode?: TNodeRender;
97
+ unhandledNode?: NoInfer<TNodeRender>;
116
98
  /**
117
99
  * Component to render if a mark type is not handled
118
100
  */
119
- unhandledMark?: TMarkRender;
101
+ unhandledMark?: NoInfer<TMarkRender>;
120
102
  };
121
103
 
122
104
  type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T;
@@ -163,13 +145,14 @@ declare function renderToElement<T>({ renderer, domOutputSpecToElement, mapDefin
163
145
  * @param attrs The attributes to serialize
164
146
  * @returns The serialized attributes as a string
165
147
  */
166
- declare function serializeAttrsToHTMLString(attrs: Record<string, any>): string;
148
+ declare function serializeAttrsToHTMLString(attrs: Record<string, any> | undefined | null): string;
167
149
  /**
168
150
  * Serialize the children of a node or mark to a string
169
151
  * @param children The children to serialize
170
152
  * @returns The serialized children as a string
171
153
  */
172
154
  declare function serializeChildrenToHTMLString(children?: string | string[]): string;
155
+
173
156
  /**
174
157
  * Take a DOMOutputSpec and return a function that can render it to a string
175
158
  * @param content The DOMOutputSpec to convert to a string
@@ -1,24 +1,6 @@
1
- import { Node, ExtensionAttribute, Mark as Mark$1, JSONContent, Extensions } from '@tiptap/core';
1
+ import { MarkType, NodeType, Node, ExtensionAttribute, Mark as Mark$1, JSONContent, Extensions } from '@tiptap/core';
2
2
  import { DOMOutputSpec, Mark, Node as Node$1 } from '@tiptap/pm/model';
3
3
 
4
- /**
5
- * A mark type is either a JSON representation of a mark or a Prosemirror mark instance
6
- */
7
- type MarkType<Type extends string = any, Attributes extends undefined | Record<string, any> = any> = {
8
- type: Type;
9
- attrs: Attributes;
10
- };
11
- /**
12
- * A node type is either a JSON representation of a node or a Prosemirror node instance
13
- */
14
- type NodeType<Type extends string = any, Attributes extends undefined | Record<string, any> = any, NodeMarkType extends MarkType = any, Content extends NodeType[] = any> = {
15
- type: Type;
16
- attrs: Attributes;
17
- content?: Content;
18
- marks?: NodeMarkType[];
19
- text?: string;
20
- };
21
-
22
4
  /**
23
5
  * Props for a node renderer
24
6
  */
@@ -104,19 +86,19 @@ TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNod
104
86
  /**
105
87
  * Mapping of node types to react components
106
88
  */
107
- nodeMapping: Record<string, TNodeRender>;
89
+ nodeMapping: Record<string, NoInfer<TNodeRender>>;
108
90
  /**
109
91
  * Mapping of mark types to react components
110
92
  */
111
- markMapping: Record<string, TMarkRender>;
93
+ markMapping: Record<string, NoInfer<TMarkRender>>;
112
94
  /**
113
95
  * Component to render if a node type is not handled
114
96
  */
115
- unhandledNode?: TNodeRender;
97
+ unhandledNode?: NoInfer<TNodeRender>;
116
98
  /**
117
99
  * Component to render if a mark type is not handled
118
100
  */
119
- unhandledMark?: TMarkRender;
101
+ unhandledMark?: NoInfer<TMarkRender>;
120
102
  };
121
103
 
122
104
  type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T;
@@ -163,13 +145,14 @@ declare function renderToElement<T>({ renderer, domOutputSpecToElement, mapDefin
163
145
  * @param attrs The attributes to serialize
164
146
  * @returns The serialized attributes as a string
165
147
  */
166
- declare function serializeAttrsToHTMLString(attrs: Record<string, any>): string;
148
+ declare function serializeAttrsToHTMLString(attrs: Record<string, any> | undefined | null): string;
167
149
  /**
168
150
  * Serialize the children of a node or mark to a string
169
151
  * @param children The children to serialize
170
152
  * @returns The serialized children as a string
171
153
  */
172
154
  declare function serializeChildrenToHTMLString(children?: string | string[]): string;
155
+
173
156
  /**
174
157
  * Take a DOMOutputSpec and return a function that can render it to a string
175
158
  * @param content The DOMOutputSpec to convert to a string
@@ -16,7 +16,7 @@ function getAttributes(nodeOrMark, extensionAttributes, onlyRenderedAttributes)
16
16
  return {};
17
17
  }
18
18
  return extensionAttributes.filter((item) => {
19
- if (item.type !== nodeOrMark.type) {
19
+ if (item.type !== (typeof nodeOrMark.type === "string" ? nodeOrMark.type : nodeOrMark.type.name)) {
20
20
  return false;
21
21
  }
22
22
  if (onlyRenderedAttributes) {
@@ -46,11 +46,7 @@ function mapNodeExtensionToReactNode(domOutputSpecToElement, extension, extensio
46
46
  storage: extension.storage,
47
47
  parent: extension.parent
48
48
  };
49
- const renderToHTML = getExtensionField(
50
- extension,
51
- "renderHTML",
52
- context
53
- );
49
+ const renderToHTML = getExtensionField(extension, "renderHTML", context);
54
50
  if (!renderToHTML) {
55
51
  if (options == null ? void 0 : options.unhandledNode) {
56
52
  return [extension.name, options.unhandledNode];
@@ -90,11 +86,7 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
90
86
  storage: extension.storage,
91
87
  parent: extension.parent
92
88
  };
93
- const renderToHTML = getExtensionField(
94
- extension,
95
- "renderHTML",
96
- context
97
- );
89
+ const renderToHTML = getExtensionField(extension, "renderHTML", context);
98
90
  if (!renderToHTML) {
99
91
  if (options == null ? void 0 : options.unhandledMark) {
100
92
  return [extension.name, options.unhandledMark];
@@ -102,9 +94,7 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
102
94
  return [
103
95
  extension.name,
104
96
  () => {
105
- throw new Error(
106
- `Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`
107
- );
97
+ throw new Error(`Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`);
108
98
  }
109
99
  ];
110
100
  }
@@ -153,12 +143,9 @@ function renderToElement({
153
143
  return !(e.name in options.nodeMapping);
154
144
  }
155
145
  return true;
156
- }).map((nodeExtension) => mapNodeExtensionToReactNode(
157
- domOutputSpecToElement,
158
- nodeExtension,
159
- extensionAttributes,
160
- options
161
- ))
146
+ }).map(
147
+ (nodeExtension) => mapNodeExtensionToReactNode(domOutputSpecToElement, nodeExtension, extensionAttributes, options)
148
+ )
162
149
  ),
163
150
  ...mapDefinedTypes,
164
151
  ...options == null ? void 0 : options.nodeMapping
@@ -170,12 +157,7 @@ function renderToElement({
170
157
  return !(e.name in options.markMapping);
171
158
  }
172
159
  return true;
173
- }).map((mark) => mapMarkExtensionToReactNode(
174
- domOutputSpecToElement,
175
- mark,
176
- extensionAttributes,
177
- options
178
- ))
160
+ }).map((mark) => mapMarkExtensionToReactNode(domOutputSpecToElement, mark, extensionAttributes, options))
179
161
  ),
180
162
  ...options == null ? void 0 : options.markMapping
181
163
  }
@@ -249,21 +231,26 @@ function renderJSONContentToString(options) {
249
231
  return ctx.component(ctx.props);
250
232
  }, options);
251
233
  }
252
-
253
- // src/pm/html-string/html-string.ts
254
234
  function serializeAttrsToHTMLString(attrs) {
255
- const output = Object.entries(attrs).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" ");
235
+ const output = Object.entries(attrs || {}).map(([key, value]) => `${key.split(" ").at(-1)}=${JSON.stringify(value)}`).join(" ");
256
236
  return output ? ` ${output}` : "";
257
237
  }
258
238
  function serializeChildrenToHTMLString(children) {
259
239
  return [].concat(children || "").filter(Boolean).join("");
260
240
  }
241
+
242
+ // src/pm/html-string/html-string.ts
261
243
  function domOutputSpecToHTMLString(content) {
262
244
  if (typeof content === "string") {
263
245
  return () => content;
264
246
  }
265
247
  if (typeof content === "object" && "length" in content) {
266
- const [tag, attrs, children, ...rest] = content;
248
+ const [_tag, attrs, children, ...rest] = content;
249
+ let tag = _tag;
250
+ const parts = tag.split(" ");
251
+ if (parts.length > 1) {
252
+ tag = `${parts[1]} xmlns="${parts[0]}"`;
253
+ }
267
254
  if (attrs === void 0) {
268
255
  return () => `<${tag}/>`;
269
256
  }
@@ -284,15 +271,13 @@ function domOutputSpecToHTMLString(content) {
284
271
  return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`;
285
272
  }
286
273
  if (children === 0) {
287
- return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(
288
- child
289
- )}</${tag}>`;
274
+ return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`;
290
275
  }
291
276
  return (child) => `<${tag}${serializeAttrsToHTMLString(attrs)}>${[children].concat(rest).map((a) => domOutputSpecToHTMLString(a)(child)).join("")}</${tag}>`;
292
277
  }
293
278
  }
294
279
  throw new Error(
295
- "[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output",
280
+ "[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output or implement a node mapping",
296
281
  {
297
282
  cause: content
298
283
  }