diff --git a/docs/src/demos/Guide/Content/GenerateJSON/index.spec.js b/docs/src/demos/Guide/Content/GenerateJSON/index.spec.js
new file mode 100644
index 00000000..78d6813c
--- /dev/null
+++ b/docs/src/demos/Guide/Content/GenerateJSON/index.spec.js
@@ -0,0 +1,7 @@
+context('/demos/Guide/Content/GenerateJSON', () => {
+ before(() => {
+ cy.visit('/demos/Guide/Content/GenerateJSON')
+ })
+
+ // TODO: Write tests
+})
diff --git a/docs/src/demos/Guide/Content/GenerateJSON/index.vue b/docs/src/demos/Guide/Content/GenerateJSON/index.vue
new file mode 100644
index 00000000..4ecf7034
--- /dev/null
+++ b/docs/src/demos/Guide/Content/GenerateJSON/index.vue
@@ -0,0 +1,27 @@
+
+ {{ output }}
+
+
+
diff --git a/docs/src/docPages/api/utilities/html.md b/docs/src/docPages/api/utilities/html.md
index de242ae8..13de12e7 100644
--- a/docs/src/docPages/api/utilities/html.md
+++ b/docs/src/docPages/api/utilities/html.md
@@ -9,3 +9,7 @@ The utility helps rendering JSON content as HTML without an editor instance, for
## Usage
+
+By the way, the other way is possible, too. The below examples shows how to generate JSON from HTML.
+
+
diff --git a/docs/src/docPages/guide/output.md b/docs/src/docPages/guide/output.md
index 7c587ecd..9771ec3b 100644
--- a/docs/src/docPages/guide/output.md
+++ b/docs/src/docPages/guide/output.md
@@ -117,7 +117,11 @@ If you need to render the content on the server side, for example to generate th
That’s what the `generateHTML()` is for. It’s a helper function which renders HTML without an actual editor instance.
-
+
+
+By the way, the other way is possible, too. The below examples shows how to generate JSON from HTML.
+
+
## Migration
If you’re migrating existing content to tiptap we would recommend to get your existing output to HTML. That’s probably the best format to get your initial content into tiptap, because ProseMirror ensures there is nothing wrong with it. Even if there are some tags or attributes that aren’t allowed (based on your configuration), tiptap just throws them away quietly.
diff --git a/packages/core/src/helpers/generateJSON.ts b/packages/core/src/helpers/generateJSON.ts
new file mode 100644
index 00000000..ec025f49
--- /dev/null
+++ b/packages/core/src/helpers/generateJSON.ts
@@ -0,0 +1,13 @@
+import { DOMParser } from 'prosemirror-model'
+import getSchema from './getSchema'
+import elementFromString from '../utilities/elementFromString'
+import { Extensions } from '../types'
+
+export default function generateJSON(html: string, extensions: Extensions): Record {
+ const schema = getSchema(extensions)
+ const dom = elementFromString(html)
+
+ return DOMParser.fromSchema(schema)
+ .parse(dom)
+ .toJSON()
+}
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 276f58af..a5043d6b 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -18,6 +18,7 @@ export { default as findChildren } from './helpers/findChildren'
export { default as findParentNode } from './helpers/findParentNode'
export { default as findParentNodeClosestToPos } from './helpers/findParentNodeClosestToPos'
export { default as generateHTML } from './helpers/generateHTML'
+export { default as generateJSON } from './helpers/generateJSON'
export { default as getSchema } from './helpers/getSchema'
export { default as getHTMLFromFragment } from './helpers/getHTMLFromFragment'
export { default as getMarkAttributes } from './helpers/getMarkAttributes'
diff --git a/tests/cypress/integration/core/generateJSON.spec.ts b/tests/cypress/integration/core/generateJSON.spec.ts
new file mode 100644
index 00000000..57f96421
--- /dev/null
+++ b/tests/cypress/integration/core/generateJSON.spec.ts
@@ -0,0 +1,29 @@
+///
+
+import { generateJSON } from '@tiptap/core'
+import Document from '@tiptap/extension-document'
+import Paragraph from '@tiptap/extension-paragraph'
+import Text from '@tiptap/extension-text'
+
+describe('generateJSON', () => {
+ it('generate HTML from JSON without an editor instance', () => {
+ const html = 'Example Text
'
+
+ const json = generateJSON(html, [
+ Document,
+ Paragraph,
+ Text,
+ ])
+
+ expect(JSON.stringify(json)).to.eq(JSON.stringify({
+ type: 'doc',
+ content: [{
+ type: 'paragraph',
+ content: [{
+ type: 'text',
+ text: 'Example Text',
+ }],
+ }],
+ }))
+ })
+})