@tiptap/static-renderer 3.23.6 → 3.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +33 -0
  2. package/dist/index.cjs +59 -17
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +57 -7
  5. package/dist/index.d.ts +57 -7
  6. package/dist/index.js +62 -18
  7. package/dist/index.js.map +1 -1
  8. package/dist/json/html-string/index.cjs +1 -1
  9. package/dist/json/html-string/index.cjs.map +1 -1
  10. package/dist/json/html-string/index.js +1 -1
  11. package/dist/json/html-string/index.js.map +1 -1
  12. package/dist/json/react/index.cjs +11 -8
  13. package/dist/json/react/index.cjs.map +1 -1
  14. package/dist/json/react/index.js +11 -8
  15. package/dist/json/react/index.js.map +1 -1
  16. package/dist/json/renderer.cjs.map +1 -1
  17. package/dist/json/renderer.js.map +1 -1
  18. package/dist/pm/html-string/index.cjs +42 -6
  19. package/dist/pm/html-string/index.cjs.map +1 -1
  20. package/dist/pm/html-string/index.d.cts +42 -4
  21. package/dist/pm/html-string/index.d.ts +42 -4
  22. package/dist/pm/html-string/index.js +45 -7
  23. package/dist/pm/html-string/index.js.map +1 -1
  24. package/dist/pm/markdown/index.cjs +46 -8
  25. package/dist/pm/markdown/index.cjs.map +1 -1
  26. package/dist/pm/markdown/index.d.cts +37 -3
  27. package/dist/pm/markdown/index.d.ts +37 -3
  28. package/dist/pm/markdown/index.js +49 -9
  29. package/dist/pm/markdown/index.js.map +1 -1
  30. package/dist/pm/react/index.cjs +41 -12
  31. package/dist/pm/react/index.cjs.map +1 -1
  32. package/dist/pm/react/index.d.cts +38 -4
  33. package/dist/pm/react/index.d.ts +38 -4
  34. package/dist/pm/react/index.js +44 -13
  35. package/dist/pm/react/index.js.map +1 -1
  36. package/package.json +21 -22
  37. package/src/helpers.ts +22 -6
  38. package/src/json/html-string/string.ts +4 -1
  39. package/src/json/react/react.ts +12 -9
  40. package/src/json/renderer.ts +7 -3
  41. package/src/pm/extensionRenderer.ts +62 -5
  42. package/src/pm/html-string/html-string.ts +40 -10
  43. package/src/pm/markdown/markdown.ts +11 -2
  44. package/src/pm/react/react.ts +27 -10
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
1
+ /* oslint-disableno-explicit-any */
2
2
  import type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'
3
3
  import type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'
4
4
 
@@ -9,22 +9,38 @@ import {
9
9
  serializeChildrenToHTMLString,
10
10
  } from '../../json/html-string/string.js'
11
11
  import type { TiptapStaticRendererOptions } from '../../json/renderer.js'
12
- import { renderToElement } from '../extensionRenderer.js'
12
+ import type { StaticEditorOptions } from '../extensionRenderer.js'
13
+ import { applyStaticEditorOptionsToExtensions, renderToElement } from '../extensionRenderer.js'
13
14
 
14
- export { serializeAttrsToHTMLString, serializeChildrenToHTMLString } from '../../json/html-string/string.js'
15
+ export {
16
+ serializeAttrsToHTMLString,
17
+ serializeChildrenToHTMLString,
18
+ } from '../../json/html-string/string.js'
15
19
 
16
20
  /**
17
21
  * HTML elements that cannot be self-closing and must always have a closing tag.
18
22
  * These elements must be rendered as <tag></tag> even when empty, not <tag />.
19
23
  */
20
- const NON_SELF_CLOSING_TAGS = new Set(['iframe', 'script', 'style', 'title', 'textarea', 'div', 'span', 'a', 'button'])
24
+ const NON_SELF_CLOSING_TAGS = new Set([
25
+ 'iframe',
26
+ 'script',
27
+ 'style',
28
+ 'title',
29
+ 'textarea',
30
+ 'div',
31
+ 'span',
32
+ 'a',
33
+ 'button',
34
+ ])
21
35
 
22
36
  /**
23
37
  * Take a DOMOutputSpec and return a function that can render it to a string
24
38
  * @param content The DOMOutputSpec to convert to a string
25
39
  * @returns A function that can render the DOMOutputSpec to a string
26
40
  */
27
- export function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: string | string[]) => string {
41
+ export function domOutputSpecToHTMLString(
42
+ content: DOMOutputSpec,
43
+ ): (children?: string | string[]) => string {
28
44
  if (typeof content === 'string') {
29
45
  return () => escapeHTML(content)
30
46
  }
@@ -46,10 +62,12 @@ export function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: s
46
62
  if (typeof attrs === 'object') {
47
63
  if (Array.isArray(attrs)) {
48
64
  if (children === undefined) {
49
- return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`
65
+ return child =>
66
+ `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`
50
67
  }
51
68
  if (children === 0) {
52
- return child => `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`
69
+ return child =>
70
+ `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}</${tag}>`
53
71
  }
54
72
  return child =>
55
73
  `<${tag}>${domOutputSpecToHTMLString(attrs as DOMOutputSpecArray)(child)}${[children]
@@ -63,7 +81,8 @@ export function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: s
63
81
  return () => `<${tag}${serializeAttrsToHTMLString(attrs)}/>`
64
82
  }
65
83
  if (children === 0) {
66
- return child => `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`
84
+ return child =>
85
+ `<${tag}${serializeAttrsToHTMLString(attrs)}>${serializeChildrenToHTMLString(child)}</${tag}>`
67
86
  }
68
87
 
69
88
  return child =>
@@ -84,19 +103,30 @@ export function domOutputSpecToHTMLString(content: DOMOutputSpec): (children?: s
84
103
  }
85
104
 
86
105
  /**
87
- * This function will statically render a Prosemirror Node to HTML using the provided extensions and options
106
+ * This function will statically render a Prosemirror Node to HTML using the provided extensions and options.
107
+ *
108
+ * Limitations: this function builds the schema and runs each extension's
109
+ * `renderHTML`, but does not instantiate an `Editor`. Extensions that mutate
110
+ * the document inside `addProseMirrorPlugins`, `onCreate`, or transaction
111
+ * hooks will not run. For UniqueID, pre-process the JSON with
112
+ * `generateUniqueIds` from `@tiptap/extension-unique-id`; for TableOfContents,
113
+ * pre-process with `generateTocIds` from `@tiptap/extension-table-of-contents`.
114
+ *
88
115
  * @param content The content to render to HTML
89
116
  * @param extensions The extensions to use for rendering
117
+ * @param staticEditorOptions Optional editor-level options that affect rendered output, currently `{ textDirection }`. Mirrors a subset of `EditorOptions`.
90
118
  * @param options The options to use for rendering
91
119
  * @returns The rendered HTML string
92
120
  */
93
121
  export function renderToHTMLString({
94
122
  content,
95
123
  extensions,
124
+ staticEditorOptions,
96
125
  options,
97
126
  }: {
98
127
  content: Node | JSONContent
99
128
  extensions: Extensions
129
+ staticEditorOptions?: StaticEditorOptions
100
130
  options?: Partial<TiptapStaticRendererOptions<string, Mark, Node>>
101
131
  }): string {
102
132
  return renderToElement<string>({
@@ -109,7 +139,7 @@ export function renderToHTMLString({
109
139
  text: ({ node }) => escapeHTML(node.text ?? ''),
110
140
  },
111
141
  content,
112
- extensions,
142
+ extensions: applyStaticEditorOptionsToExtensions(extensions, staticEditorOptions),
113
143
  options,
114
144
  })
115
145
  }
@@ -2,24 +2,33 @@ import type { Extensions, JSONContent } from '@tiptap/core'
2
2
  import type { Mark, Node } from '@tiptap/pm/model'
3
3
 
4
4
  import type { TiptapStaticRendererOptions } from '../../json/renderer.js'
5
+ import type { StaticEditorOptions } from '../extensionRenderer.js'
5
6
  import { renderToHTMLString, serializeChildrenToHTMLString } from '../html-string/html-string.js'
6
7
 
7
8
  /**
8
9
  * This code is just to show the flexibility of this renderer. We can potentially render content to any format we want.
9
10
  * This is a simple example of how we can render content to markdown. This is not a full implementation of a markdown renderer.
11
+ *
12
+ * Limitations: see `renderToHTMLString` — extensions that mutate the document
13
+ * via plugins/onCreate (UniqueID, TableOfContents) need to be pre-processed.
14
+ *
15
+ * @param staticEditorOptions Optional editor-level options that affect rendered output — mirrors a subset of `EditorOptions`.
10
16
  */
11
17
  export function renderToMarkdown({
12
18
  content,
13
19
  extensions,
20
+ staticEditorOptions,
14
21
  options,
15
22
  }: {
16
23
  content: Node | JSONContent
17
24
  extensions: Extensions
25
+ staticEditorOptions?: StaticEditorOptions
18
26
  options?: Partial<TiptapStaticRendererOptions<string, Mark, Node>>
19
27
  }) {
20
28
  return renderToHTMLString({
21
29
  content,
22
30
  extensions,
31
+ staticEditorOptions,
23
32
  options: {
24
33
  ...options,
25
34
  nodeMapping: {
@@ -53,7 +62,7 @@ export function renderToMarkdown({
53
62
  heading({ node, children }) {
54
63
  const level = node.attrs.level as number
55
64
 
56
- return `${new Array(level).fill('#').join('')} ${children}\n`
65
+ return `${Array.from<string>({ length: level }).fill('#').join('')} ${children}\n`
57
66
  },
58
67
  codeBlock({ node, children }) {
59
68
  return `\n\`\`\`${node.attrs.language}\n${serializeChildrenToHTMLString(children)}\n\`\`\`\n`
@@ -80,7 +89,7 @@ export function renderToMarkdown({
80
89
  }
81
90
 
82
91
  const columnCount = node.children[0].childCount
83
- return `\n${serializeChildrenToHTMLString(children[0])}| ${new Array(columnCount).fill('---').join(' | ')} |\n${serializeChildrenToHTMLString(children.slice(1))}\n`
92
+ return `\n${serializeChildrenToHTMLString(children[0])}| ${Array.from<string>({ length: columnCount }).fill('---').join(' | ')} |\n${serializeChildrenToHTMLString(children.slice(1))}\n`
84
93
  },
85
94
  tableRow({ children }) {
86
95
  if (Array.isArray(children)) {
@@ -1,11 +1,12 @@
1
- /* eslint-disable no-plusplus, @typescript-eslint/no-explicit-any */
1
+ /* oslint-disable no-plusplus,no-explicit-any */
2
2
  import type { DOMOutputSpecArray, Extensions, JSONContent } from '@tiptap/core'
3
3
  import type { DOMOutputSpec, Mark, Node } from '@tiptap/pm/model'
4
4
  import React from 'react'
5
5
 
6
6
  import { renderJSONContentToReactElement } from '../../json/react/react.js'
7
7
  import type { TiptapStaticRendererOptions } from '../../json/renderer.js'
8
- import { renderToElement } from '../extensionRenderer.js'
8
+ import type { StaticEditorOptions } from '../extensionRenderer.js'
9
+ import { applyStaticEditorOptionsToExtensions, renderToElement } from '../extensionRenderer.js'
9
10
 
10
11
  /**
11
12
  * This function maps the attributes of a node or mark to HTML attributes
@@ -13,7 +14,10 @@ import { renderToElement } from '../extensionRenderer.js'
13
14
  * @param key The key to use for the React element
14
15
  * @returns The mapped HTML attributes as an object
15
16
  */
16
- export function mapAttrsToHTMLAttributes(attrs?: Record<string, any>, key?: string): Record<string, any> {
17
+ export function mapAttrsToHTMLAttributes(
18
+ attrs?: Record<string, any>,
19
+ key?: string,
20
+ ): Record<string, any> {
17
21
  if (!attrs) {
18
22
  return { key }
19
23
  }
@@ -58,7 +62,7 @@ export function domOutputSpecToReactElement(
58
62
  return () => content
59
63
  }
60
64
  if (typeof content === 'object' && 'length' in content) {
61
- // eslint-disable-next-line prefer-const
65
+ // oxlint-disable-next-line prefer-const
62
66
  let [tag, attrs, children, ...rest] = content as DOMOutputSpecArray
63
67
  const parts = tag.split(' ')
64
68
 
@@ -84,7 +88,8 @@ export function domOutputSpecToReactElement(
84
88
  return () => React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()))
85
89
  }
86
90
  if (attrs === 0) {
87
- return child => React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()), child)
91
+ return child =>
92
+ React.createElement(tag, mapAttrsToHTMLAttributes(undefined, key.toString()), child)
88
93
  }
89
94
  if (typeof attrs === 'object') {
90
95
  if (Array.isArray(attrs)) {
@@ -109,21 +114,26 @@ export function domOutputSpecToReactElement(
109
114
  tag,
110
115
  mapAttrsToHTMLAttributes(undefined, key.toString()),
111
116
  domOutputSpecToReactElement(attrs as DOMOutputSpecArray)(child),
112
- [children].concat(rest).map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),
117
+ [children]
118
+ .concat(rest)
119
+ .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),
113
120
  )
114
121
  }
115
122
  if (children === undefined) {
116
123
  return () => React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()))
117
124
  }
118
125
  if (children === 0) {
119
- return child => React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()), child)
126
+ return child =>
127
+ React.createElement(tag, mapAttrsToHTMLAttributes(attrs, key.toString()), child)
120
128
  }
121
129
 
122
130
  return child =>
123
131
  React.createElement(
124
132
  tag,
125
133
  mapAttrsToHTMLAttributes(attrs, key.toString()),
126
- [children].concat(rest).map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),
134
+ [children]
135
+ .concat(rest)
136
+ .map(outputSpec => domOutputSpecToReactElement(outputSpec, key++)(child)),
127
137
  )
128
138
  }
129
139
  }
@@ -138,19 +148,26 @@ export function domOutputSpecToReactElement(
138
148
  }
139
149
 
140
150
  /**
141
- * This function will statically render a Prosemirror Node to a React component using the given extensions
151
+ * This function will statically render a Prosemirror Node to a React component using the given extensions.
152
+ *
153
+ * Limitations: see `renderToHTMLString` — extensions that mutate the document
154
+ * via plugins/onCreate (UniqueID, TableOfContents) need to be pre-processed.
155
+ *
142
156
  * @param content The content to render to a React component
143
157
  * @param extensions The extensions to use for rendering
158
+ * @param staticEditorOptions Optional editor-level options that affect rendered output — mirrors a subset of `EditorOptions`.
144
159
  * @param options The options to use for rendering
145
160
  * @returns The React element that represents the rendered content
146
161
  */
147
162
  export function renderToReactElement({
148
163
  content,
149
164
  extensions,
165
+ staticEditorOptions,
150
166
  options,
151
167
  }: {
152
168
  content: Node | JSONContent
153
169
  extensions: Extensions
170
+ staticEditorOptions?: StaticEditorOptions
154
171
  options?: Partial<TiptapStaticRendererOptions<React.ReactNode, Mark, Node>>
155
172
  }): React.ReactNode {
156
173
  return renderToElement<React.ReactNode>({
@@ -163,7 +180,7 @@ export function renderToReactElement({
163
180
  text: ({ node }) => node.text ?? '',
164
181
  },
165
182
  content,
166
- extensions,
183
+ extensions: applyStaticEditorOptionsToExtensions(extensions, staticEditorOptions),
167
184
  options,
168
185
  })
169
186
  }