@tiptap/static-renderer 3.0.0-next.1 → 3.0.0-next.4
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/LICENSE.md +21 -0
- package/README.md +1 -1
- package/dist/index.cjs +573 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +307 -32
- package/dist/index.d.ts +307 -32
- package/dist/index.js +552 -2
- package/dist/index.js.map +1 -1
- package/dist/json/html-string/index.cjs +16 -5
- package/dist/json/html-string/index.cjs.map +1 -1
- package/dist/json/html-string/index.d.cts +18 -22
- package/dist/json/html-string/index.d.ts +18 -22
- package/dist/json/html-string/index.js +10 -1
- package/dist/json/html-string/index.js.map +1 -1
- package/dist/json/react/index.cjs +12 -2201
- package/dist/json/react/index.cjs.map +1 -1
- package/dist/json/react/index.d.cts +5 -22
- package/dist/json/react/index.d.ts +5 -22
- package/dist/json/react/index.js +9 -2221
- package/dist/json/react/index.js.map +1 -1
- package/dist/json/renderer.cjs.map +1 -1
- package/dist/json/renderer.d.cts +5 -21
- package/dist/json/renderer.d.ts +5 -21
- package/dist/json/renderer.js.map +1 -1
- package/dist/pm/html-string/index.cjs +22 -37
- package/dist/pm/html-string/index.cjs.map +1 -1
- package/dist/pm/html-string/index.d.cts +7 -24
- package/dist/pm/html-string/index.d.ts +7 -24
- package/dist/pm/html-string/index.js +19 -34
- package/dist/pm/html-string/index.js.map +1 -1
- package/dist/pm/markdown/index.cjs +473 -0
- package/dist/pm/markdown/index.cjs.map +1 -0
- package/dist/pm/markdown/index.d.cts +153 -0
- package/dist/pm/markdown/index.d.ts +153 -0
- package/dist/pm/markdown/index.js +449 -0
- package/dist/pm/markdown/index.js.map +1 -0
- package/dist/pm/react/index.cjs +41 -2230
- package/dist/pm/react/index.cjs.map +1 -1
- package/dist/pm/react/index.d.cts +5 -23
- package/dist/pm/react/index.d.ts +5 -23
- package/dist/pm/react/index.js +47 -2259
- package/dist/pm/react/index.js.map +1 -1
- package/package.json +27 -8
- package/src/helpers.ts +5 -16
- package/src/index.ts +5 -1
- package/src/json/html-string/string.ts +39 -13
- package/src/json/react/react.tsx +12 -15
- package/src/json/renderer.ts +50 -51
- package/src/pm/extensionRenderer.ts +16 -34
- package/src/pm/html-string/html-string.ts +29 -45
- package/src/pm/markdown/index.ts +2 -0
- package/src/pm/markdown/markdown.ts +142 -0
- package/src/pm/react/react.tsx +49 -30
- package/src/helpers.example.ts +0 -35
- package/src/json/html-string/string.example.ts +0 -46
- package/src/json/react/react.example.ts +0 -45
- package/src/pm/html-string/html-string.example.ts +0 -225
- package/src/pm/markdown/markdown.example.ts +0 -296
- package/src/pm/react/react.example.tsx +0 -306
- package/src/types.ts +0 -57
package/src/index.ts
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { MarkType, NodeType } from '
|
|
2
|
+
import type { MarkType, NodeType } from '@tiptap/core'
|
|
3
|
+
|
|
3
4
|
import { TiptapStaticRenderer, TiptapStaticRendererOptions } from '../renderer.js'
|
|
4
5
|
|
|
5
6
|
export function renderJSONContentToString<
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
TMarkType extends { type: any } = MarkType,
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
TNodeType extends {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} = NodeType,
|
|
7
|
+
/**
|
|
8
|
+
* A mark type is either a JSON representation of a mark or a Prosemirror mark instance
|
|
9
|
+
*/
|
|
10
|
+
TMarkType extends { type: any } = MarkType,
|
|
11
|
+
/**
|
|
12
|
+
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
13
|
+
*/
|
|
14
|
+
TNodeType extends {
|
|
15
|
+
content?: { forEach: (cb: (node: TNodeType) => void) => void }
|
|
16
|
+
marks?: readonly TMarkType[]
|
|
17
|
+
type: string | { name: string }
|
|
18
|
+
} = NodeType,
|
|
18
19
|
>(options: TiptapStaticRendererOptions<string, TMarkType, TNodeType>) {
|
|
19
20
|
return TiptapStaticRenderer(ctx => {
|
|
20
21
|
return ctx.component(ctx.props as any)
|
|
21
22
|
}, options)
|
|
22
23
|
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Serialize the attributes of a node or mark to a string
|
|
27
|
+
* @param attrs The attributes to serialize
|
|
28
|
+
* @returns The serialized attributes as a string
|
|
29
|
+
*/
|
|
30
|
+
export function serializeAttrsToHTMLString(attrs: Record<string, any> | undefined | null): string {
|
|
31
|
+
const output = Object.entries(attrs || {})
|
|
32
|
+
.map(([key, value]) => `${key.split(' ').at(-1)}=${JSON.stringify(value)}`)
|
|
33
|
+
.join(' ')
|
|
34
|
+
|
|
35
|
+
return output ? ` ${output}` : ''
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Serialize the children of a node or mark to a string
|
|
40
|
+
* @param children The children to serialize
|
|
41
|
+
* @returns The serialized children as a string
|
|
42
|
+
*/
|
|
43
|
+
export function serializeChildrenToHTMLString(children?: string | string[]): string {
|
|
44
|
+
return ([] as string[])
|
|
45
|
+
.concat(children || '')
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
.join('')
|
|
48
|
+
}
|
package/src/json/react/react.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
|
|
3
|
+
import type { MarkType, NodeType } from '@tiptap/core'
|
|
3
4
|
import React from 'react'
|
|
4
5
|
|
|
5
|
-
import { MarkType, NodeType } from '../../types.js'
|
|
6
6
|
import { TiptapStaticRenderer, TiptapStaticRendererOptions } from '../renderer.js'
|
|
7
7
|
|
|
8
8
|
export function renderJSONContentToReactElement<
|
|
@@ -14,22 +14,19 @@ export function renderJSONContentToReactElement<
|
|
|
14
14
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
15
15
|
*/
|
|
16
16
|
TNodeType extends {
|
|
17
|
-
content?: { forEach:(cb: (node: TNodeType) => void) => void }
|
|
18
|
-
marks?: readonly TMarkType[]
|
|
19
|
-
type: string | { name: string }
|
|
17
|
+
content?: { forEach: (cb: (node: TNodeType) => void) => void }
|
|
18
|
+
marks?: readonly TMarkType[]
|
|
19
|
+
type: string | { name: string }
|
|
20
20
|
} = NodeType,
|
|
21
21
|
>(options: TiptapStaticRendererOptions<React.ReactNode, TMarkType, TNodeType>) {
|
|
22
22
|
let key = 0
|
|
23
23
|
|
|
24
|
-
return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(
|
|
25
|
-
(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
options,
|
|
34
|
-
)
|
|
24
|
+
return TiptapStaticRenderer<React.ReactNode, TMarkType, TNodeType>(({ component, props: { children, ...props } }) => {
|
|
25
|
+
return React.createElement(
|
|
26
|
+
component as React.FC<typeof props>,
|
|
27
|
+
// eslint-disable-next-line no-plusplus
|
|
28
|
+
Object.assign(props, { key: key++ }),
|
|
29
|
+
([] as React.ReactNode[]).concat(children),
|
|
30
|
+
)
|
|
31
|
+
}, options)
|
|
35
32
|
}
|
package/src/json/renderer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import type { MarkType, NodeType } from '
|
|
2
|
+
import type { MarkType, NodeType } from '@tiptap/core'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Props for a node renderer
|
|
@@ -8,15 +8,15 @@ export type NodeProps<TNodeType = any, TChildren = any> = {
|
|
|
8
8
|
/**
|
|
9
9
|
* The current node to render
|
|
10
10
|
*/
|
|
11
|
-
node: TNodeType
|
|
11
|
+
node: TNodeType
|
|
12
12
|
/**
|
|
13
13
|
* Unless the node is the root node, this will always be defined
|
|
14
14
|
*/
|
|
15
|
-
parent?: TNodeType
|
|
15
|
+
parent?: TNodeType
|
|
16
16
|
/**
|
|
17
17
|
* The children of the current node
|
|
18
18
|
*/
|
|
19
|
-
children?: TChildren
|
|
19
|
+
children?: TChildren
|
|
20
20
|
/**
|
|
21
21
|
* Render a child element
|
|
22
22
|
*/
|
|
@@ -24,13 +24,13 @@ export type NodeProps<TNodeType = any, TChildren = any> = {
|
|
|
24
24
|
/**
|
|
25
25
|
* Tiptap JSON content to render
|
|
26
26
|
*/
|
|
27
|
-
content: TNodeType
|
|
27
|
+
content: TNodeType
|
|
28
28
|
/**
|
|
29
29
|
* The parent node of the current node
|
|
30
30
|
*/
|
|
31
|
-
parent?: TNodeType
|
|
32
|
-
}) => TChildren
|
|
33
|
-
}
|
|
31
|
+
parent?: TNodeType
|
|
32
|
+
}) => TChildren
|
|
33
|
+
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Props for a mark renderer
|
|
@@ -39,20 +39,20 @@ export type MarkProps<TMarkType = any, TChildren = any, TNodeType = any> = {
|
|
|
39
39
|
/**
|
|
40
40
|
* The current mark to render
|
|
41
41
|
*/
|
|
42
|
-
mark: TMarkType
|
|
42
|
+
mark: TMarkType
|
|
43
43
|
/**
|
|
44
44
|
* The children of the current mark
|
|
45
45
|
*/
|
|
46
|
-
children?: TChildren
|
|
46
|
+
children?: TChildren
|
|
47
47
|
/**
|
|
48
48
|
* The node the current mark is applied to
|
|
49
49
|
*/
|
|
50
|
-
node: TNodeType
|
|
50
|
+
node: TNodeType
|
|
51
51
|
/**
|
|
52
52
|
* The node the current mark is applied to
|
|
53
53
|
*/
|
|
54
|
-
parent?: TNodeType
|
|
55
|
-
}
|
|
54
|
+
parent?: TNodeType
|
|
55
|
+
}
|
|
56
56
|
|
|
57
57
|
export type TiptapStaticRendererOptions<
|
|
58
58
|
/**
|
|
@@ -67,40 +67,40 @@ export type TiptapStaticRendererOptions<
|
|
|
67
67
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
68
68
|
*/
|
|
69
69
|
TNodeType extends {
|
|
70
|
-
content?: { forEach: (cb: (node: TNodeType) => void) => void }
|
|
71
|
-
marks?: readonly TMarkType[]
|
|
72
|
-
type: string | { name: string }
|
|
70
|
+
content?: { forEach: (cb: (node: TNodeType) => void) => void }
|
|
71
|
+
marks?: readonly TMarkType[]
|
|
72
|
+
type: string | { name: string }
|
|
73
73
|
} = NodeType,
|
|
74
74
|
/**
|
|
75
75
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
76
76
|
*/
|
|
77
77
|
TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (
|
|
78
|
-
ctx: NodeProps<TNodeType, TReturnType | TReturnType[]
|
|
78
|
+
ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,
|
|
79
79
|
) => TReturnType,
|
|
80
80
|
/**
|
|
81
81
|
* A mark renderer is a function that takes a mark and its children and returns the rendered output
|
|
82
82
|
*/
|
|
83
83
|
TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => TReturnType = (
|
|
84
|
-
ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType
|
|
84
|
+
ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,
|
|
85
85
|
) => TReturnType,
|
|
86
86
|
> = {
|
|
87
87
|
/**
|
|
88
88
|
* Mapping of node types to react components
|
|
89
89
|
*/
|
|
90
|
-
nodeMapping: Record<string, TNodeRender
|
|
90
|
+
nodeMapping: Record<string, NoInfer<TNodeRender>>
|
|
91
91
|
/**
|
|
92
92
|
* Mapping of mark types to react components
|
|
93
93
|
*/
|
|
94
|
-
markMapping: Record<string, TMarkRender
|
|
94
|
+
markMapping: Record<string, NoInfer<TMarkRender>>
|
|
95
95
|
/**
|
|
96
96
|
* Component to render if a node type is not handled
|
|
97
97
|
*/
|
|
98
|
-
unhandledNode?: TNodeRender
|
|
98
|
+
unhandledNode?: NoInfer<TNodeRender>
|
|
99
99
|
/**
|
|
100
100
|
* Component to render if a mark type is not handled
|
|
101
101
|
*/
|
|
102
|
-
unhandledMark?: TMarkRender
|
|
103
|
-
}
|
|
102
|
+
unhandledMark?: NoInfer<TMarkRender>
|
|
103
|
+
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Tiptap Static Renderer
|
|
@@ -126,22 +126,21 @@ export function TiptapStaticRenderer<
|
|
|
126
126
|
* A node type is either a JSON representation of a node or a Prosemirror node instance
|
|
127
127
|
*/
|
|
128
128
|
TNodeType extends {
|
|
129
|
-
content?: { forEach:(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
type: string | { name: string };
|
|
129
|
+
content?: { forEach: (cb: (node: TNodeType) => void) => void }
|
|
130
|
+
marks?: readonly TMarkType[]
|
|
131
|
+
type: string | { name: string }
|
|
133
132
|
} = NodeType,
|
|
134
133
|
/**
|
|
135
134
|
* A node renderer is a function that takes a node and its children and returns the rendered output
|
|
136
135
|
*/
|
|
137
136
|
TNodeRender extends (ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>) => TReturnType = (
|
|
138
|
-
ctx: NodeProps<TNodeType, TReturnType | TReturnType[]
|
|
137
|
+
ctx: NodeProps<TNodeType, TReturnType | TReturnType[]>,
|
|
139
138
|
) => TReturnType,
|
|
140
139
|
/**
|
|
141
140
|
* A mark renderer is a function that takes a mark and its children and returns the rendered output
|
|
142
141
|
*/
|
|
143
142
|
TMarkRender extends (ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>) => TReturnType = (
|
|
144
|
-
ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType
|
|
143
|
+
ctx: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>,
|
|
145
144
|
) => TReturnType,
|
|
146
145
|
>(
|
|
147
146
|
/**
|
|
@@ -150,13 +149,13 @@ cb: (node: TNodeType) => void) => void };
|
|
|
150
149
|
renderComponent: (
|
|
151
150
|
ctx:
|
|
152
151
|
| {
|
|
153
|
-
component: TNodeRender
|
|
154
|
-
props: NodeProps<TNodeType, TReturnType | TReturnType[]
|
|
152
|
+
component: TNodeRender
|
|
153
|
+
props: NodeProps<TNodeType, TReturnType | TReturnType[]>
|
|
155
154
|
}
|
|
156
155
|
| {
|
|
157
|
-
component: TMarkRender
|
|
158
|
-
props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType
|
|
159
|
-
}
|
|
156
|
+
component: TMarkRender
|
|
157
|
+
props: MarkProps<TMarkType, TReturnType | TReturnType[], TNodeType>
|
|
158
|
+
},
|
|
160
159
|
) => TReturnType,
|
|
161
160
|
{
|
|
162
161
|
nodeMapping,
|
|
@@ -175,11 +174,11 @@ cb: (node: TNodeType) => void) => void };
|
|
|
175
174
|
/**
|
|
176
175
|
* Tiptap JSON content to render
|
|
177
176
|
*/
|
|
178
|
-
content: TNodeType
|
|
177
|
+
content: TNodeType
|
|
179
178
|
/**
|
|
180
179
|
* The parent node of the current node
|
|
181
180
|
*/
|
|
182
|
-
parent?: TNodeType
|
|
181
|
+
parent?: TNodeType
|
|
183
182
|
}): TReturnType {
|
|
184
183
|
const nodeType = typeof content.type === 'string' ? content.type : content.type.name
|
|
185
184
|
const NodeHandler = nodeMapping[nodeType] ?? unhandledNode
|
|
@@ -218,23 +217,23 @@ cb: (node: TNodeType) => void) => void };
|
|
|
218
217
|
// apply marks to the content
|
|
219
218
|
const markedContent = content.marks
|
|
220
219
|
? content.marks.reduce((acc, mark) => {
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
const markType = typeof mark.type === 'string' ? mark.type : mark.type.name
|
|
221
|
+
const MarkHandler = markMapping[markType] ?? unhandledMark
|
|
223
222
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
if (!MarkHandler) {
|
|
224
|
+
throw new Error(`missing handler for mark type ${markType}`)
|
|
225
|
+
}
|
|
227
226
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
227
|
+
return renderComponent({
|
|
228
|
+
component: MarkHandler,
|
|
229
|
+
props: {
|
|
230
|
+
mark,
|
|
231
|
+
parent,
|
|
232
|
+
node: content,
|
|
233
|
+
children: acc,
|
|
234
|
+
},
|
|
235
|
+
})
|
|
236
|
+
}, nodeContent)
|
|
238
237
|
: nodeContent
|
|
239
238
|
|
|
240
239
|
return markedContent
|
|
@@ -20,7 +20,7 @@ import { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'
|
|
|
20
20
|
import { getHTMLAttributes } from '../helpers.js'
|
|
21
21
|
import { MarkProps, NodeProps, TiptapStaticRendererOptions } from '../json/renderer.js'
|
|
22
22
|
|
|
23
|
-
export type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T
|
|
23
|
+
export type DomOutputSpecToElement<T> = (content: DOMOutputSpec) => (children?: T | T[]) => T
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* This takes a NodeExtension and maps it to a React component
|
|
@@ -41,11 +41,7 @@ export function mapNodeExtensionToReactNode<T>(
|
|
|
41
41
|
parent: extension.parent,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const renderToHTML = getExtensionField<NodeConfig['renderHTML']>(
|
|
45
|
-
extension,
|
|
46
|
-
'renderHTML',
|
|
47
|
-
context,
|
|
48
|
-
)
|
|
44
|
+
const renderToHTML = getExtensionField<NodeConfig['renderHTML']>(extension, 'renderHTML', context)
|
|
49
45
|
|
|
50
46
|
if (!renderToHTML) {
|
|
51
47
|
if (options?.unhandledNode) {
|
|
@@ -102,11 +98,7 @@ export function mapMarkExtensionToReactNode<T>(
|
|
|
102
98
|
parent: extension.parent,
|
|
103
99
|
}
|
|
104
100
|
|
|
105
|
-
const renderToHTML = getExtensionField<MarkConfig['renderHTML']>(
|
|
106
|
-
extension,
|
|
107
|
-
'renderHTML',
|
|
108
|
-
context,
|
|
109
|
-
)
|
|
101
|
+
const renderToHTML = getExtensionField<MarkConfig['renderHTML']>(extension, 'renderHTML', context)
|
|
110
102
|
|
|
111
103
|
if (!renderToHTML) {
|
|
112
104
|
if (options?.unhandledMark) {
|
|
@@ -115,9 +107,7 @@ export function mapMarkExtensionToReactNode<T>(
|
|
|
115
107
|
return [
|
|
116
108
|
extension.name,
|
|
117
109
|
() => {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`,
|
|
120
|
-
)
|
|
110
|
+
throw new Error(`Node ${extension.name} cannot be rendered, it is missing a "renderToHTML" method`)
|
|
121
111
|
},
|
|
122
112
|
]
|
|
123
113
|
}
|
|
@@ -162,15 +152,15 @@ export function renderToElement<T>({
|
|
|
162
152
|
extensions,
|
|
163
153
|
options,
|
|
164
154
|
}: {
|
|
165
|
-
renderer: (options: TiptapStaticRendererOptions<T, Mark, Node>) => (ctx: { content: Node }) => T
|
|
166
|
-
domOutputSpecToElement: DomOutputSpecToElement<T
|
|
155
|
+
renderer: (options: TiptapStaticRendererOptions<T, Mark, Node>) => (ctx: { content: Node }) => T
|
|
156
|
+
domOutputSpecToElement: DomOutputSpecToElement<T>
|
|
167
157
|
mapDefinedTypes: {
|
|
168
|
-
doc: (props: NodeProps<Node, T | T[]>) => T
|
|
169
|
-
text: (props: NodeProps<Node, T | T[]>) => T
|
|
170
|
-
}
|
|
171
|
-
content: Node | JSONContent
|
|
172
|
-
extensions: Extensions
|
|
173
|
-
options?: Partial<TiptapStaticRendererOptions<T, Mark, Node
|
|
158
|
+
doc: (props: NodeProps<Node, T | T[]>) => T
|
|
159
|
+
text: (props: NodeProps<Node, T | T[]>) => T
|
|
160
|
+
}
|
|
161
|
+
content: Node | JSONContent
|
|
162
|
+
extensions: Extensions
|
|
163
|
+
options?: Partial<TiptapStaticRendererOptions<T, Mark, Node>>
|
|
174
164
|
}): T {
|
|
175
165
|
// get all extensions in order & split them into nodes and marks
|
|
176
166
|
extensions = resolveExtensions(extensions)
|
|
@@ -197,12 +187,9 @@ export function renderToElement<T>({
|
|
|
197
187
|
}
|
|
198
188
|
return true
|
|
199
189
|
})
|
|
200
|
-
.map(nodeExtension =>
|
|
201
|
-
domOutputSpecToElement,
|
|
202
|
-
|
|
203
|
-
extensionAttributes,
|
|
204
|
-
options,
|
|
205
|
-
)),
|
|
190
|
+
.map(nodeExtension =>
|
|
191
|
+
mapNodeExtensionToReactNode<T>(domOutputSpecToElement, nodeExtension, extensionAttributes, options),
|
|
192
|
+
),
|
|
206
193
|
),
|
|
207
194
|
...mapDefinedTypes,
|
|
208
195
|
...options?.nodeMapping,
|
|
@@ -217,12 +204,7 @@ export function renderToElement<T>({
|
|
|
217
204
|
}
|
|
218
205
|
return true
|
|
219
206
|
})
|
|
220
|
-
.map(mark => mapMarkExtensionToReactNode<T>(
|
|
221
|
-
domOutputSpecToElement,
|
|
222
|
-
mark,
|
|
223
|
-
extensionAttributes,
|
|
224
|
-
options,
|
|
225
|
-
)),
|
|
207
|
+
.map(mark => mapMarkExtensionToReactNode<T>(domOutputSpecToElement, mark, extensionAttributes, options)),
|
|
226
208
|
),
|
|
227
209
|
...options?.markMapping,
|
|
228
210
|
},
|
|
@@ -1,50 +1,34 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Extensions, JSONContent } from '@tiptap/core'
|
|
2
|
+
import type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'
|
|
3
3
|
import type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
renderJSONContentToString,
|
|
7
|
+
serializeAttrsToHTMLString,
|
|
8
|
+
serializeChildrenToHTMLString,
|
|
9
|
+
} from '../../json/html-string/string.js'
|
|
6
10
|
import { TiptapStaticRendererOptions } from '../../json/renderer.js'
|
|
7
|
-
import type { DOMOutputSpecArray } from '../../types.js'
|
|
8
11
|
import { renderToElement } from '../extensionRenderer.js'
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
* Serialize the attributes of a node or mark to a string
|
|
12
|
-
* @param attrs The attributes to serialize
|
|
13
|
-
* @returns The serialized attributes as a string
|
|
14
|
-
*/
|
|
15
|
-
export function serializeAttrsToHTMLString(attrs: Record<string, any>): string {
|
|
16
|
-
const output = Object.entries(attrs)
|
|
17
|
-
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
|
|
18
|
-
.join(' ')
|
|
19
|
-
|
|
20
|
-
return output ? ` ${output}` : ''
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Serialize the children of a node or mark to a string
|
|
25
|
-
* @param children The children to serialize
|
|
26
|
-
* @returns The serialized children as a string
|
|
27
|
-
*/
|
|
28
|
-
export function serializeChildrenToHTMLString(children?: string | string[]): string {
|
|
29
|
-
return ([] as string[])
|
|
30
|
-
.concat(children || '')
|
|
31
|
-
.filter(Boolean)
|
|
32
|
-
.join('')
|
|
33
|
-
}
|
|
13
|
+
export { serializeAttrsToHTMLString, serializeChildrenToHTMLString } from '../../json/html-string/string.js'
|
|
34
14
|
|
|
35
15
|
/**
|
|
36
16
|
* Take a DOMOutputSpec and return a function that can render it to a string
|
|
37
17
|
* @param content The DOMOutputSpec to convert to a string
|
|
38
18
|
* @returns A function that can render the DOMOutputSpec to a string
|
|
39
19
|
*/
|
|
40
|
-
export function domOutputSpecToHTMLString(
|
|
41
|
-
content: DOMOutputSpec,
|
|
42
|
-
): (children?: string | string[]) => string {
|
|
20
|
+
export function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: string | string[]) => string {
|
|
43
21
|
if (typeof content === 'string') {
|
|
44
22
|
return () => content
|
|
45
23
|
}
|
|
46
24
|
if (typeof content === 'object' && 'length' in content) {
|
|
47
|
-
const [
|
|
25
|
+
const [_tag, attrs, children, ...rest] = content as DOMOutputSpecArray
|
|
26
|
+
let tag = _tag
|
|
27
|
+
const parts = tag.split(' ')
|
|
28
|
+
|
|
29
|
+
if (parts.length > 1) {
|
|
30
|
+
tag = `${parts[1]} xmlns="${parts[0]}"`
|
|
31
|
+
}
|
|
48
32
|
|
|
49
33
|
if (attrs === undefined) {
|
|
50
34
|
return () => `<${tag}/>`
|
|
@@ -60,29 +44,29 @@ export function domOutputSpecToHTMLString(
|
|
|
60
44
|
if (children === 0) {
|
|
61
45
|
return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`
|
|
62
46
|
}
|
|
63
|
-
return child =>
|
|
64
|
-
|
|
65
|
-
|
|
47
|
+
return child =>
|
|
48
|
+
`<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}${[children]
|
|
49
|
+
.concat(rest)
|
|
50
|
+
.map(a => domOutputSpecToHTMLString(a)(child))}</${tag}>`
|
|
66
51
|
}
|
|
67
52
|
if (children === undefined) {
|
|
68
53
|
return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`
|
|
69
54
|
}
|
|
70
55
|
if (children === 0) {
|
|
71
|
-
return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(
|
|
72
|
-
child,
|
|
73
|
-
)}</${tag}>`
|
|
56
|
+
return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`
|
|
74
57
|
}
|
|
75
58
|
|
|
76
|
-
return child =>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
59
|
+
return child =>
|
|
60
|
+
`<${tag}${serializeAttrsToHTMLString(attrs)}>${[children]
|
|
61
|
+
.concat(rest)
|
|
62
|
+
.map(a => domOutputSpecToHTMLString(a)(child))
|
|
63
|
+
.join('')}</${tag}>`
|
|
80
64
|
}
|
|
81
65
|
}
|
|
82
66
|
|
|
83
67
|
// TODO support DOM elements? How to handle them?
|
|
84
68
|
throw new Error(
|
|
85
|
-
'[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output',
|
|
69
|
+
'[tiptap error]: Unsupported DomOutputSpec type, check the `renderHTML` method output or implement a node mapping',
|
|
86
70
|
{
|
|
87
71
|
cause: content,
|
|
88
72
|
},
|
|
@@ -101,9 +85,9 @@ export function renderToHTMLString({
|
|
|
101
85
|
extensions,
|
|
102
86
|
options,
|
|
103
87
|
}: {
|
|
104
|
-
content: Node | JSONContent
|
|
105
|
-
extensions: Extensions
|
|
106
|
-
options?: Partial<TiptapStaticRendererOptions<string, Mark, Node
|
|
88
|
+
content: Node | JSONContent
|
|
89
|
+
extensions: Extensions
|
|
90
|
+
options?: Partial<TiptapStaticRendererOptions<string, Mark, Node>>
|
|
107
91
|
}): string {
|
|
108
92
|
return renderToElement<string>({
|
|
109
93
|
renderer: renderJSONContentToString,
|