diff --git a/wax-prosemirror-core/src/Serializer.js b/wax-prosemirror-core/src/Serializer.js new file mode 100644 index 0000000000000000000000000000000000000000..6e5f911dc981bc392dda33ea9c64c9be5d32f1a6 --- /dev/null +++ b/wax-prosemirror-core/src/Serializer.js @@ -0,0 +1,74 @@ +import { DOMSerializer } from 'prosemirror-model'; + +export default class Serializer extends DOMSerializer { + constructor(props) { + super(props); + } + + serializeNode(node, options = {}) { + // console.log('hohohohho'); + // let dom = this.serializeNodeInner(node, options); + // for (let i = node.marks.length - 1; i >= 0; i--) { + // let wrap = this.serializeMark(node.marks[i], node.isInline, options); + // if (wrap) { + // (wrap.contentDOM || wrap.dom).appendChild(dom); + // dom = wrap.dom; + // } + // } + // return dom; + } + + serializeFragment(fragment, options = {}, target) { + // if (!target) target = doc(options).createDocumentFragment(); + // let top = target, + // active = null; + // fragment.forEach(node => { + // if (active || node.marks.length) { + // if (!active) active = []; + // let keep = 0, + // rendered = 0; + // while (keep < active.length && rendered < node.marks.length) { + // let next = node.marks[rendered]; + // if (!this.marks[next.type.name]) { + // rendered++; + // continue; + // } + // if (!next.eq(active[keep]) || next.type.spec.spanning === false) + // break; + // keep += 2; + // rendered++; + // } + // while (keep < active.length) { + // top = active.pop(); + // active.pop(); + // } + // while (rendered < node.marks.length) { + // let add = node.marks[rendered++]; + // let markDOM = this.serializeMark(add, node.isInline, options); + // if (markDOM) { + // active.push(add, top); + // top.appendChild(markDOM.dom); + // top = markDOM.contentDOM || markDOM.dom; + // } + // } + // } + // top.appendChild(this.serializeNodeInner(node, options)); + // }); + // return target; + } + + serializeNodeInner(node, options = {}) { + console.log('hohohohho'); + let { dom, contentDOM } = DOMSerializer.renderSpec( + doc(options), + this.nodes[node.type.name](node), + ); + if (contentDOM) { + if (node.isLeaf) + throw new RangeError('Content hole not allowed in a leaf node spec'); + if (options.onContent) options.onContent(node, contentDOM, options); + else this.serializeFragment(node.content, options, contentDOM); + } + return dom; + } +} diff --git a/wax-prosemirror-core/src/Wax.js b/wax-prosemirror-core/src/Wax.js index eae0b5ea8eb6de9bf52043a8bcbeb4bf72d1ac3b..1aa1373a3d1031f88db0f11975001ea2e39ac950 100644 --- a/wax-prosemirror-core/src/Wax.js +++ b/wax-prosemirror-core/src/Wax.js @@ -1,13 +1,13 @@ /* eslint react/prop-types: 0 */ import React, { useEffect, useState, forwardRef } from 'react'; -import { each } from 'lodash'; import { DOMSerializer } from 'prosemirror-model'; +import { DefaultSchema } from 'wax-prosemirror-utilities'; import WaxProvider from './WaxContext'; import PortalProvider from './PortalContext'; import Application from './Application'; - import WaxView from './WaxView'; +import helpers from './helpers/helpers'; const serializer = schema => { const WaxSerializer = DOMSerializer.fromSchema(schema); @@ -52,38 +52,15 @@ const Wax = forwardRef((props, ref) => { const WaxOnchange = onChange || (v => true); const finalOnChange = content => { - /* HACK alter toDOM of footnote, because of how PM treats inline nodes - with content */ const { schema } = application.schema; - const notes = []; - each(schema.nodes, node => { - if (node.groups.includes('notes')) notes.push(node); - }); - - if (notes.length > 0) { - notes.forEach(note => { - schema.nodes[note.name].spec.toDOM = node => { - // eslint-disable-next-line prefer-rest-params - if (node) return [note.name, node.attrs, 0]; - }; - }); - } - + helpers.alterNotesSchema(schema); if (targetFormat === 'JSON') { WaxOnchange(content); } else { const serialize = serializer(schema); WaxOnchange(serialize(content)); } - - if (notes.length > 0) { - notes.forEach(note => { - schema.nodes[note.name].spec.toDOM = node => { - // eslint-disable-next-line prefer-rest-params - if (node) return [note.name, node.attrs]; - }; - }); - } + helpers.revertNotesSchema(schema); }; const TrackChange = application.config.get('config.EnableTrackChangeService'); @@ -118,7 +95,7 @@ const Wax = forwardRef((props, ref) => { }); Wax.defaultProps = { - config: { services: [] }, + config: { SchemaService: DefaultSchema, services: [] }, }; export default Wax; diff --git a/wax-prosemirror-core/src/WaxView.js b/wax-prosemirror-core/src/WaxView.js index d355f3d60858ef736b5149d54bd35c06f63eacb3..3524bf11127de1431050c6eae1c0377e8b77bb63 100644 --- a/wax-prosemirror-core/src/WaxView.js +++ b/wax-prosemirror-core/src/WaxView.js @@ -18,7 +18,7 @@ import { WaxContext } from './WaxContext'; import { PortalContext } from './PortalContext'; import ComponentPlugin from './ComponentPlugin'; import WaxOptions from './WaxOptions'; -import getDocContent from './helpers/GetDocContent'; +import helpers from './helpers/helpers'; import './styles/styles.css'; const WaxPortals = ComponentPlugin('waxPortals'); @@ -111,7 +111,7 @@ const WaxView = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ getContent() { - return getDocContent(schema, serializer, targetFormat, context); + return helpers.getDocContent(schema, serializer, targetFormat, context); }, })); diff --git a/wax-prosemirror-core/src/helpers/GetDocContent.js b/wax-prosemirror-core/src/helpers/helpers.js similarity index 53% rename from wax-prosemirror-core/src/helpers/GetDocContent.js rename to wax-prosemirror-core/src/helpers/helpers.js index baa124a22942802cea67adbf77c2b0e6a746cdbe..1f5b4d5123e80dab9b0e0db111b8a7f25b87312e 100644 --- a/wax-prosemirror-core/src/helpers/GetDocContent.js +++ b/wax-prosemirror-core/src/helpers/helpers.js @@ -1,40 +1,52 @@ -/* eslint-disable consistent-return */ -/* eslint-disable no-else-return */ /* eslint-disable no-param-reassign */ import { each } from 'lodash'; -const getDocContent = (schema, serializer, targetFormat, context) => { - /* HACK alter toDOM of footnote, because of how PM treats inline nodes - with content */ - let content = ''; +const alterNotesSchema = schema => { const notes = []; each(schema.nodes, node => { if (node.groups.includes('notes')) notes.push(node); }); + if (notes.length > 0) { + notes.forEach(note => { + schema.nodes[note.name].spec.toDOM = node => { + if (node) return [note.name, node.attrs, 0]; + return true; + }; + }); + } +}; +const revertNotesSchema = schema => { + const notes = []; + each(schema.nodes, node => { + if (node.groups.includes('notes')) notes.push(node); + }); if (notes.length > 0) { notes.forEach(note => { - schema.nodes[note.name].spec.toDOM = singleNode => { - if (singleNode) return [note.name, singleNode.attrs, 0]; + schema.nodes[note.name].spec.toDOM = node => { + if (node) return [note.name, node.attrs]; + return true; }; }); } +}; +const getDocContent = (schema, serializer, targetFormat, context) => { + let content = ''; + alterNotesSchema(schema); if (targetFormat === 'JSON') { content = context.app.context.view.main.state.doc.content; } else { const serialize = serializer(schema); content = serialize(context.app.context.view.main.state.doc.content); } + revertNotesSchema(content); - if (notes.length > 0) { - notes.forEach(note => { - schema.nodes[note.name].spec.toDOM = sinlgeNode => { - if (sinlgeNode) return [note.name, sinlgeNode.attrs]; - }; - }); - } return content; }; -export default getDocContent; +export default { + alterNotesSchema, + getDocContent, + revertNotesSchema, +};