@tiptap/static-renderer 3.27.1 → 3.27.3
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 +132 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +133 -10
- package/dist/index.js.map +1 -1
- package/dist/json/html-string/index.cjs.map +1 -1
- package/dist/json/html-string/index.d.cts +14 -2
- package/dist/json/html-string/index.d.ts +14 -2
- package/dist/json/html-string/index.js.map +1 -1
- package/dist/json/react/index.cjs.map +1 -1
- package/dist/json/react/index.d.cts +14 -2
- package/dist/json/react/index.d.ts +14 -2
- package/dist/json/react/index.js.map +1 -1
- package/dist/json/renderer.cjs.map +1 -1
- package/dist/json/renderer.d.cts +14 -2
- package/dist/json/renderer.d.ts +14 -2
- package/dist/json/renderer.js.map +1 -1
- package/dist/pm/html-string/index.cjs +132 -9
- package/dist/pm/html-string/index.cjs.map +1 -1
- package/dist/pm/html-string/index.d.cts +14 -2
- package/dist/pm/html-string/index.d.ts +14 -2
- package/dist/pm/html-string/index.js +133 -10
- package/dist/pm/html-string/index.js.map +1 -1
- package/dist/pm/markdown/index.cjs +132 -9
- package/dist/pm/markdown/index.cjs.map +1 -1
- package/dist/pm/markdown/index.d.cts +14 -2
- package/dist/pm/markdown/index.d.ts +14 -2
- package/dist/pm/markdown/index.js +133 -10
- package/dist/pm/markdown/index.js.map +1 -1
- package/dist/pm/react/index.cjs +132 -9
- package/dist/pm/react/index.cjs.map +1 -1
- package/dist/pm/react/index.d.cts +14 -2
- package/dist/pm/react/index.d.ts +14 -2
- package/dist/pm/react/index.js +133 -10
- package/dist/pm/react/index.js.map +1 -1
- package/package.json +8 -8
- package/src/json/renderer.ts +14 -2
- package/src/pm/extensionRenderer.ts +217 -10
package/dist/pm/react/index.cjs
CHANGED
|
@@ -164,6 +164,121 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
|
|
|
164
164
|
}
|
|
165
165
|
];
|
|
166
166
|
}
|
|
167
|
+
var UNHANDLED_NODE_TYPE = "__tiptapUnhandledNode__";
|
|
168
|
+
var UNHANDLED_MARK_TYPE = "__tiptapUnhandledMark__";
|
|
169
|
+
var ORIGINAL_TYPE_ATTR = "__originalType";
|
|
170
|
+
var ORIGINAL_ATTRS_ATTR = "__originalAttrs";
|
|
171
|
+
var placeholderAttrs = {
|
|
172
|
+
[ORIGINAL_TYPE_ATTR]: { default: "" },
|
|
173
|
+
[ORIGINAL_ATTRS_ATTR]: { default: {} }
|
|
174
|
+
};
|
|
175
|
+
function hasUnknownType(content, schema) {
|
|
176
|
+
let found = false;
|
|
177
|
+
const visit = (node) => {
|
|
178
|
+
var _a, _b;
|
|
179
|
+
if (found) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (node.type && !(node.type in schema.nodes)) {
|
|
183
|
+
found = true;
|
|
184
|
+
}
|
|
185
|
+
(_a = node.marks) == null ? void 0 : _a.forEach((mark) => {
|
|
186
|
+
if (mark.type && !(mark.type in schema.marks)) {
|
|
187
|
+
found = true;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
(_b = node.content) == null ? void 0 : _b.forEach(visit);
|
|
191
|
+
};
|
|
192
|
+
visit(content);
|
|
193
|
+
return found;
|
|
194
|
+
}
|
|
195
|
+
function substituteUnknownTypes(content, schema, options) {
|
|
196
|
+
const canSubstituteNode = Boolean(options == null ? void 0 : options.unhandledNode);
|
|
197
|
+
const canSubstituteMark = Boolean(options == null ? void 0 : options.unhandledMark);
|
|
198
|
+
const substituteMark = (mark) => {
|
|
199
|
+
var _a;
|
|
200
|
+
return canSubstituteMark && !(mark.type in schema.marks) ? {
|
|
201
|
+
type: UNHANDLED_MARK_TYPE,
|
|
202
|
+
attrs: { [ORIGINAL_TYPE_ATTR]: mark.type, [ORIGINAL_ATTRS_ATTR]: (_a = mark.attrs) != null ? _a : {} }
|
|
203
|
+
} : mark;
|
|
204
|
+
};
|
|
205
|
+
const isUnknownNode = (node) => canSubstituteNode && node.type != null && !(node.type in schema.nodes);
|
|
206
|
+
const toPlaceholder = (node, rewritten) => {
|
|
207
|
+
var _a;
|
|
208
|
+
return {
|
|
209
|
+
...rewritten,
|
|
210
|
+
type: UNHANDLED_NODE_TYPE,
|
|
211
|
+
attrs: { [ORIGINAL_TYPE_ATTR]: node.type, [ORIGINAL_ATTRS_ATTR]: (_a = node.attrs) != null ? _a : {} }
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
const substituteNode = (node) => {
|
|
215
|
+
var _a, _b;
|
|
216
|
+
const rewritten = {
|
|
217
|
+
...node,
|
|
218
|
+
marks: (_a = node.marks) == null ? void 0 : _a.map(substituteMark),
|
|
219
|
+
content: (_b = node.content) == null ? void 0 : _b.map(substituteNode)
|
|
220
|
+
};
|
|
221
|
+
return isUnknownNode(node) ? toPlaceholder(node, rewritten) : rewritten;
|
|
222
|
+
};
|
|
223
|
+
return substituteNode(content);
|
|
224
|
+
}
|
|
225
|
+
function withPlaceholderTypes(schema) {
|
|
226
|
+
return new import_model.Schema({
|
|
227
|
+
topNode: schema.spec.topNode,
|
|
228
|
+
nodes: schema.spec.nodes.addToEnd(UNHANDLED_NODE_TYPE, { attrs: placeholderAttrs }),
|
|
229
|
+
marks: schema.spec.marks.addToEnd(UNHANDLED_MARK_TYPE, { attrs: placeholderAttrs })
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function resolveRenderContent(content, extensions, options) {
|
|
233
|
+
if (content instanceof import_model.Node) {
|
|
234
|
+
return content;
|
|
235
|
+
}
|
|
236
|
+
const schema = (0, import_core2.getSchemaByResolvedExtensions)(extensions);
|
|
237
|
+
if (!hasUnknownType(content, schema)) {
|
|
238
|
+
return import_model.Node.fromJSON(schema, content);
|
|
239
|
+
}
|
|
240
|
+
return import_model.Node.fromJSON(
|
|
241
|
+
withPlaceholderTypes(schema),
|
|
242
|
+
substituteUnknownTypes(content, schema, options)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
function unwrapPlaceholderJSON(json) {
|
|
246
|
+
return json.type === UNHANDLED_NODE_TYPE || json.type === UNHANDLED_MARK_TYPE ? { ...json, type: json.attrs[ORIGINAL_TYPE_ATTR], attrs: json.attrs[ORIGINAL_ATTRS_ATTR] } : json;
|
|
247
|
+
}
|
|
248
|
+
function restoreOriginalJSON(json) {
|
|
249
|
+
var _a, _b;
|
|
250
|
+
const node = unwrapPlaceholderJSON(json);
|
|
251
|
+
return {
|
|
252
|
+
...node,
|
|
253
|
+
marks: (_a = node.marks) == null ? void 0 : _a.map(
|
|
254
|
+
(mark) => unwrapPlaceholderJSON(mark)
|
|
255
|
+
),
|
|
256
|
+
content: (_b = node.content) == null ? void 0 : _b.map(restoreOriginalJSON)
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function withOriginalIdentity(target) {
|
|
260
|
+
const overrides = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
261
|
+
type: { name: target.attrs[ORIGINAL_TYPE_ATTR] },
|
|
262
|
+
attrs: target.attrs[ORIGINAL_ATTRS_ATTR],
|
|
263
|
+
toJSON: () => restoreOriginalJSON(target.toJSON())
|
|
264
|
+
});
|
|
265
|
+
return new Proxy(target, {
|
|
266
|
+
get(node, prop) {
|
|
267
|
+
const override = overrides[prop];
|
|
268
|
+
if (override !== void 0) {
|
|
269
|
+
return override;
|
|
270
|
+
}
|
|
271
|
+
const value = node[prop];
|
|
272
|
+
return typeof value === "function" ? value.bind(node) : value;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function placeholderNodeRenderer(unhandledNode) {
|
|
277
|
+
return (props) => unhandledNode({ ...props, node: withOriginalIdentity(props.node) });
|
|
278
|
+
}
|
|
279
|
+
function placeholderMarkRenderer(unhandledMark) {
|
|
280
|
+
return (props) => unhandledMark({ ...props, mark: withOriginalIdentity(props.mark) });
|
|
281
|
+
}
|
|
167
282
|
function renderToElement({
|
|
168
283
|
renderer,
|
|
169
284
|
domOutputSpecToElement,
|
|
@@ -175,9 +290,13 @@ function renderToElement({
|
|
|
175
290
|
extensions = (0, import_core2.resolveExtensions)(extensions);
|
|
176
291
|
const extensionAttributes = (0, import_core2.getAttributesFromExtensions)(extensions);
|
|
177
292
|
const { nodeExtensions, markExtensions } = (0, import_core2.splitExtensions)(extensions);
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
293
|
+
const {
|
|
294
|
+
unhandledNode,
|
|
295
|
+
unhandledMark,
|
|
296
|
+
nodeMapping: userNodeMapping,
|
|
297
|
+
markMapping: userMarkMapping
|
|
298
|
+
} = options != null ? options : {};
|
|
299
|
+
content = resolveRenderContent(content, extensions, options);
|
|
181
300
|
return renderer({
|
|
182
301
|
...options,
|
|
183
302
|
nodeMapping: {
|
|
@@ -186,8 +305,8 @@ function renderToElement({
|
|
|
186
305
|
if (e.name in mapDefinedTypes) {
|
|
187
306
|
return false;
|
|
188
307
|
}
|
|
189
|
-
if (
|
|
190
|
-
return !(e.name in
|
|
308
|
+
if (userNodeMapping) {
|
|
309
|
+
return !(e.name in userNodeMapping);
|
|
191
310
|
}
|
|
192
311
|
return true;
|
|
193
312
|
}).map(
|
|
@@ -200,13 +319,15 @@ function renderToElement({
|
|
|
200
319
|
)
|
|
201
320
|
),
|
|
202
321
|
...mapDefinedTypes,
|
|
203
|
-
...
|
|
322
|
+
...userNodeMapping,
|
|
323
|
+
// Route substituted unknown nodes to the caller's fallback (see resolveRenderContent).
|
|
324
|
+
...unhandledNode ? { [UNHANDLED_NODE_TYPE]: placeholderNodeRenderer(unhandledNode) } : {}
|
|
204
325
|
},
|
|
205
326
|
markMapping: {
|
|
206
327
|
...Object.fromEntries(
|
|
207
328
|
markExtensions.filter((e) => {
|
|
208
|
-
if (
|
|
209
|
-
return !(e.name in
|
|
329
|
+
if (userMarkMapping) {
|
|
330
|
+
return !(e.name in userMarkMapping);
|
|
210
331
|
}
|
|
211
332
|
return true;
|
|
212
333
|
}).map(
|
|
@@ -218,7 +339,9 @@ function renderToElement({
|
|
|
218
339
|
)
|
|
219
340
|
)
|
|
220
341
|
),
|
|
221
|
-
...
|
|
342
|
+
...userMarkMapping,
|
|
343
|
+
// Route substituted unknown marks to the caller's fallback (see resolveRenderContent).
|
|
344
|
+
...unhandledMark ? { [UNHANDLED_MARK_TYPE]: placeholderMarkRenderer(unhandledMark) } : {}
|
|
222
345
|
}
|
|
223
346
|
})({ content });
|
|
224
347
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/pm/react/index.ts","../../../src/pm/extensionRenderer.ts","../../../src/helpers.ts","../../../src/pm/react/react.ts","../../../src/json/react/react.ts","../../../src/json/renderer.ts"],"sourcesContent":["export * from '../extensionRenderer.js'\nexport * from './react.js'\n","/* oslint-disable no-plusplus */\n/* oslint-disableno-explicit-any */\n\nimport type {\n ExtensionAttribute,\n Extensions,\n JSONContent,\n Mark as MarkExtension,\n MarkConfig,\n Node as NodeExtension,\n NodeConfig,\n} from '@tiptap/core'\nimport {\n extensions as coreExtensions,\n getAttributesFromExtensions,\n getExtensionField,\n getSchemaByResolvedExtensions,\n resolveExtensions,\n splitExtensions,\n} from '@tiptap/core'\nimport type { DOMOutputSpec, Mark } from '@tiptap/pm/model'\nimport { Node } from '@tiptap/pm/model'\n\nimport { getHTMLAttributes } from '../helpers.js'\nimport type { MarkProps, NodeProps, TiptapStaticRendererOptions } from '../json/renderer.js'\n\nexport type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T\n\n/**\n * Options that mirror a subset of `EditorOptions` and affect rendered output.\n * Kept narrow on purpose: only options whose effect is reproducible without an\n * `Editor` instance belong here.\n */\nexport type StaticEditorOptions = {\n /**\n * Sets the text direction for all non-text nodes. Matches the `textDirection`\n * editor option on `Editor`. The configured `TextDirection` extension is\n * prepended to the user-supplied `extensions`; if a user-supplied\n * `TextDirection` is also present, the user's wins (last-defined precedence —\n * same as Editor).\n */\n textDirection?: 'ltr' | 'rtl' | 'auto'\n}\n\n/**\n * Apply editor-level options to the user's extension array.\n *\n * Mirrors `new Editor({ textDirection })`: the option-driven `TextDirection`\n * extension is prepended so a user-supplied `TextDirection` (which comes after)\n * can override it via tiptap's last-defined precedence for duplicate extensions.\n *\n * Known limitation: this only inspects top-level extensions. A `TextDirection`\n * bundled inside a kit (e.g. `StarterKit`) is not detected for override\n * purposes — today no shipped kit includes `TextDirection`, so this is purely\n * theoretical.\n */\nexport function applyStaticEditorOptionsToExtensions(\n extensions: Extensions,\n options?: StaticEditorOptions,\n): Extensions {\n if (!options?.textDirection) {\n return extensions\n }\n\n return [\n coreExtensions.TextDirection.configure({ direction: options.textDirection }),\n ...extensions,\n ]\n}\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(\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 =>\n mapNodeExtensionToReactNode<T>(\n domOutputSpecToElement,\n nodeExtension,\n extensionAttributes,\n options,\n ),\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 =>\n mapMarkExtensionToReactNode<T>(\n domOutputSpecToElement,\n mark,\n extensionAttributes,\n options,\n ),\n ),\n ),\n ...options?.markMapping,\n },\n })({ content })\n}\n","/* oslint-disableno-explicit-any */\nimport {\n type ExtensionAttribute,\n type MarkType,\n type NodeType,\n mergeAttributes,\n} 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 (\n item.type !== (typeof nodeOrMark.type === 'string' ? nodeOrMark.type : nodeOrMark.type.name)\n ) {\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","/* oslint-disable no-plusplus,no-explicit-any */\nimport type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'\nimport type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\nimport React from 'react'\n\nimport { renderJSONContentToReactElement } from '../../json/react/react.js'\nimport type { TiptapStaticRendererOptions } from '../../json/renderer.js'\nimport type { StaticEditorOptions } from '../extensionRenderer.js'\nimport { applyStaticEditorOptionsToExtensions, renderToElement } from '../extensionRenderer.js'\n\n/**\n * This function maps the attributes of a node or mark to HTML attributes\n * @param attrs The attributes to map\n * @param key The key to use for the React element\n * @returns The mapped HTML attributes as an object\n */\nexport function mapAttrsToHTMLAttributes(\n attrs?: Record<string, any>,\n key?: string,\n): Record<string, any> {\n if (!attrs) {\n return { key }\n }\n return Object.entries(attrs).reduce(\n (acc, [name, value]) => {\n if (name === 'class') {\n return Object.assign(acc, { className: value })\n }\n\n // React expects styles to be a object\n // so we need to convert it from string to object\n if (name === 'style' && typeof value === 'string') {\n const styleObject: Record<string, string> = {}\n value.split(';').forEach(style => {\n const [styleKey, val] = style.split(':')\n if (styleKey && val) {\n // we need to turn the key into camelCase\n const camelCaseKey = styleKey.trim().replace(/-([a-z])/g, g => g[1].toUpperCase())\n styleObject[camelCaseKey] = val.trim()\n }\n })\n\n return Object.assign(acc, { style: styleObject })\n }\n\n return Object.assign(acc, { [name]: value })\n },\n { key },\n )\n}\n\n/**\n * Take a DOMOutputSpec and return a function that can render it to a React element\n * @param content The DOMOutputSpec to convert to a React element\n * @returns A function that can render the DOMOutputSpec to a React element\n */\nexport function domOutputSpecToReactElement(\n content: DOMOutputSpec,\n key = 0,\n): (children?: React.ReactNode) => React.ReactNode {\n if (typeof content === 'string') {\n return () => content\n }\n if (typeof content === 'object' && 'length' in content) {\n // oxlint-disable-next-line prefer-const\n let [tag, attrs, children, ...rest] = content as DOMOutputSpecArray\n const parts = tag.split(' ')\n\n if (parts.length > 1) {\n tag = parts[1]\n if (attrs === undefined) {\n attrs = {\n xmlns: parts[0],\n }\n }\n if (attrs === 0) {\n attrs = {\n xmlns: parts[0],\n }\n children = 0\n }\n if (typeof attrs === 'object') {\n attrs = Object.assign(attrs, { xmlns: parts[0] })\n }\n }\n\n if (attrs === undefined) {\n return () => React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()))\n }\n if (attrs === 0) {\n return child =>\n React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()), child)\n }\n if (typeof attrs === 'object') {\n if (Array.isArray(attrs)) {\n if (children === undefined) {\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray, key++)(child),\n )\n }\n if (children === 0) {\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray, key++)(child),\n )\n }\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray)(child),\n [children]\n .concat(rest)\n .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),\n )\n }\n if (children === undefined) {\n return () => React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()))\n }\n if (children === 0) {\n return child =>\n React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()), child)\n }\n\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(attrs, key.toString()),\n [children]\n .concat(rest)\n .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),\n )\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 a React component using the given extensions.\n *\n * Limitations: see `renderToHTMLString` — extensions that mutate the document\n * via plugins/onCreate (UniqueID, TableOfContents) need to be pre-processed.\n *\n * @param content The content to render to a React component\n * @param extensions The extensions to use for rendering\n * @param staticEditorOptions Optional editor-level options that affect rendered output — mirrors a subset of `EditorOptions`.\n * @param options The options to use for rendering\n * @returns The React element that represents the rendered content\n */\nexport function renderToReactElement({\n content,\n extensions,\n staticEditorOptions,\n options,\n}: {\n content: Node | JSONContent\n extensions: Extensions\n staticEditorOptions?: StaticEditorOptions\n options?: Partial<TiptapStaticRendererOptions<React.ReactNode, Mark, Node>>\n}): React.ReactNode {\n return renderToElement<React.ReactNode>({\n renderer: renderJSONContentToReactElement,\n domOutputSpecToElement: domOutputSpecToReactElement,\n mapDefinedTypes: {\n // Map a doc node to concatenated children\n doc: ({ children }) => React.createElement(React.Fragment, {}, children),\n // Map a text node to its text content\n text: ({ node }) => node.text ?? '',\n },\n content,\n extensions: applyStaticEditorOptionsToExtensions(extensions, staticEditorOptions),\n options,\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","/* 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":"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","names":["import_core","coreExtensions","import_react","_a","React","React"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/pm/react/index.ts","../../../src/pm/extensionRenderer.ts","../../../src/helpers.ts","../../../src/pm/react/react.ts","../../../src/json/react/react.ts","../../../src/json/renderer.ts"],"sourcesContent":["export * from '../extensionRenderer.js'\nexport * from './react.js'\n","/* oslint-disable no-plusplus */\n/* oslint-disableno-explicit-any */\n\nimport type {\n ExtensionAttribute,\n Extensions,\n JSONContent,\n Mark as MarkExtension,\n MarkConfig,\n Node as NodeExtension,\n NodeConfig,\n} from '@tiptap/core'\nimport {\n extensions as coreExtensions,\n getAttributesFromExtensions,\n getExtensionField,\n getSchemaByResolvedExtensions,\n resolveExtensions,\n splitExtensions,\n} from '@tiptap/core'\nimport type { DOMOutputSpec, Mark } from '@tiptap/pm/model'\nimport { Node, Schema } from '@tiptap/pm/model'\n\nimport { getHTMLAttributes } from '../helpers.js'\nimport type { MarkProps, NodeProps, TiptapStaticRendererOptions } from '../json/renderer.js'\n\nexport type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T\n\n/**\n * Options that mirror a subset of `EditorOptions` and affect rendered output.\n * Kept narrow on purpose: only options whose effect is reproducible without an\n * `Editor` instance belong here.\n */\nexport type StaticEditorOptions = {\n /**\n * Sets the text direction for all non-text nodes. Matches the `textDirection`\n * editor option on `Editor`. The configured `TextDirection` extension is\n * prepended to the user-supplied `extensions`; if a user-supplied\n * `TextDirection` is also present, the user's wins (last-defined precedence —\n * same as Editor).\n */\n textDirection?: 'ltr' | 'rtl' | 'auto'\n}\n\n/**\n * Apply editor-level options to the user's extension array.\n *\n * Mirrors `new Editor({ textDirection })`: the option-driven `TextDirection`\n * extension is prepended so a user-supplied `TextDirection` (which comes after)\n * can override it via tiptap's last-defined precedence for duplicate extensions.\n *\n * Known limitation: this only inspects top-level extensions. A `TextDirection`\n * bundled inside a kit (e.g. `StarterKit`) is not detected for override\n * purposes — today no shipped kit includes `TextDirection`, so this is purely\n * theoretical.\n */\nexport function applyStaticEditorOptionsToExtensions(\n extensions: Extensions,\n options?: StaticEditorOptions,\n): Extensions {\n if (!options?.textDirection) {\n return extensions\n }\n\n return [\n coreExtensions.TextDirection.configure({ direction: options.textDirection }),\n ...extensions,\n ]\n}\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(\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// Placeholder node/mark types injected into a copy of the schema so JSON that\n// references types missing from the user's schema can still be converted by\n// `Node.fromJSON`. The original type/attrs are carried on the placeholder and\n// restored when it reaches `unhandledNode`/`unhandledMark`.\nconst UNHANDLED_NODE_TYPE = '__tiptapUnhandledNode__'\nconst UNHANDLED_MARK_TYPE = '__tiptapUnhandledMark__'\nconst ORIGINAL_TYPE_ATTR = '__originalType'\nconst ORIGINAL_ATTRS_ATTR = '__originalAttrs'\n\nconst placeholderAttrs = {\n [ORIGINAL_TYPE_ATTR]: { default: '' },\n [ORIGINAL_ATTRS_ATTR]: { default: {} },\n}\n\n/**\n * Returns true if `content` references any node or mark type absent from `schema`.\n */\nfunction hasUnknownType(content: JSONContent, schema: Schema): boolean {\n let found = false\n\n const visit = (node: JSONContent): void => {\n if (found) {\n return\n }\n if (node.type && !(node.type in schema.nodes)) {\n found = true\n }\n node.marks?.forEach(mark => {\n if (mark.type && !(mark.type in schema.marks)) {\n found = true\n }\n })\n node.content?.forEach(visit)\n }\n\n visit(content)\n\n return found\n}\n\n/**\n * Returns a deep copy of `content` in which every node/mark type absent from\n * `schema` AND covered by a matching fallback in `options` is replaced by a\n * placeholder type carrying the original type/attrs. Unknown types without a\n * matching fallback are left untouched so `Node.fromJSON` still surfaces its clear\n * error for them.\n */\nfunction substituteUnknownTypes(\n content: JSONContent,\n schema: Schema,\n options?: { unhandledNode?: unknown; unhandledMark?: unknown },\n): JSONContent {\n const canSubstituteNode = Boolean(options?.unhandledNode)\n const canSubstituteMark = Boolean(options?.unhandledMark)\n\n const substituteMark = (mark: NonNullable<JSONContent['marks']>[number]) =>\n canSubstituteMark && !(mark.type in schema.marks)\n ? {\n type: UNHANDLED_MARK_TYPE,\n attrs: { [ORIGINAL_TYPE_ATTR]: mark.type, [ORIGINAL_ATTRS_ATTR]: mark.attrs ?? {} },\n }\n : mark\n\n const isUnknownNode = (node: JSONContent) =>\n canSubstituteNode && node.type != null && !(node.type in schema.nodes)\n\n const toPlaceholder = (node: JSONContent, rewritten: JSONContent): JSONContent => ({\n ...rewritten,\n type: UNHANDLED_NODE_TYPE,\n attrs: { [ORIGINAL_TYPE_ATTR]: node.type, [ORIGINAL_ATTRS_ATTR]: node.attrs ?? {} },\n })\n\n const substituteNode = (node: JSONContent): JSONContent => {\n const rewritten = {\n ...node,\n marks: node.marks?.map(substituteMark),\n content: node.content?.map(substituteNode),\n }\n return isUnknownNode(node) ? toPlaceholder(node, rewritten) : rewritten\n }\n\n return substituteNode(content)\n}\n\n/**\n * Builds a copy of `schema` with the placeholder node/mark types added, so a\n * document produced by `substituteUnknownTypes` converts cleanly.\n */\nfunction withPlaceholderTypes(schema: Schema): Schema {\n return new Schema({\n topNode: schema.spec.topNode,\n nodes: schema.spec.nodes.addToEnd(UNHANDLED_NODE_TYPE, { attrs: placeholderAttrs }),\n marks: schema.spec.marks.addToEnd(UNHANDLED_MARK_TYPE, { attrs: placeholderAttrs }),\n })\n}\n\n/**\n * Resolves render input to a ProseMirror `Node`. A `Node` is returned as-is. JSON\n * with only known types converts directly. JSON containing types missing from the\n * schema has those types — when a matching `unhandledNode`/`unhandledMark` fallback\n * exists — swapped for placeholders before conversion, so known nodes keep their\n * materialized attributes and only the unknown ones route to the fallbacks. Unknown\n * types without a fallback, and genuinely malformed content, still throw.\n */\nfunction resolveRenderContent(\n content: Node | JSONContent,\n extensions: Extensions,\n options?: { unhandledNode?: unknown; unhandledMark?: unknown },\n): Node {\n if (content instanceof Node) {\n return content\n }\n\n const schema = getSchemaByResolvedExtensions(extensions)\n\n if (!hasUnknownType(content, schema)) {\n return Node.fromJSON(schema, content)\n }\n\n return Node.fromJSON(\n withPlaceholderTypes(schema),\n substituteUnknownTypes(content, schema, options),\n )\n}\n\n/**\n * Swaps a placeholder node/mark JSON back to its original type and attributes.\n * Leaves non-placeholder JSON untouched.\n */\nfunction unwrapPlaceholderJSON(json: JSONContent): JSONContent {\n return json.type === UNHANDLED_NODE_TYPE || json.type === UNHANDLED_MARK_TYPE\n ? { ...json, type: json.attrs![ORIGINAL_TYPE_ATTR], attrs: json.attrs![ORIGINAL_ATTRS_ATTR] }\n : json\n}\n\n/**\n * Recursively restores the original JSON of a (possibly nested) placeholder\n * subtree, including placeholder marks.\n */\nfunction restoreOriginalJSON(json: JSONContent): JSONContent {\n const node = unwrapPlaceholderJSON(json)\n\n return {\n ...node,\n marks: node.marks?.map(\n mark => unwrapPlaceholderJSON(mark) as NonNullable<JSONContent['marks']>[number],\n ),\n content: node.content?.map(restoreOriginalJSON),\n }\n}\n\n/**\n * Presents a placeholder node/mark to a fallback renderer under its original type\n * name and attributes — including a `toJSON()` that returns the restored original\n * JSON — while keeping the live ProseMirror children/methods intact.\n *\n * `type` is exposed as a minimal `{ name }` rather than a real `NodeType`/`MarkType`:\n * the original type is absent from the schema so no real one exists, and surfacing\n * the placeholder's own type would leak misleading `spec`/`schema`/`isInline` values.\n */\nfunction withOriginalIdentity<T extends { attrs: Record<string, any>; toJSON: () => JSONContent }>(\n target: T,\n): T {\n const overrides: Record<string | symbol, unknown> = Object.assign(Object.create(null), {\n type: { name: target.attrs[ORIGINAL_TYPE_ATTR] },\n attrs: target.attrs[ORIGINAL_ATTRS_ATTR],\n toJSON: () => restoreOriginalJSON(target.toJSON()),\n })\n\n return new Proxy(target, {\n get(node, prop) {\n const override = overrides[prop]\n if (override !== undefined) {\n return override\n }\n const value = (node as Record<string | symbol, unknown>)[prop]\n return typeof value === 'function' ? value.bind(node) : value\n },\n })\n}\n\n/** Maps the placeholder node type to the caller's `unhandledNode`, restoring identity. */\nfunction placeholderNodeRenderer<T>(\n unhandledNode: (props: NodeProps<Node, T | T[]>) => T,\n): (props: NodeProps<Node, T | T[]>) => T {\n return props => unhandledNode({ ...props, node: withOriginalIdentity(props.node) })\n}\n\n/** Maps the placeholder mark type to the caller's `unhandledMark`, restoring identity. */\nfunction placeholderMarkRenderer<T>(\n unhandledMark: (props: MarkProps<Mark, T | T[], Node>) => T,\n): (props: MarkProps<Mark, T | T[], Node>) => T {\n return props => unhandledMark({ ...props, mark: withOriginalIdentity(props.mark) })\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 const {\n unhandledNode,\n unhandledMark,\n nodeMapping: userNodeMapping,\n markMapping: userMarkMapping,\n } = options ?? {}\n\n content = resolveRenderContent(content, extensions, options)\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 (userNodeMapping) {\n return !(e.name in userNodeMapping)\n }\n return true\n })\n .map(nodeExtension =>\n mapNodeExtensionToReactNode<T>(\n domOutputSpecToElement,\n nodeExtension,\n extensionAttributes,\n options,\n ),\n ),\n ),\n ...mapDefinedTypes,\n ...userNodeMapping,\n // Route substituted unknown nodes to the caller's fallback (see resolveRenderContent).\n ...(unhandledNode\n ? { [UNHANDLED_NODE_TYPE]: placeholderNodeRenderer<T>(unhandledNode) }\n : {}),\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 (userMarkMapping) {\n return !(e.name in userMarkMapping)\n }\n return true\n })\n .map(mark =>\n mapMarkExtensionToReactNode<T>(\n domOutputSpecToElement,\n mark,\n extensionAttributes,\n options,\n ),\n ),\n ),\n ...userMarkMapping,\n // Route substituted unknown marks to the caller's fallback (see resolveRenderContent).\n ...(unhandledMark\n ? { [UNHANDLED_MARK_TYPE]: placeholderMarkRenderer<T>(unhandledMark) }\n : {}),\n },\n })({ content })\n}\n","/* oslint-disableno-explicit-any */\nimport {\n type ExtensionAttribute,\n type MarkType,\n type NodeType,\n mergeAttributes,\n} 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 (\n item.type !== (typeof nodeOrMark.type === 'string' ? nodeOrMark.type : nodeOrMark.type.name)\n ) {\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","/* oslint-disable no-plusplus,no-explicit-any */\nimport type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'\nimport type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'\nimport React from 'react'\n\nimport { renderJSONContentToReactElement } from '../../json/react/react.js'\nimport type { TiptapStaticRendererOptions } from '../../json/renderer.js'\nimport type { StaticEditorOptions } from '../extensionRenderer.js'\nimport { applyStaticEditorOptionsToExtensions, renderToElement } from '../extensionRenderer.js'\n\n/**\n * This function maps the attributes of a node or mark to HTML attributes\n * @param attrs The attributes to map\n * @param key The key to use for the React element\n * @returns The mapped HTML attributes as an object\n */\nexport function mapAttrsToHTMLAttributes(\n attrs?: Record<string, any>,\n key?: string,\n): Record<string, any> {\n if (!attrs) {\n return { key }\n }\n return Object.entries(attrs).reduce(\n (acc, [name, value]) => {\n if (name === 'class') {\n return Object.assign(acc, { className: value })\n }\n\n // React expects styles to be a object\n // so we need to convert it from string to object\n if (name === 'style' && typeof value === 'string') {\n const styleObject: Record<string, string> = {}\n value.split(';').forEach(style => {\n const [styleKey, val] = style.split(':')\n if (styleKey && val) {\n // we need to turn the key into camelCase\n const camelCaseKey = styleKey.trim().replace(/-([a-z])/g, g => g[1].toUpperCase())\n styleObject[camelCaseKey] = val.trim()\n }\n })\n\n return Object.assign(acc, { style: styleObject })\n }\n\n return Object.assign(acc, { [name]: value })\n },\n { key },\n )\n}\n\n/**\n * Take a DOMOutputSpec and return a function that can render it to a React element\n * @param content The DOMOutputSpec to convert to a React element\n * @returns A function that can render the DOMOutputSpec to a React element\n */\nexport function domOutputSpecToReactElement(\n content: DOMOutputSpec,\n key = 0,\n): (children?: React.ReactNode) => React.ReactNode {\n if (typeof content === 'string') {\n return () => content\n }\n if (typeof content === 'object' && 'length' in content) {\n // oxlint-disable-next-line prefer-const\n let [tag, attrs, children, ...rest] = content as DOMOutputSpecArray\n const parts = tag.split(' ')\n\n if (parts.length > 1) {\n tag = parts[1]\n if (attrs === undefined) {\n attrs = {\n xmlns: parts[0],\n }\n }\n if (attrs === 0) {\n attrs = {\n xmlns: parts[0],\n }\n children = 0\n }\n if (typeof attrs === 'object') {\n attrs = Object.assign(attrs, { xmlns: parts[0] })\n }\n }\n\n if (attrs === undefined) {\n return () => React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()))\n }\n if (attrs === 0) {\n return child =>\n React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()), child)\n }\n if (typeof attrs === 'object') {\n if (Array.isArray(attrs)) {\n if (children === undefined) {\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray, key++)(child),\n )\n }\n if (children === 0) {\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray, key++)(child),\n )\n }\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(undefined, key.toString()),\n domOutputSpecToReactElement(attrs as DOMOutputSpecArray)(child),\n [children]\n .concat(rest)\n .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),\n )\n }\n if (children === undefined) {\n return () => React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()))\n }\n if (children === 0) {\n return child =>\n React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()), child)\n }\n\n return child =>\n React.createElement(\n tag,\n mapAttrsToHTMLAttributes(attrs, key.toString()),\n [children]\n .concat(rest)\n .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),\n )\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 a React component using the given extensions.\n *\n * Limitations: see `renderToHTMLString` — extensions that mutate the document\n * via plugins/onCreate (UniqueID, TableOfContents) need to be pre-processed.\n *\n * @param content The content to render to a React component\n * @param extensions The extensions to use for rendering\n * @param staticEditorOptions Optional editor-level options that affect rendered output — mirrors a subset of `EditorOptions`.\n * @param options The options to use for rendering\n * @returns The React element that represents the rendered content\n */\nexport function renderToReactElement({\n content,\n extensions,\n staticEditorOptions,\n options,\n}: {\n content: Node | JSONContent\n extensions: Extensions\n staticEditorOptions?: StaticEditorOptions\n options?: Partial<TiptapStaticRendererOptions<React.ReactNode, Mark, Node>>\n}): React.ReactNode {\n return renderToElement<React.ReactNode>({\n renderer: renderJSONContentToReactElement,\n domOutputSpecToElement: domOutputSpecToReactElement,\n mapDefinedTypes: {\n // Map a doc node to concatenated children\n doc: ({ children }) => React.createElement(React.Fragment, {}, children),\n // Map a text node to its text content\n text: ({ node }) => node.text ?? '',\n },\n content,\n extensions: applyStaticEditorOptionsToExtensions(extensions, staticEditorOptions),\n options,\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","/* 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 * With the ProseMirror renderers, a type missing from the schema is passed here\n * as a lightweight stand-in: `node.type` is only `{ name }` (no real `NodeType`\n * exists for a type absent from the schema), while `node.attrs` and\n * `node.toJSON()` reflect the original. Do not rely on `type.spec`,\n * `type.schema`, `isInline`, etc.\n */\n unhandledNode?: NoInfer<TNodeRender>\n /**\n * Component to render if a mark type is not handled.\n *\n * With the ProseMirror renderers, a type missing from the schema is passed here\n * as a lightweight stand-in: `mark.type` is only `{ name }` (no real `MarkType`\n * exists for a type absent from the schema), while `mark.attrs` and\n * `mark.toJSON()` reflect the original. Do not rely on `type.spec`,\n * `type.schema`, etc.\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":"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","names":["import_core","coreExtensions","import_react","_a","React","React"]}
|
|
@@ -121,11 +121,23 @@ TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNod
|
|
|
121
121
|
*/
|
|
122
122
|
markMapping: Record<string, NoInfer<TMarkRender>>;
|
|
123
123
|
/**
|
|
124
|
-
* Component to render if a node type is not handled
|
|
124
|
+
* Component to render if a node type is not handled.
|
|
125
|
+
*
|
|
126
|
+
* With the ProseMirror renderers, a type missing from the schema is passed here
|
|
127
|
+
* as a lightweight stand-in: `node.type` is only `{ name }` (no real `NodeType`
|
|
128
|
+
* exists for a type absent from the schema), while `node.attrs` and
|
|
129
|
+
* `node.toJSON()` reflect the original. Do not rely on `type.spec`,
|
|
130
|
+
* `type.schema`, `isInline`, etc.
|
|
125
131
|
*/
|
|
126
132
|
unhandledNode?: NoInfer<TNodeRender>;
|
|
127
133
|
/**
|
|
128
|
-
* Component to render if a mark type is not handled
|
|
134
|
+
* Component to render if a mark type is not handled.
|
|
135
|
+
*
|
|
136
|
+
* With the ProseMirror renderers, a type missing from the schema is passed here
|
|
137
|
+
* as a lightweight stand-in: `mark.type` is only `{ name }` (no real `MarkType`
|
|
138
|
+
* exists for a type absent from the schema), while `mark.attrs` and
|
|
139
|
+
* `mark.toJSON()` reflect the original. Do not rely on `type.spec`,
|
|
140
|
+
* `type.schema`, etc.
|
|
129
141
|
*/
|
|
130
142
|
unhandledMark?: NoInfer<TMarkRender>;
|
|
131
143
|
};
|
package/dist/pm/react/index.d.ts
CHANGED
|
@@ -121,11 +121,23 @@ TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNod
|
|
|
121
121
|
*/
|
|
122
122
|
markMapping: Record<string, NoInfer<TMarkRender>>;
|
|
123
123
|
/**
|
|
124
|
-
* Component to render if a node type is not handled
|
|
124
|
+
* Component to render if a node type is not handled.
|
|
125
|
+
*
|
|
126
|
+
* With the ProseMirror renderers, a type missing from the schema is passed here
|
|
127
|
+
* as a lightweight stand-in: `node.type` is only `{ name }` (no real `NodeType`
|
|
128
|
+
* exists for a type absent from the schema), while `node.attrs` and
|
|
129
|
+
* `node.toJSON()` reflect the original. Do not rely on `type.spec`,
|
|
130
|
+
* `type.schema`, `isInline`, etc.
|
|
125
131
|
*/
|
|
126
132
|
unhandledNode?: NoInfer<TNodeRender>;
|
|
127
133
|
/**
|
|
128
|
-
* Component to render if a mark type is not handled
|
|
134
|
+
* Component to render if a mark type is not handled.
|
|
135
|
+
*
|
|
136
|
+
* With the ProseMirror renderers, a type missing from the schema is passed here
|
|
137
|
+
* as a lightweight stand-in: `mark.type` is only `{ name }` (no real `MarkType`
|
|
138
|
+
* exists for a type absent from the schema), while `mark.attrs` and
|
|
139
|
+
* `mark.toJSON()` reflect the original. Do not rely on `type.spec`,
|
|
140
|
+
* `type.schema`, etc.
|
|
129
141
|
*/
|
|
130
142
|
unhandledMark?: NoInfer<TMarkRender>;
|
|
131
143
|
};
|
package/dist/pm/react/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
resolveExtensions,
|
|
8
8
|
splitExtensions
|
|
9
9
|
} from "@tiptap/core";
|
|
10
|
-
import { Node } from "@tiptap/pm/model";
|
|
10
|
+
import { Node, Schema } from "@tiptap/pm/model";
|
|
11
11
|
|
|
12
12
|
// src/helpers.ts
|
|
13
13
|
import {
|
|
@@ -131,6 +131,121 @@ function mapMarkExtensionToReactNode(domOutputSpecToElement, extension, extensio
|
|
|
131
131
|
}
|
|
132
132
|
];
|
|
133
133
|
}
|
|
134
|
+
var UNHANDLED_NODE_TYPE = "__tiptapUnhandledNode__";
|
|
135
|
+
var UNHANDLED_MARK_TYPE = "__tiptapUnhandledMark__";
|
|
136
|
+
var ORIGINAL_TYPE_ATTR = "__originalType";
|
|
137
|
+
var ORIGINAL_ATTRS_ATTR = "__originalAttrs";
|
|
138
|
+
var placeholderAttrs = {
|
|
139
|
+
[ORIGINAL_TYPE_ATTR]: { default: "" },
|
|
140
|
+
[ORIGINAL_ATTRS_ATTR]: { default: {} }
|
|
141
|
+
};
|
|
142
|
+
function hasUnknownType(content, schema) {
|
|
143
|
+
let found = false;
|
|
144
|
+
const visit = (node) => {
|
|
145
|
+
var _a, _b;
|
|
146
|
+
if (found) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (node.type && !(node.type in schema.nodes)) {
|
|
150
|
+
found = true;
|
|
151
|
+
}
|
|
152
|
+
(_a = node.marks) == null ? void 0 : _a.forEach((mark) => {
|
|
153
|
+
if (mark.type && !(mark.type in schema.marks)) {
|
|
154
|
+
found = true;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
(_b = node.content) == null ? void 0 : _b.forEach(visit);
|
|
158
|
+
};
|
|
159
|
+
visit(content);
|
|
160
|
+
return found;
|
|
161
|
+
}
|
|
162
|
+
function substituteUnknownTypes(content, schema, options) {
|
|
163
|
+
const canSubstituteNode = Boolean(options == null ? void 0 : options.unhandledNode);
|
|
164
|
+
const canSubstituteMark = Boolean(options == null ? void 0 : options.unhandledMark);
|
|
165
|
+
const substituteMark = (mark) => {
|
|
166
|
+
var _a;
|
|
167
|
+
return canSubstituteMark && !(mark.type in schema.marks) ? {
|
|
168
|
+
type: UNHANDLED_MARK_TYPE,
|
|
169
|
+
attrs: { [ORIGINAL_TYPE_ATTR]: mark.type, [ORIGINAL_ATTRS_ATTR]: (_a = mark.attrs) != null ? _a : {} }
|
|
170
|
+
} : mark;
|
|
171
|
+
};
|
|
172
|
+
const isUnknownNode = (node) => canSubstituteNode && node.type != null && !(node.type in schema.nodes);
|
|
173
|
+
const toPlaceholder = (node, rewritten) => {
|
|
174
|
+
var _a;
|
|
175
|
+
return {
|
|
176
|
+
...rewritten,
|
|
177
|
+
type: UNHANDLED_NODE_TYPE,
|
|
178
|
+
attrs: { [ORIGINAL_TYPE_ATTR]: node.type, [ORIGINAL_ATTRS_ATTR]: (_a = node.attrs) != null ? _a : {} }
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
const substituteNode = (node) => {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
const rewritten = {
|
|
184
|
+
...node,
|
|
185
|
+
marks: (_a = node.marks) == null ? void 0 : _a.map(substituteMark),
|
|
186
|
+
content: (_b = node.content) == null ? void 0 : _b.map(substituteNode)
|
|
187
|
+
};
|
|
188
|
+
return isUnknownNode(node) ? toPlaceholder(node, rewritten) : rewritten;
|
|
189
|
+
};
|
|
190
|
+
return substituteNode(content);
|
|
191
|
+
}
|
|
192
|
+
function withPlaceholderTypes(schema) {
|
|
193
|
+
return new Schema({
|
|
194
|
+
topNode: schema.spec.topNode,
|
|
195
|
+
nodes: schema.spec.nodes.addToEnd(UNHANDLED_NODE_TYPE, { attrs: placeholderAttrs }),
|
|
196
|
+
marks: schema.spec.marks.addToEnd(UNHANDLED_MARK_TYPE, { attrs: placeholderAttrs })
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function resolveRenderContent(content, extensions, options) {
|
|
200
|
+
if (content instanceof Node) {
|
|
201
|
+
return content;
|
|
202
|
+
}
|
|
203
|
+
const schema = getSchemaByResolvedExtensions(extensions);
|
|
204
|
+
if (!hasUnknownType(content, schema)) {
|
|
205
|
+
return Node.fromJSON(schema, content);
|
|
206
|
+
}
|
|
207
|
+
return Node.fromJSON(
|
|
208
|
+
withPlaceholderTypes(schema),
|
|
209
|
+
substituteUnknownTypes(content, schema, options)
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
function unwrapPlaceholderJSON(json) {
|
|
213
|
+
return json.type === UNHANDLED_NODE_TYPE || json.type === UNHANDLED_MARK_TYPE ? { ...json, type: json.attrs[ORIGINAL_TYPE_ATTR], attrs: json.attrs[ORIGINAL_ATTRS_ATTR] } : json;
|
|
214
|
+
}
|
|
215
|
+
function restoreOriginalJSON(json) {
|
|
216
|
+
var _a, _b;
|
|
217
|
+
const node = unwrapPlaceholderJSON(json);
|
|
218
|
+
return {
|
|
219
|
+
...node,
|
|
220
|
+
marks: (_a = node.marks) == null ? void 0 : _a.map(
|
|
221
|
+
(mark) => unwrapPlaceholderJSON(mark)
|
|
222
|
+
),
|
|
223
|
+
content: (_b = node.content) == null ? void 0 : _b.map(restoreOriginalJSON)
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function withOriginalIdentity(target) {
|
|
227
|
+
const overrides = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
228
|
+
type: { name: target.attrs[ORIGINAL_TYPE_ATTR] },
|
|
229
|
+
attrs: target.attrs[ORIGINAL_ATTRS_ATTR],
|
|
230
|
+
toJSON: () => restoreOriginalJSON(target.toJSON())
|
|
231
|
+
});
|
|
232
|
+
return new Proxy(target, {
|
|
233
|
+
get(node, prop) {
|
|
234
|
+
const override = overrides[prop];
|
|
235
|
+
if (override !== void 0) {
|
|
236
|
+
return override;
|
|
237
|
+
}
|
|
238
|
+
const value = node[prop];
|
|
239
|
+
return typeof value === "function" ? value.bind(node) : value;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function placeholderNodeRenderer(unhandledNode) {
|
|
244
|
+
return (props) => unhandledNode({ ...props, node: withOriginalIdentity(props.node) });
|
|
245
|
+
}
|
|
246
|
+
function placeholderMarkRenderer(unhandledMark) {
|
|
247
|
+
return (props) => unhandledMark({ ...props, mark: withOriginalIdentity(props.mark) });
|
|
248
|
+
}
|
|
134
249
|
function renderToElement({
|
|
135
250
|
renderer,
|
|
136
251
|
domOutputSpecToElement,
|
|
@@ -142,9 +257,13 @@ function renderToElement({
|
|
|
142
257
|
extensions = resolveExtensions(extensions);
|
|
143
258
|
const extensionAttributes = getAttributesFromExtensions(extensions);
|
|
144
259
|
const { nodeExtensions, markExtensions } = splitExtensions(extensions);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
260
|
+
const {
|
|
261
|
+
unhandledNode,
|
|
262
|
+
unhandledMark,
|
|
263
|
+
nodeMapping: userNodeMapping,
|
|
264
|
+
markMapping: userMarkMapping
|
|
265
|
+
} = options != null ? options : {};
|
|
266
|
+
content = resolveRenderContent(content, extensions, options);
|
|
148
267
|
return renderer({
|
|
149
268
|
...options,
|
|
150
269
|
nodeMapping: {
|
|
@@ -153,8 +272,8 @@ function renderToElement({
|
|
|
153
272
|
if (e.name in mapDefinedTypes) {
|
|
154
273
|
return false;
|
|
155
274
|
}
|
|
156
|
-
if (
|
|
157
|
-
return !(e.name in
|
|
275
|
+
if (userNodeMapping) {
|
|
276
|
+
return !(e.name in userNodeMapping);
|
|
158
277
|
}
|
|
159
278
|
return true;
|
|
160
279
|
}).map(
|
|
@@ -167,13 +286,15 @@ function renderToElement({
|
|
|
167
286
|
)
|
|
168
287
|
),
|
|
169
288
|
...mapDefinedTypes,
|
|
170
|
-
...
|
|
289
|
+
...userNodeMapping,
|
|
290
|
+
// Route substituted unknown nodes to the caller's fallback (see resolveRenderContent).
|
|
291
|
+
...unhandledNode ? { [UNHANDLED_NODE_TYPE]: placeholderNodeRenderer(unhandledNode) } : {}
|
|
171
292
|
},
|
|
172
293
|
markMapping: {
|
|
173
294
|
...Object.fromEntries(
|
|
174
295
|
markExtensions.filter((e) => {
|
|
175
|
-
if (
|
|
176
|
-
return !(e.name in
|
|
296
|
+
if (userMarkMapping) {
|
|
297
|
+
return !(e.name in userMarkMapping);
|
|
177
298
|
}
|
|
178
299
|
return true;
|
|
179
300
|
}).map(
|
|
@@ -185,7 +306,9 @@ function renderToElement({
|
|
|
185
306
|
)
|
|
186
307
|
)
|
|
187
308
|
),
|
|
188
|
-
...
|
|
309
|
+
...userMarkMapping,
|
|
310
|
+
// Route substituted unknown marks to the caller's fallback (see resolveRenderContent).
|
|
311
|
+
...unhandledMark ? { [UNHANDLED_MARK_TYPE]: placeholderMarkRenderer(unhandledMark) } : {}
|
|
189
312
|
}
|
|
190
313
|
})({ content });
|
|
191
314
|
}
|