From 62c617e17b9556d0f812983c51d2721bf6447a79 Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Thu, 3 Sep 2020 16:22:08 +0200 Subject: [PATCH] add getSchema & getHtml utility functions to generate HTML from a ProseMirror/tiptap document, without an Editor instance --- docs/src/demos/Api/Schema/index.vue | 38 +++++++++++++++++++++++++ docs/src/docPages/api/schema.md | 14 +++++++++ packages/core/index.ts | 5 +++- packages/core/src/utils/generateHtml.ts | 21 ++++++++++++++ packages/core/src/utils/getSchema.ts | 35 +++++++++++++++++++++++ 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 docs/src/demos/Api/Schema/index.vue create mode 100644 packages/core/src/utils/generateHtml.ts create mode 100644 packages/core/src/utils/getSchema.ts diff --git a/docs/src/demos/Api/Schema/index.vue b/docs/src/demos/Api/Schema/index.vue new file mode 100644 index 000000000..e9f6b1d91 --- /dev/null +++ b/docs/src/demos/Api/Schema/index.vue @@ -0,0 +1,38 @@ + + + \ No newline at end of file diff --git a/docs/src/docPages/api/schema.md b/docs/src/docPages/api/schema.md index 5776e9c11..b15ae0d75 100644 --- a/docs/src/docPages/api/schema.md +++ b/docs/src/docPages/api/schema.md @@ -1,5 +1,19 @@ # Schema +## Get the ProseMirror schema without initializing the editor + +```js +import { getSchema } from '@tiptap/core' + +const schema = getSchema(extensions) +``` + +## Generate HTML from ProseMirror JSON without initializing the editor + + + +## Old Content + :::warning Out of date This content is written for tiptap 1 and needs an update. ::: diff --git a/packages/core/index.ts b/packages/core/index.ts index f82559e84..7571b28c6 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -8,4 +8,7 @@ export { default as Node } from './src/Node' export { default as Mark } from './src/Mark' export { default as markInputRule } from './src/inputRules/markInputRule' -export { default as markPasteRule } from './src/pasteRules/markPasteRule' \ No newline at end of file +export { default as markPasteRule } from './src/pasteRules/markPasteRule' + +export { default as getSchema } from './src/utils/getSchema' +export { default as generateHtml } from './src/utils/generateHtml' \ No newline at end of file diff --git a/packages/core/src/utils/generateHtml.ts b/packages/core/src/utils/generateHtml.ts new file mode 100644 index 000000000..ae70cbbfa --- /dev/null +++ b/packages/core/src/utils/generateHtml.ts @@ -0,0 +1,21 @@ +import Extension from '../Extension' +import Node from '../Node' +import Mark from '../Mark' +import getSchema from './getSchema' +import { Node as ProseMirrorNode, DOMSerializer } from "prosemirror-model" + +export default function generateHtml(doc: object, extensions: (Extension | Node | Mark)[]): string { + const schema = getSchema(extensions) + + let contentNode = ProseMirrorNode.fromJSON(schema, doc) + let temporaryDocument = document.implementation.createHTMLDocument() + const div = temporaryDocument.createElement('div') + + const fragment = DOMSerializer + .fromSchema(schema) + .serializeFragment(contentNode.content) + + div.appendChild(fragment) + + return div.innerHTML +} diff --git a/packages/core/src/utils/getSchema.ts b/packages/core/src/utils/getSchema.ts new file mode 100644 index 000000000..ec8bae1ca --- /dev/null +++ b/packages/core/src/utils/getSchema.ts @@ -0,0 +1,35 @@ +import Extension from '../Extension' +import Node from '../Node' +import Mark from '../Mark' +import { Schema } from 'prosemirror-model' +import collect from 'collect.js' + +export default function getSchema(extensions: (Extension | Node | Mark)[]): Schema { + return new Schema({ + topNode: getTopNodeFromExtensions(extensions), + nodes: getNodesFromExtensions(extensions), + marks: getMarksFromExtensions(extensions), + }) +} + +function getNodesFromExtensions(extensions: (Extension | Node | Mark)[]): any { + return collect(extensions) + .where('extensionType', 'node') + .mapWithKeys((extension: Node) => [extension.name, extension.schema()]) + .all() +} + +function getTopNodeFromExtensions(extensions: (Extension | Node | Mark)[]): any { + const topNode = collect(extensions).firstWhere('topNode', true) + + if (topNode) { + return topNode.name + } +} + +function getMarksFromExtensions(extensions: (Extension | Node | Mark)[]): any { + return collect(extensions) + .where('extensionType', 'mark') + .mapWithKeys((extension: Mark) => [extension.name, extension.schema()]) + .all() +}