UNPKG

reactjs-tiptap-editor

Version:

A modern WYSIWYG rich text editor based on tiptap and shadcn ui for React

1,606 lines (1,605 loc) 242 kB
import L, { createContext as ln, useContext as cn, createRef as mr, memo as yr, createElement as gr, version as At, useState as vr, useLayoutEffect as wr, useEffect as Sr, useDebugValue as kr, forwardRef as xr } from "react"; import br, { flushSync as Er } from "react-dom"; import { jsx as ae, jsxs as Mr, Fragment as un } from "react/jsx-runtime"; import { NodeSelection as le, TextSelection as F, Plugin as X, PluginKey as Y, Selection as ie, AllSelection as Cr } from "@tiptap/pm/state"; import { Fragment as se, Slice as Ar, Node as Rr, Schema as Tr, DOMParser as je } from "@tiptap/pm/model"; import "@tiptap/pm/view"; var xe = { exports: {} }, We = {}; /** * @license React * use-sync-external-store-shim.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var Rt; function Or() { if (Rt) return We; Rt = 1; var n = L; function e(f, h) { return f === h && (f !== 0 || 1 / f === 1 / h) || f !== f && h !== h; } var t = typeof Object.is == "function" ? Object.is : e, r = n.useState, i = n.useEffect, s = n.useLayoutEffect, o = n.useDebugValue; function a(f, h) { var d = h(), m = r({ inst: { value: d, getSnapshot: h } }), p = m[0].inst, y = m[1]; return s( function() { p.value = d, p.getSnapshot = h, l(p) && y({ inst: p }); }, [f, d, h] ), i( function() { return l(p) && y({ inst: p }), f(function() { l(p) && y({ inst: p }); }); }, [f] ), o(d), d; } function l(f) { var h = f.getSnapshot; f = f.value; try { var d = h(); return !t(f, d); } catch { return !0; } } function c(f, h) { return h(); } var u = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? c : a; return We.useSyncExternalStore = n.useSyncExternalStore !== void 0 ? n.useSyncExternalStore : u, We; } var Ve = {}; /** * @license React * use-sync-external-store-shim.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var Tt; function Nr() { return Tt || (Tt = 1, process.env.NODE_ENV !== "production" && (function() { function n(d, m) { return d === m && (d !== 0 || 1 / d === 1 / m) || d !== d && m !== m; } function e(d, m) { u || i.startTransition === void 0 || (u = !0, console.error( "You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release." )); var p = m(); if (!f) { var y = m(); s(p, y) || (console.error( "The result of getSnapshot should be cached to avoid an infinite loop" ), f = !0); } y = o({ inst: { value: p, getSnapshot: m } }); var g = y[0].inst, S = y[1]; return l( function() { g.value = p, g.getSnapshot = m, t(g) && S({ inst: g }); }, [d, p, m] ), a( function() { return t(g) && S({ inst: g }), d(function() { t(g) && S({ inst: g }); }); }, [d] ), c(p), p; } function t(d) { var m = d.getSnapshot; d = d.value; try { var p = m(); return !s(d, p); } catch { return !0; } } function r(d, m) { return m(); } typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error()); var i = L, s = typeof Object.is == "function" ? Object.is : n, o = i.useState, a = i.useEffect, l = i.useLayoutEffect, c = i.useDebugValue, u = !1, f = !1, h = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? r : e; Ve.useSyncExternalStore = i.useSyncExternalStore !== void 0 ? i.useSyncExternalStore : h, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error()); })()), Ve; } var Ot; function ut() { return Ot || (Ot = 1, process.env.NODE_ENV === "production" ? xe.exports = Or() : xe.exports = Nr()), xe.exports; } var Ir = ut(); function fn(n, e, t) { for (let r = 0; ; r++) { if (r == n.childCount || r == e.childCount) return n.childCount == e.childCount ? null : t; let i = n.child(r), s = e.child(r); if (i == s) { t += i.nodeSize; continue; } if (!i.sameMarkup(s)) return t; if (i.isText && i.text != s.text) { for (let o = 0; i.text[o] == s.text[o]; o++) t++; return t; } if (i.content.size || s.content.size) { let o = fn(i.content, s.content, t + 1); if (o != null) return o; } t += i.nodeSize; } } function dn(n, e, t, r) { for (let i = n.childCount, s = e.childCount; ; ) { if (i == 0 || s == 0) return i == s ? null : { a: t, b: r }; let o = n.child(--i), a = e.child(--s), l = o.nodeSize; if (o == a) { t -= l, r -= l; continue; } if (!o.sameMarkup(a)) return { a: t, b: r }; if (o.isText && o.text != a.text) { let c = 0, u = Math.min(o.text.length, a.text.length); for (; c < u && o.text[o.text.length - c - 1] == a.text[a.text.length - c - 1]; ) c++, t--, r--; return { a: t, b: r }; } if (o.content.size || a.content.size) { let c = dn(o.content, a.content, t - 1, r - 1); if (c) return c; } t -= l, r -= l; } } class v { /** @internal */ constructor(e, t) { if (this.content = e, this.size = t || 0, t == null) for (let r = 0; r < e.length; r++) this.size += e[r].nodeSize; } /** Invoke a callback for all descendant nodes between the given two positions (relative to start of this fragment). Doesn't descend into a node when the callback returns `false`. */ nodesBetween(e, t, r, i = 0, s) { for (let o = 0, a = 0; a < t; o++) { let l = this.content[o], c = a + l.nodeSize; if (c > e && r(l, i + a, s || null, o) !== !1 && l.content.size) { let u = a + 1; l.nodesBetween(Math.max(0, e - u), Math.min(l.content.size, t - u), r, i + u); } a = c; } } /** Call the given callback for every descendant node. `pos` will be relative to the start of the fragment. The callback may return `false` to prevent traversal of a given node's children. */ descendants(e) { this.nodesBetween(0, this.size, e); } /** Extract the text between `from` and `to`. See the same method on [`Node`](https://prosemirror.net/docs/ref/#model.Node.textBetween). */ textBetween(e, t, r, i) { let s = "", o = !0; return this.nodesBetween(e, t, (a, l) => { let c = a.isText ? a.text.slice(Math.max(e, l) - l, t - l) : a.isLeaf ? i ? typeof i == "function" ? i(a) : i : a.type.spec.leafText ? a.type.spec.leafText(a) : "" : ""; a.isBlock && (a.isLeaf && c || a.isTextblock) && r && (o ? o = !1 : s += r), s += c; }, 0), s; } /** Create a new fragment containing the combined content of this fragment and the other. */ append(e) { if (!e.size) return this; if (!this.size) return e; let t = this.lastChild, r = e.firstChild, i = this.content.slice(), s = 0; for (t.isText && t.sameMarkup(r) && (i[i.length - 1] = t.withText(t.text + r.text), s = 1); s < e.content.length; s++) i.push(e.content[s]); return new v(i, this.size + e.size); } /** Cut out the sub-fragment between the two given positions. */ cut(e, t = this.size) { if (e == 0 && t == this.size) return this; let r = [], i = 0; if (t > e) for (let s = 0, o = 0; o < t; s++) { let a = this.content[s], l = o + a.nodeSize; l > e && ((o < e || l > t) && (a.isText ? a = a.cut(Math.max(0, e - o), Math.min(a.text.length, t - o)) : a = a.cut(Math.max(0, e - o - 1), Math.min(a.content.size, t - o - 1))), r.push(a), i += a.nodeSize), o = l; } return new v(r, i); } /** @internal */ cutByIndex(e, t) { return e == t ? v.empty : e == 0 && t == this.content.length ? this : new v(this.content.slice(e, t)); } /** Create a new fragment in which the node at the given index is replaced by the given node. */ replaceChild(e, t) { let r = this.content[e]; if (r == t) return this; let i = this.content.slice(), s = this.size + t.nodeSize - r.nodeSize; return i[e] = t, new v(i, s); } /** Create a new fragment by prepending the given node to this fragment. */ addToStart(e) { return new v([e].concat(this.content), this.size + e.nodeSize); } /** Create a new fragment by appending the given node to this fragment. */ addToEnd(e) { return new v(this.content.concat(e), this.size + e.nodeSize); } /** Compare this fragment to another one. */ eq(e) { if (this.content.length != e.content.length) return !1; for (let t = 0; t < this.content.length; t++) if (!this.content[t].eq(e.content[t])) return !1; return !0; } /** The first child of the fragment, or `null` if it is empty. */ get firstChild() { return this.content.length ? this.content[0] : null; } /** The last child of the fragment, or `null` if it is empty. */ get lastChild() { return this.content.length ? this.content[this.content.length - 1] : null; } /** The number of child nodes in this fragment. */ get childCount() { return this.content.length; } /** Get the child node at the given index. Raise an error when the index is out of range. */ child(e) { let t = this.content[e]; if (!t) throw new RangeError("Index " + e + " out of range for " + this); return t; } /** Get the child node at the given index, if it exists. */ maybeChild(e) { return this.content[e] || null; } /** Call `f` for every child node, passing the node, its offset into this parent node, and its index. */ forEach(e) { for (let t = 0, r = 0; t < this.content.length; t++) { let i = this.content[t]; e(i, r, t), r += i.nodeSize; } } /** Find the first position at which this fragment and another fragment differ, or `null` if they are the same. */ findDiffStart(e, t = 0) { return fn(this, e, t); } /** Find the first position, searching from the end, at which this fragment and the given fragment differ, or `null` if they are the same. Since this position will not be the same in both nodes, an object with two separate positions is returned. */ findDiffEnd(e, t = this.size, r = e.size) { return dn(this, e, t, r); } /** Find the index and inner offset corresponding to a given relative position in this fragment. The result object will be reused (overwritten) the next time the function is called. @internal */ findIndex(e) { if (e == 0) return be(0, e); if (e == this.size) return be(this.content.length, e); if (e > this.size || e < 0) throw new RangeError(`Position ${e} outside of fragment (${this})`); for (let t = 0, r = 0; ; t++) { let i = this.child(t), s = r + i.nodeSize; if (s >= e) return s == e ? be(t + 1, s) : be(t, r); r = s; } } /** Return a debugging string that describes this fragment. */ toString() { return "<" + this.toStringInner() + ">"; } /** @internal */ toStringInner() { return this.content.join(", "); } /** Create a JSON-serializeable representation of this fragment. */ toJSON() { return this.content.length ? this.content.map((e) => e.toJSON()) : null; } /** Deserialize a fragment from its JSON representation. */ static fromJSON(e, t) { if (!t) return v.empty; if (!Array.isArray(t)) throw new RangeError("Invalid input for Fragment.fromJSON"); return new v(t.map(e.nodeFromJSON)); } /** Build a fragment from an array of nodes. Ensures that adjacent text nodes with the same marks are joined together. */ static fromArray(e) { if (!e.length) return v.empty; let t, r = 0; for (let i = 0; i < e.length; i++) { let s = e[i]; r += s.nodeSize, i && s.isText && e[i - 1].sameMarkup(s) ? (t || (t = e.slice(0, i)), t[t.length - 1] = s.withText(t[t.length - 1].text + s.text)) : t && t.push(s); } return new v(t || e, r); } /** Create a fragment from something that can be interpreted as a set of nodes. For `null`, it returns the empty fragment. For a fragment, the fragment itself. For a node or array of nodes, a fragment containing those nodes. */ static from(e) { if (!e) return v.empty; if (e instanceof v) return e; if (Array.isArray(e)) return this.fromArray(e); if (e.attrs) return new v([e], e.nodeSize); throw new RangeError("Can not convert " + e + " to a Fragment" + (e.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : "")); } } v.empty = new v([], 0); const Je = { index: 0, offset: 0 }; function be(n, e) { return Je.index = n, Je.offset = e, Je; } function nt(n, e) { if (n === e) return !0; if (!(n && typeof n == "object") || !(e && typeof e == "object")) return !1; let t = Array.isArray(n); if (Array.isArray(e) != t) return !1; if (t) { if (n.length != e.length) return !1; for (let r = 0; r < n.length; r++) if (!nt(n[r], e[r])) return !1; } else { for (let r in n) if (!(r in e) || !nt(n[r], e[r])) return !1; for (let r in e) if (!(r in n)) return !1; } return !0; } let D = class rt { /** @internal */ constructor(e, t) { this.type = e, this.attrs = t; } /** Given a set of marks, create a new set which contains this one as well, in the right position. If this mark is already in the set, the set itself is returned. If any marks that are set to be [exclusive](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) with this mark are present, those are replaced by this one. */ addToSet(e) { let t, r = !1; for (let i = 0; i < e.length; i++) { let s = e[i]; if (this.eq(s)) return e; if (this.type.excludes(s.type)) t || (t = e.slice(0, i)); else { if (s.type.excludes(this.type)) return e; !r && s.type.rank > this.type.rank && (t || (t = e.slice(0, i)), t.push(this), r = !0), t && t.push(s); } } return t || (t = e.slice()), r || t.push(this), t; } /** Remove this mark from the given set, returning a new set. If this mark is not in the set, the set itself is returned. */ removeFromSet(e) { for (let t = 0; t < e.length; t++) if (this.eq(e[t])) return e.slice(0, t).concat(e.slice(t + 1)); return e; } /** Test whether this mark is in the given set of marks. */ isInSet(e) { for (let t = 0; t < e.length; t++) if (this.eq(e[t])) return !0; return !1; } /** Test whether this mark has the same type and attributes as another mark. */ eq(e) { return this == e || this.type == e.type && nt(this.attrs, e.attrs); } /** Convert this mark to a JSON-serializeable representation. */ toJSON() { let e = { type: this.type.name }; for (let t in this.attrs) { e.attrs = this.attrs; break; } return e; } /** Deserialize a mark from JSON. */ static fromJSON(e, t) { if (!t) throw new RangeError("Invalid input for Mark.fromJSON"); let r = e.marks[t.type]; if (!r) throw new RangeError(`There is no mark type ${t.type} in this schema`); let i = r.create(t.attrs); return r.checkAttrs(i.attrs), i; } /** Test whether two sets of marks are identical. */ static sameSet(e, t) { if (e == t) return !0; if (e.length != t.length) return !1; for (let r = 0; r < e.length; r++) if (!e[r].eq(t[r])) return !1; return !0; } /** Create a properly sorted mark set from null, a single mark, or an unsorted array of marks. */ static setFrom(e) { if (!e || Array.isArray(e) && e.length == 0) return rt.none; if (e instanceof rt) return [e]; let t = e.slice(); return t.sort((r, i) => r.type.rank - i.type.rank), t; } }; D.none = []; class zr extends Error { } class w { /** Create a slice. When specifying a non-zero open depth, you must make sure that there are nodes of at least that depth at the appropriate side of the fragment—i.e. if the fragment is an empty paragraph node, `openStart` and `openEnd` can't be greater than 1. It is not necessary for the content of open nodes to conform to the schema's content constraints, though it should be a valid start/end/middle for such a node, depending on which sides are open. */ constructor(e, t, r) { this.content = e, this.openStart = t, this.openEnd = r; } /** The size this slice would add when inserted into a document. */ get size() { return this.content.size - this.openStart - this.openEnd; } /** @internal */ insertAt(e, t) { let r = pn(this.content, e + this.openStart, t); return r && new w(r, this.openStart, this.openEnd); } /** @internal */ removeBetween(e, t) { return new w(hn(this.content, e + this.openStart, t + this.openStart), this.openStart, this.openEnd); } /** Tests whether this slice is equal to another slice. */ eq(e) { return this.content.eq(e.content) && this.openStart == e.openStart && this.openEnd == e.openEnd; } /** @internal */ toString() { return this.content + "(" + this.openStart + "," + this.openEnd + ")"; } /** Convert a slice to a JSON-serializable representation. */ toJSON() { if (!this.content.size) return null; let e = { content: this.content.toJSON() }; return this.openStart > 0 && (e.openStart = this.openStart), this.openEnd > 0 && (e.openEnd = this.openEnd), e; } /** Deserialize a slice from its JSON representation. */ static fromJSON(e, t) { if (!t) return w.empty; let r = t.openStart || 0, i = t.openEnd || 0; if (typeof r != "number" || typeof i != "number") throw new RangeError("Invalid input for Slice.fromJSON"); return new w(v.fromJSON(e, t.content), r, i); } /** Create a slice from a fragment by taking the maximum possible open value on both side of the fragment. */ static maxOpen(e, t = !0) { let r = 0, i = 0; for (let s = e.firstChild; s && !s.isLeaf && (t || !s.type.spec.isolating); s = s.firstChild) r++; for (let s = e.lastChild; s && !s.isLeaf && (t || !s.type.spec.isolating); s = s.lastChild) i++; return new w(e, r, i); } } w.empty = new w(v.empty, 0, 0); function hn(n, e, t) { let { index: r, offset: i } = n.findIndex(e), s = n.maybeChild(r), { index: o, offset: a } = n.findIndex(t); if (i == e || s.isText) { if (a != t && !n.child(o).isText) throw new RangeError("Removing non-flat range"); return n.cut(0, e).append(n.cut(t)); } if (r != o) throw new RangeError("Removing non-flat range"); return n.replaceChild(r, s.copy(hn(s.content, e - i - 1, t - i - 1))); } function pn(n, e, t, r) { let { index: i, offset: s } = n.findIndex(e), o = n.maybeChild(i); if (s == e || o.isText) return r && !r.canReplace(i, i, t) ? null : n.cut(0, e).append(t).append(n.cut(e)); let a = pn(o.content, e - s - 1, t, o); return a && n.replaceChild(i, o.copy(a)); } class it { /** Construct a node range. `$from` and `$to` should point into the same node until at least the given `depth`, since a node range denotes an adjacent set of nodes in a single parent node. */ constructor(e, t, r) { this.$from = e, this.$to = t, this.depth = r; } /** The position at the start of the range. */ get start() { return this.$from.before(this.depth + 1); } /** The position at the end of the range. */ get end() { return this.$to.after(this.depth + 1); } /** The parent node that the range points into. */ get parent() { return this.$from.node(this.depth); } /** The start index of the range in the parent node. */ get startIndex() { return this.$from.index(this.depth); } /** The end index of the range in the parent node. */ get endIndex() { return this.$to.indexAfter(this.depth); } } function $r(n) { let e = /* @__PURE__ */ Object.create(null); for (let t in n) { let r = n[t]; if (!r.hasDefault) return null; e[t] = r.default; } return e; } function Pr(n, e) { let t = /* @__PURE__ */ Object.create(null); for (let r in n) { let i = e && e[r]; if (i === void 0) { let s = n[r]; if (s.hasDefault) i = s.default; else throw new RangeError("No value supplied for attribute " + r); } t[r] = i; } return t; } function Dr(n, e, t, r) { for (let i in e) if (!(i in n)) throw new RangeError(`Unsupported attribute ${i} for ${t} of type ${i}`); for (let i in n) { let s = n[i]; s.validate && s.validate(e[i]); } } function Br(n, e) { let t = /* @__PURE__ */ Object.create(null); if (e) for (let r in e) t[r] = new Lr(n, r, e[r]); return t; } function _r(n, e, t) { let r = t.split("|"); return (i) => { let s = i === null ? "null" : typeof i; if (r.indexOf(s) < 0) throw new RangeError(`Expected value of type ${r} for attribute ${e} on type ${n}, got ${s}`); }; } class Lr { constructor(e, t, r) { this.hasDefault = Object.prototype.hasOwnProperty.call(r, "default"), this.default = r.default, this.validate = typeof r.validate == "string" ? _r(e, t, r.validate) : r.validate; } get isRequired() { return !this.hasDefault; } } class ft { /** @internal */ constructor(e, t, r, i) { this.name = e, this.rank = t, this.schema = r, this.spec = i, this.attrs = Br(e, i.attrs), this.excluded = null; let s = $r(this.attrs); this.instance = s ? new D(this, s) : null; } /** Create a mark of this type. `attrs` may be `null` or an object containing only some of the mark's attributes. The others, if they have defaults, will be added. */ create(e = null) { return !e && this.instance ? this.instance : new D(this, Pr(this.attrs, e)); } /** @internal */ static compile(e, t) { let r = /* @__PURE__ */ Object.create(null), i = 0; return e.forEach((s, o) => r[s] = new ft(s, i++, t, o)), r; } /** When there is a mark of this type in the given set, a new set without it is returned. Otherwise, the input set is returned. */ removeFromSet(e) { for (var t = 0; t < e.length; t++) e[t].type == this && (e = e.slice(0, t).concat(e.slice(t + 1)), t--); return e; } /** Tests whether there is a mark of this type in the given set. */ isInSet(e) { for (let t = 0; t < e.length; t++) if (e[t].type == this) return e[t]; } /** @internal */ checkAttrs(e) { Dr(this.attrs, e, "mark", this.name); } /** Queries whether a given mark type is [excluded](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) by this one. */ excludes(e) { return this.excluded.indexOf(e) > -1; } } function Fr(n) { return n.tag != null; } function qr(n) { return n.style != null; } class st { /** Create a parser that targets the given schema, using the given parsing rules. */ constructor(e, t) { this.schema = e, this.rules = t, this.tags = [], this.styles = []; let r = this.matchedStyles = []; t.forEach((i) => { if (Fr(i)) this.tags.push(i); else if (qr(i)) { let s = /[^=]*/.exec(i.style)[0]; r.indexOf(s) < 0 && r.push(s), this.styles.push(i); } }), this.normalizeLists = !this.tags.some((i) => { if (!/^(ul|ol)\b/.test(i.tag) || !i.node) return !1; let s = e.nodes[i.node]; return s.contentMatch.matchType(s); }); } /** Parse a document from the content of a DOM node. */ parse(e, t = {}) { let r = new It(this, t, !1); return r.addAll(e, D.none, t.from, t.to), r.finish(); } /** Parses the content of the given DOM node, like [`parse`](https://prosemirror.net/docs/ref/#model.DOMParser.parse), and takes the same set of options. But unlike that method, which produces a whole node, this one returns a slice that is open at the sides, meaning that the schema constraints aren't applied to the start of nodes to the left of the input and the end of nodes at the end. */ parseSlice(e, t = {}) { let r = new It(this, t, !0); return r.addAll(e, D.none, t.from, t.to), w.maxOpen(r.finish()); } /** @internal */ matchTag(e, t, r) { for (let i = r ? this.tags.indexOf(r) + 1 : 0; i < this.tags.length; i++) { let s = this.tags[i]; if (Vr(e, s.tag) && (s.namespace === void 0 || e.namespaceURI == s.namespace) && (!s.context || t.matchesContext(s.context))) { if (s.getAttrs) { let o = s.getAttrs(e); if (o === !1) continue; s.attrs = o || void 0; } return s; } } } /** @internal */ matchStyle(e, t, r, i) { for (let s = i ? this.styles.indexOf(i) + 1 : 0; s < this.styles.length; s++) { let o = this.styles[s], a = o.style; if (!(a.indexOf(e) != 0 || o.context && !r.matchesContext(o.context) || // Test that the style string either precisely matches the prop, // or has an '=' sign after the prop, followed by the given // value. a.length > e.length && (a.charCodeAt(e.length) != 61 || a.slice(e.length + 1) != t))) { if (o.getAttrs) { let l = o.getAttrs(t); if (l === !1) continue; o.attrs = l || void 0; } return o; } } } /** @internal */ static schemaRules(e) { let t = []; function r(i) { let s = i.priority == null ? 50 : i.priority, o = 0; for (; o < t.length; o++) { let a = t[o]; if ((a.priority == null ? 50 : a.priority) < s) break; } t.splice(o, 0, i); } for (let i in e.marks) { let s = e.marks[i].spec.parseDOM; s && s.forEach((o) => { r(o = zt(o)), o.mark || o.ignore || o.clearMark || (o.mark = i); }); } for (let i in e.nodes) { let s = e.nodes[i].spec.parseDOM; s && s.forEach((o) => { r(o = zt(o)), o.node || o.ignore || o.mark || (o.node = i); }); } return t; } /** Construct a DOM parser using the parsing rules listed in a schema's [node specs](https://prosemirror.net/docs/ref/#model.NodeSpec.parseDOM), reordered by [priority](https://prosemirror.net/docs/ref/#model.GenericParseRule.priority). */ static fromSchema(e) { return e.cached.domParser || (e.cached.domParser = new st(e, st.schemaRules(e))); } } const mn = { address: !0, article: !0, aside: !0, blockquote: !0, canvas: !0, dd: !0, div: !0, dl: !0, fieldset: !0, figcaption: !0, figure: !0, footer: !0, form: !0, h1: !0, h2: !0, h3: !0, h4: !0, h5: !0, h6: !0, header: !0, hgroup: !0, hr: !0, li: !0, noscript: !0, ol: !0, output: !0, p: !0, pre: !0, section: !0, table: !0, tfoot: !0, ul: !0 }, jr = { head: !0, noscript: !0, object: !0, script: !0, style: !0, title: !0 }, yn = { ol: !0, ul: !0 }, ye = 1, ot = 2, me = 4; function Nt(n, e, t) { return e != null ? (e ? ye : 0) | (e === "full" ? ot : 0) : n && n.whitespace == "pre" ? ye | ot : t & ~me; } class Ee { constructor(e, t, r, i, s, o) { this.type = e, this.attrs = t, this.marks = r, this.solid = i, this.options = o, this.content = [], this.activeMarks = D.none, this.match = s || (o & me ? null : e.contentMatch); } findWrapping(e) { if (!this.match) { if (!this.type) return []; let t = this.type.contentMatch.fillBefore(v.from(e)); if (t) this.match = this.type.contentMatch.matchFragment(t); else { let r = this.type.contentMatch, i; return (i = r.findWrapping(e.type)) ? (this.match = r, i) : null; } } return this.match.findWrapping(e.type); } finish(e) { if (!(this.options & ye)) { let r = this.content[this.content.length - 1], i; if (r && r.isText && (i = /[ \t\r\n\u000c]+$/.exec(r.text))) { let s = r; r.text.length == i[0].length ? this.content.pop() : this.content[this.content.length - 1] = s.withText(s.text.slice(0, s.text.length - i[0].length)); } } let t = v.from(this.content); return !e && this.match && (t = t.append(this.match.fillBefore(v.empty, !0))), this.type ? this.type.create(this.attrs, t, this.marks) : t; } inlineContext(e) { return this.type ? this.type.inlineContent : this.content.length ? this.content[0].isInline : e.parentNode && !mn.hasOwnProperty(e.parentNode.nodeName.toLowerCase()); } } class It { constructor(e, t, r) { this.parser = e, this.options = t, this.isOpen = r, this.open = 0, this.localPreserveWS = !1; let i = t.topNode, s, o = Nt(null, t.preserveWhitespace, 0) | (r ? me : 0); i ? s = new Ee(i.type, i.attrs, D.none, !0, t.topMatch || i.type.contentMatch, o) : r ? s = new Ee(null, null, D.none, !0, null, o) : s = new Ee(e.schema.topNodeType, null, D.none, !0, null, o), this.nodes = [s], this.find = t.findPositions, this.needsBlock = !1; } get top() { return this.nodes[this.open]; } // Add a DOM node to the content. Text is inserted as text node, // otherwise, the node is passed to `addElement` or, if it has a // `style` attribute, `addElementWithStyles`. addDOM(e, t) { e.nodeType == 3 ? this.addTextNode(e, t) : e.nodeType == 1 && this.addElement(e, t); } addTextNode(e, t) { let r = e.nodeValue, i = this.top, s = i.options & ot ? "full" : this.localPreserveWS || (i.options & ye) > 0, { schema: o } = this.parser; if (s === "full" || i.inlineContext(e) || /[^ \t\r\n\u000c]/.test(r)) { if (s) if (s === "full") r = r.replace(/\r\n?/g, ` `); else if (o.linebreakReplacement && /[\r\n]/.test(r) && this.top.findWrapping(o.linebreakReplacement.create())) { let a = r.split(/\r?\n|\r/); for (let l = 0; l < a.length; l++) l && this.insertNode(o.linebreakReplacement.create(), t, !0), a[l] && this.insertNode(o.text(a[l]), t, !/\S/.test(a[l])); r = ""; } else r = r.replace(/\r?\n|\r/g, " "); else if (r = r.replace(/[ \t\r\n\u000c]+/g, " "), /^[ \t\r\n\u000c]/.test(r) && this.open == this.nodes.length - 1) { let a = i.content[i.content.length - 1], l = e.previousSibling; (!a || l && l.nodeName == "BR" || a.isText && /[ \t\r\n\u000c]$/.test(a.text)) && (r = r.slice(1)); } r && this.insertNode(o.text(r), t, !/\S/.test(r)), this.findInText(e); } else this.findInside(e); } // Try to find a handler for the given tag and use that to parse. If // none is found, the element's content nodes are added directly. addElement(e, t, r) { let i = this.localPreserveWS, s = this.top; (e.tagName == "PRE" || /pre/.test(e.style && e.style.whiteSpace)) && (this.localPreserveWS = !0); let o = e.nodeName.toLowerCase(), a; yn.hasOwnProperty(o) && this.parser.normalizeLists && Wr(e); let l = this.options.ruleFromNode && this.options.ruleFromNode(e) || (a = this.parser.matchTag(e, this, r)); e: if (l ? l.ignore : jr.hasOwnProperty(o)) this.findInside(e), this.ignoreFallback(e, t); else if (!l || l.skip || l.closeParent) { l && l.closeParent ? this.open = Math.max(0, this.open - 1) : l && l.skip.nodeType && (e = l.skip); let c, u = this.needsBlock; if (mn.hasOwnProperty(o)) s.content.length && s.content[0].isInline && this.open && (this.open--, s = this.top), c = !0, s.type || (this.needsBlock = !0); else if (!e.firstChild) { this.leafFallback(e, t); break e; } let f = l && l.skip ? t : this.readStyles(e, t); f && this.addAll(e, f), c && this.sync(s), this.needsBlock = u; } else { let c = this.readStyles(e, t); c && this.addElementByRule(e, l, c, l.consuming === !1 ? a : void 0); } this.localPreserveWS = i; } // Called for leaf DOM nodes that would otherwise be ignored leafFallback(e, t) { e.nodeName == "BR" && this.top.type && this.top.type.inlineContent && this.addTextNode(e.ownerDocument.createTextNode(` `), t); } // Called for ignored nodes ignoreFallback(e, t) { e.nodeName == "BR" && (!this.top.type || !this.top.type.inlineContent) && this.findPlace(this.parser.schema.text("-"), t, !0); } // Run any style parser associated with the node's styles. Either // return an updated array of marks, or null to indicate some of the // styles had a rule with `ignore` set. readStyles(e, t) { let r = e.style; if (r && r.length) for (let i = 0; i < this.parser.matchedStyles.length; i++) { let s = this.parser.matchedStyles[i], o = r.getPropertyValue(s); if (o) for (let a = void 0; ; ) { let l = this.parser.matchStyle(s, o, this, a); if (!l) break; if (l.ignore) return null; if (l.clearMark ? t = t.filter((c) => !l.clearMark(c)) : t = t.concat(this.parser.schema.marks[l.mark].create(l.attrs)), l.consuming === !1) a = l; else break; } } return t; } // Look up a handler for the given node. If none are found, return // false. Otherwise, apply it, use its return value to drive the way // the node's content is wrapped, and return true. addElementByRule(e, t, r, i) { let s, o; if (t.node) if (o = this.parser.schema.nodes[t.node], o.isLeaf) this.insertNode(o.create(t.attrs), r, e.nodeName == "BR") || this.leafFallback(e, r); else { let l = this.enter(o, t.attrs || null, r, t.preserveWhitespace); l && (s = !0, r = l); } else { let l = this.parser.schema.marks[t.mark]; r = r.concat(l.create(t.attrs)); } let a = this.top; if (o && o.isLeaf) this.findInside(e); else if (i) this.addElement(e, r, i); else if (t.getContent) this.findInside(e), t.getContent(e, this.parser.schema).forEach((l) => this.insertNode(l, r, !1)); else { let l = e; typeof t.contentElement == "string" ? l = e.querySelector(t.contentElement) : typeof t.contentElement == "function" ? l = t.contentElement(e) : t.contentElement && (l = t.contentElement), this.findAround(e, l, !0), this.addAll(l, r), this.findAround(e, l, !1); } s && this.sync(a) && this.open--; } // Add all child nodes between `startIndex` and `endIndex` (or the // whole node, if not given). If `sync` is passed, use it to // synchronize after every block element. addAll(e, t, r, i) { let s = r || 0; for (let o = r ? e.childNodes[r] : e.firstChild, a = i == null ? null : e.childNodes[i]; o != a; o = o.nextSibling, ++s) this.findAtPoint(e, s), this.addDOM(o, t); this.findAtPoint(e, s); } // Try to find a way to fit the given node type into the current // context. May add intermediate wrappers and/or leave non-solid // nodes that we're in. findPlace(e, t, r) { let i, s; for (let o = this.open, a = 0; o >= 0; o--) { let l = this.nodes[o], c = l.findWrapping(e); if (c && (!i || i.length > c.length + a) && (i = c, s = l, !c.length)) break; if (l.solid) { if (r) break; a += 2; } } if (!i) return null; this.sync(s); for (let o = 0; o < i.length; o++) t = this.enterInner(i[o], null, t, !1); return t; } // Try to insert the given node, adjusting the context when needed. insertNode(e, t, r) { if (e.isInline && this.needsBlock && !this.top.type) { let s = this.textblockFromContext(); s && (t = this.enterInner(s, null, t)); } let i = this.findPlace(e, t, r); if (i) { this.closeExtra(); let s = this.top; s.match && (s.match = s.match.matchType(e.type)); let o = D.none; for (let a of i.concat(e.marks)) (s.type ? s.type.allowsMarkType(a.type) : $t(a.type, e.type)) && (o = a.addToSet(o)); return s.content.push(e.mark(o)), !0; } return !1; } // Try to start a node of the given type, adjusting the context when // necessary. enter(e, t, r, i) { let s = this.findPlace(e.create(t), r, !1); return s && (s = this.enterInner(e, t, r, !0, i)), s; } // Open a node of the given type enterInner(e, t, r, i = !1, s) { this.closeExtra(); let o = this.top; o.match = o.match && o.match.matchType(e); let a = Nt(e, s, o.options); o.options & me && o.content.length == 0 && (a |= me); let l = D.none; return r = r.filter((c) => (o.type ? o.type.allowsMarkType(c.type) : $t(c.type, e)) ? (l = c.addToSet(l), !1) : !0), this.nodes.push(new Ee(e, t, l, i, null, a)), this.open++, r; } // Make sure all nodes above this.open are finished and added to // their parents closeExtra(e = !1) { let t = this.nodes.length - 1; if (t > this.open) { for (; t > this.open; t--) this.nodes[t - 1].content.push(this.nodes[t].finish(e)); this.nodes.length = this.open + 1; } } finish() { return this.open = 0, this.closeExtra(this.isOpen), this.nodes[0].finish(!!(this.isOpen || this.options.topOpen)); } sync(e) { for (let t = this.open; t >= 0; t--) { if (this.nodes[t] == e) return this.open = t, !0; this.localPreserveWS && (this.nodes[t].options |= ye); } return !1; } get currentPos() { this.closeExtra(); let e = 0; for (let t = this.open; t >= 0; t--) { let r = this.nodes[t].content; for (let i = r.length - 1; i >= 0; i--) e += r[i].nodeSize; t && e++; } return e; } findAtPoint(e, t) { if (this.find) for (let r = 0; r < this.find.length; r++) this.find[r].node == e && this.find[r].offset == t && (this.find[r].pos = this.currentPos); } findInside(e) { if (this.find) for (let t = 0; t < this.find.length; t++) this.find[t].pos == null && e.nodeType == 1 && e.contains(this.find[t].node) && (this.find[t].pos = this.currentPos); } findAround(e, t, r) { if (e != t && this.find) for (let i = 0; i < this.find.length; i++) this.find[i].pos == null && e.nodeType == 1 && e.contains(this.find[i].node) && t.compareDocumentPosition(this.find[i].node) & (r ? 2 : 4) && (this.find[i].pos = this.currentPos); } findInText(e) { if (this.find) for (let t = 0; t < this.find.length; t++) this.find[t].node == e && (this.find[t].pos = this.currentPos - (e.nodeValue.length - this.find[t].offset)); } // Determines whether the given context string matches this context. matchesContext(e) { if (e.indexOf("|") > -1) return e.split(/\s*\|\s*/).some(this.matchesContext, this); let t = e.split("/"), r = this.options.context, i = !this.isOpen && (!r || r.parent.type == this.nodes[0].type), s = -(r ? r.depth + 1 : 0) + (i ? 0 : 1), o = (a, l) => { for (; a >= 0; a--) { let c = t[a]; if (c == "") { if (a == t.length - 1 || a == 0) continue; for (; l >= s; l--) if (o(a - 1, l)) return !0; return !1; } else { let u = l > 0 || l == 0 && i ? this.nodes[l].type : r && l >= s ? r.node(l - s).type : null; if (!u || u.name != c && !u.isInGroup(c)) return !1; l--; } } return !0; }; return o(t.length - 1, this.open); } textblockFromContext() { let e = this.options.context; if (e) for (let t = e.depth; t >= 0; t--) { let r = e.node(t).contentMatchAt(e.indexAfter(t)).defaultType; if (r && r.isTextblock && r.defaultAttrs) return r; } for (let t in this.parser.schema.nodes) { let r = this.parser.schema.nodes[t]; if (r.isTextblock && r.defaultAttrs) return r; } } } function Wr(n) { for (let e = n.firstChild, t = null; e; e = e.nextSibling) { let r = e.nodeType == 1 ? e.nodeName.toLowerCase() : null; r && yn.hasOwnProperty(r) && t ? (t.appendChild(e), e = t) : r == "li" ? t = e : r && (t = null); } } function Vr(n, e) { return (n.matches || n.msMatchesSelector || n.webkitMatchesSelector || n.mozMatchesSelector).call(n, e); } function zt(n) { let e = {}; for (let t in n) e[t] = n[t]; return e; } function $t(n, e) { let t = e.schema.nodes; for (let r in t) { let i = t[r]; if (!i.allowsMarkType(n)) continue; let s = [], o = (a) => { s.push(a); for (let l = 0; l < a.edgeCount; l++) { let { type: c, next: u } = a.edge(l); if (c == e || s.indexOf(u) < 0 && o(u)) return !0; } }; if (o(i.contentMatch)) return !0; } } class gn { /** Create a serializer. `nodes` should map node names to functions that take a node and return a description of the corresponding DOM. `marks` does the same for mark names, but also gets an argument that tells it whether the mark's content is block or inline content (for typical use, it'll always be inline). A mark serializer may be `null` to indicate that marks of that type should not be serialized. */ constructor(e, t) { this.nodes = e, this.marks = t; } /** Serialize the content of this fragment to a DOM fragment. When not in the browser, the `document` option, containing a DOM document, should be passed so that the serializer can create nodes. */ serializeFragment(e, t = {}, r) { r || (r = He(t).createDocumentFragment()); let i = r, s = []; return e.forEach((o) => { if (s.length || o.marks.length) { let a = 0, l = 0; for (; a < s.length && l < o.marks.length; ) { let c = o.marks[l]; if (!this.marks[c.type.name]) { l++; continue; } if (!c.eq(s[a][0]) || c.type.spec.spanning === !1) break; a++, l++; } for (; a < s.length; ) i = s.pop()[1]; for (; l < o.marks.length; ) { let c = o.marks[l++], u = this.serializeMark(c, o.isInline, t); u && (s.push([c, i]), i.appendChild(u.dom), i = u.contentDOM || u.dom); } } i.appendChild(this.serializeNodeInner(o, t)); }), r; } /** @internal */ serializeNodeInner(e, t) { let { dom: r, contentDOM: i } = Oe(He(t), this.nodes[e.type.name](e), null, e.attrs); if (i) { if (e.isLeaf) throw new RangeError("Content hole not allowed in a leaf node spec"); this.serializeFragment(e.content, t, i); } return r; } /** Serialize this node to a DOM node. This can be useful when you need to serialize a part of a document, as opposed to the whole document. To serialize a whole document, use [`serializeFragment`](https://prosemirror.net/docs/ref/#model.DOMSerializer.serializeFragment) on its [content](https://prosemirror.net/docs/ref/#model.Node.content). */ serializeNode(e, t = {}) { let r = this.serializeNodeInner(e, t); for (let i = e.marks.length - 1; i >= 0; i--) { let s = this.serializeMark(e.marks[i], e.isInline, t); s && ((s.contentDOM || s.dom).appendChild(r), r = s.dom); } return r; } /** @internal */ serializeMark(e, t, r = {}) { let i = this.marks[e.type.name]; return i && Oe(He(r), i(e, t), null, e.attrs); } static renderSpec(e, t, r = null, i) { return Oe(e, t, r, i); } /** Build a serializer using the [`toDOM`](https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM) properties in a schema's node and mark specs. */ static fromSchema(e) { return e.cached.domSerializer || (e.cached.domSerializer = new gn(this.nodesFromSchema(e), this.marksFromSchema(e))); } /** Gather the serializers in a schema's node specs into an object. This can be useful as a base to build a custom serializer from. */ static nodesFromSchema(e) { let t = Pt(e.nodes); return t.text || (t.text = (r) => r.text), t; } /** Gather the serializers in a schema's mark specs into an object. */ static marksFromSchema(e) { return Pt(e.marks); } } function Pt(n) { let e = {}; for (let t in n) { let r = n[t].spec.toDOM; r && (e[t] = r); } return e; } function He(n) { return n.document || window.document; } const Dt = /* @__PURE__ */ new WeakMap(); function Jr(n) { let e = Dt.get(n); return e === void 0 && Dt.set(n, e = Hr(n)), e; } function Hr(n) { let e = null; function t(r) { if (r && typeof r == "object") if (Array.isArray(r)) if (typeof r[0] == "string") e || (e = []), e.push(r); else for (let i = 0; i < r.length; i++) t(r[i]); else for (let i in r) t(r[i]); } return t(n), e; } function Oe(n, e, t, r) { if (typeof e == "string") return { dom: n.createTextNode(e) }; if (e.nodeType != null) return { dom: e }; if (e.dom && e.dom.nodeType != null) return e; let i = e[0], s; if (typeof i != "string") throw new RangeError("Invalid array passed to renderSpec"); if (r && (s = Jr(r)) && s.indexOf(e) > -1) throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack."); let o = i.indexOf(" "); o > 0 && (t = i.slice(0, o), i = i.slice(o + 1)); let a, l = t ? n.createElementNS(t, i) : n.createElement(i), c = e[1], u = 1; if (c && typeof c == "object" && c.nodeType == null && !Array.isArray(c)) { u = 2; for (let f in c) if (c[f] != null) { let h = f.indexOf(" "); h > 0 ? l.setAttributeNS(f.slice(0, h), f.slice(h + 1), c[f]) : f == "style" && l.style ? l.style.cssText = c[f] : l.setAttribute(f, c[f]); } } for (let f = u; f < e.length; f++) { let h = e[f]; if (h === 0) { if (f < e.length - 1 || f > u) throw new RangeError("Content hole must be the only child of its parent node"); return { dom: l, contentDOM: l }; } else { let { dom: d, contentDOM: m } = Oe(n, h, t, r); if (l.appendChild(d), m) { if (a) throw new RangeError("Multiple content holes"); a = m; } } } return { dom: l, contentDOM: a }; } const vn = 65535, wn = Math.pow(2, 16); function Ur(n, e) { return n + e * wn; } function Bt(n) { return n & vn; } function Kr(n) { return (n - (n & vn)) / wn; } const Sn = 1, kn = 2, Ne = 4, xn = 8; class at { /** @internal */ constructor(e, t, r) { this.pos = e, this.delInfo = t, this.recover = r; } /** Tells you whether the position was deleted, that is, whether the step removed the token on the side queried (via the `assoc`) argument from the document. */ get deleted() { return (this.delInfo & xn) > 0; } /** Tells you whether the token before the mapped position was deleted. */ get deletedBefore() { return (this.delInfo & (Sn | Ne)) > 0; } /** True when the token after the mapped position was deleted. */ get deletedAfter() { return (this.delInfo & (kn | Ne)) > 0; } /** Tells whether any of the steps mapped through deletes across the position (including both the token before and after the position). */ get deletedAcross() { return (this.delInfo & Ne) > 0; } } class P { /** Create a position map. The modifications to the document are represented as an array of numbers, in which each group of three represents a modified chunk as `[start, oldSize, newSize]`. */ constructor(e, t = !1) { if (this.ranges = e, this.inverted = t, !e.length && P.empty) return P.empty; } /** @internal */ recover(e) { let t = 0, r = Bt(e); if (!this.inverted) for (let i = 0; i < r; i++) t += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1]; return this.ranges[r * 3] + t + Kr(e); } mapResult(e, t = 1) { return this._map(e, t, !1); } map(e, t = 1) { return this._map(e, t, !0); } /** @internal */ _map(e, t, r) { let i = 0, s = this.inverted ? 2 : 1, o = this.inverted ? 1 : 2; for (let a = 0; a < this.ranges.length; a += 3) { let l = this.ranges[a] - (this.inverted ? i : 0); if (l > e) break; let c = this.ranges[a + s], u = this.ranges[a + o], f = l + c; if (e <= f) { let h = c ? e == l ? -1 : e == f ? 1 : t : t, d = l + i + (h < 0 ? 0 : u); if (r) return d; let m = e == (t < 0 ? l : f) ? null : Ur(a / 3, e - l), p = e == l ? kn : e == f ? Sn : Ne; return (t < 0 ? e != l : e != f) && (p |= xn), new at(d, p, m); } i += u - c; } return r ? e + i : new at(e + i, 0, null); } /** @internal */ touches(e, t) { let r = 0, i = Bt(t), s = this.inverted ? 2 : 1, o = this.inverted ? 1 : 2; for (let a = 0; a < this.ranges.length; a += 3) { let l = this.ranges[a] - (this.inverted ? r : 0); if (l > e) b