1 import schema from "./schema";
2 import {DOMParser, DOMSerializer} from "prosemirror-model";
8 export function htmlToDoc(html) {
9 const renderDoc = document.implementation.createHTMLDocument();
10 renderDoc.body.innerHTML = html;
11 return DOMParser.fromSchema(schema).parse(renderDoc.body);
18 export function docToHtml(doc) {
19 const fragment = DOMSerializer.fromSchema(schema).serializeFragment(doc.content);
20 const renderDoc = document.implementation.createHTMLDocument();
21 renderDoc.body.appendChild(fragment);
22 return renderDoc.body.innerHTML;
26 * @param {PmEditorState} state
29 export function stateToHtml(state) {
30 const fragment = DOMSerializer.fromSchema(schema).serializeFragment(state.doc.content);
31 const renderDoc = document.implementation.createHTMLDocument();
32 renderDoc.body.appendChild(fragment);
33 return renderDoc.body.innerHTML;
37 * @param {Object} object
40 export function nullifyEmptyValues(object) {
42 for (const [key, value] of Object.entries(object)) {
43 clean[key] = (value === "") ? null : value;
49 * @param {PmEditorState} state
50 * @param {PmSelection} selection
51 * @param {PmMarkType} markType
52 * @return {{from: Number, to: Number}}
54 export function expandSelectionToMark(state, selection, markType) {
55 let {from, to} = selection;
56 const noRange = (from === to);
58 const markRange = markRangeAtPosition(state, markType, from);
59 if (markRange.from !== -1) {
60 from = markRange.from;
68 * @param {PmEditorState} state
69 * @param {PmMarkType} markType
71 * @return {{from: Number, to: Number}}
73 export function markRangeAtPosition(state, markType, pos) {
74 const $pos = state.doc.resolve(pos);
76 const {parent, parentOffset} = $pos;
77 const start = parent.childAfter(parentOffset);
78 if (!start.node) return {from: -1, to: -1};
80 const mark = start.node.marks.find((mark) => mark.type === markType);
81 if (!mark) return {from: -1, to: -1};
83 let startIndex = $pos.index();
84 let startPos = $pos.start() + start.offset;
85 let endIndex = startIndex + 1;
86 let endPos = startPos + start.node.nodeSize;
87 while (startIndex > 0 && mark.isInSet(parent.child(startIndex - 1).marks)) {
89 startPos -= parent.child(startIndex).nodeSize;
91 while (endIndex < parent.childCount && mark.isInSet(parent.child(endIndex).marks)) {
92 endPos += parent.child(endIndex).nodeSize;
95 return {from: startPos, to: endPos};
99 * @class KeyedMultiStack
100 * Holds many stacks, seperated via a key, with a simple
101 * interface to pop and push values to the stacks.
103 export class KeyedMultiStack {
110 * @param {String} key
111 * @return {undefined|*}
114 if (Array.isArray(this.stack[key])) {
115 return this.stack[key].pop();
121 * @param {String} key
125 if (this.stack[key] === undefined) {
126 this.stack[key] = [];
129 this.stack[key].push(value);