Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol diffdown.com

feat(frontend): bundle prosemirror-collab for browser

+3196 -3
+13 -1
package-lock.json
··· 14 14 "@codemirror/theme-one-dark": "^6.1.3", 15 15 "@codemirror/view": "^6.39.16", 16 16 "@milkdown/kit": "^7.19.0", 17 - "codemirror": "^6.0.2" 17 + "codemirror": "^6.0.2", 18 + "prosemirror-collab": "^1.3.1", 19 + "prosemirror-state": "^1.4.4", 20 + "prosemirror-transform": "^1.11.0" 18 21 } 19 22 }, 20 23 "node_modules/@babel/helper-string-parser": { ··· 1845 1848 "license": "MIT", 1846 1849 "dependencies": { 1847 1850 "prosemirror-transform": "^1.0.0" 1851 + } 1852 + }, 1853 + "node_modules/prosemirror-collab": { 1854 + "version": "1.3.1", 1855 + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", 1856 + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", 1857 + "license": "MIT", 1858 + "dependencies": { 1859 + "prosemirror-state": "^1.0.0" 1848 1860 } 1849 1861 }, 1850 1862 "node_modules/prosemirror-commands": {
+6 -2
package.json
··· 4 4 "description": "Collaborative Markdown editor with real-time preview, version history, and multi-file repository support.", 5 5 "main": "index.js", 6 6 "scripts": { 7 - "test": "echo \"Error: no test specified\" && exit 1" 7 + "test": "echo \"Error: no test specified\" && exit 1", 8 + "build:collab": "npx esbuild node_modules/prosemirror-collab/dist/index.js --bundle --format=esm --outfile=static/vendor/collab.js" 8 9 }, 9 10 "keywords": [], 10 11 "author": "", ··· 16 17 "@codemirror/theme-one-dark": "^6.1.3", 17 18 "@codemirror/view": "^6.39.16", 18 19 "@milkdown/kit": "^7.19.0", 19 - "codemirror": "^6.0.2" 20 + "codemirror": "^6.0.2", 21 + "prosemirror-collab": "^1.3.1", 22 + "prosemirror-state": "^1.4.4", 23 + "prosemirror-transform": "^1.11.0" 20 24 } 21 25 }
+3177
static/vendor/collab.js
··· 1 + // node_modules/prosemirror-model/dist/index.js 2 + function findDiffStart(a, b, pos) { 3 + for (let i = 0; ; i++) { 4 + if (i == a.childCount || i == b.childCount) 5 + return a.childCount == b.childCount ? null : pos; 6 + let childA = a.child(i), childB = b.child(i); 7 + if (childA == childB) { 8 + pos += childA.nodeSize; 9 + continue; 10 + } 11 + if (!childA.sameMarkup(childB)) 12 + return pos; 13 + if (childA.isText && childA.text != childB.text) { 14 + for (let j = 0; childA.text[j] == childB.text[j]; j++) 15 + pos++; 16 + return pos; 17 + } 18 + if (childA.content.size || childB.content.size) { 19 + let inner = findDiffStart(childA.content, childB.content, pos + 1); 20 + if (inner != null) 21 + return inner; 22 + } 23 + pos += childA.nodeSize; 24 + } 25 + } 26 + function findDiffEnd(a, b, posA, posB) { 27 + for (let iA = a.childCount, iB = b.childCount; ; ) { 28 + if (iA == 0 || iB == 0) 29 + return iA == iB ? null : { a: posA, b: posB }; 30 + let childA = a.child(--iA), childB = b.child(--iB), size = childA.nodeSize; 31 + if (childA == childB) { 32 + posA -= size; 33 + posB -= size; 34 + continue; 35 + } 36 + if (!childA.sameMarkup(childB)) 37 + return { a: posA, b: posB }; 38 + if (childA.isText && childA.text != childB.text) { 39 + let same = 0, minSize = Math.min(childA.text.length, childB.text.length); 40 + while (same < minSize && childA.text[childA.text.length - same - 1] == childB.text[childB.text.length - same - 1]) { 41 + same++; 42 + posA--; 43 + posB--; 44 + } 45 + return { a: posA, b: posB }; 46 + } 47 + if (childA.content.size || childB.content.size) { 48 + let inner = findDiffEnd(childA.content, childB.content, posA - 1, posB - 1); 49 + if (inner) 50 + return inner; 51 + } 52 + posA -= size; 53 + posB -= size; 54 + } 55 + } 56 + var Fragment = class _Fragment { 57 + /** 58 + @internal 59 + */ 60 + constructor(content, size) { 61 + this.content = content; 62 + this.size = size || 0; 63 + if (size == null) 64 + for (let i = 0; i < content.length; i++) 65 + this.size += content[i].nodeSize; 66 + } 67 + /** 68 + Invoke a callback for all descendant nodes between the given two 69 + positions (relative to start of this fragment). Doesn't descend 70 + into a node when the callback returns `false`. 71 + */ 72 + nodesBetween(from, to, f, nodeStart = 0, parent) { 73 + for (let i = 0, pos = 0; pos < to; i++) { 74 + let child = this.content[i], end = pos + child.nodeSize; 75 + if (end > from && f(child, nodeStart + pos, parent || null, i) !== false && child.content.size) { 76 + let start = pos + 1; 77 + child.nodesBetween(Math.max(0, from - start), Math.min(child.content.size, to - start), f, nodeStart + start); 78 + } 79 + pos = end; 80 + } 81 + } 82 + /** 83 + Call the given callback for every descendant node. `pos` will be 84 + relative to the start of the fragment. The callback may return 85 + `false` to prevent traversal of a given node's children. 86 + */ 87 + descendants(f) { 88 + this.nodesBetween(0, this.size, f); 89 + } 90 + /** 91 + Extract the text between `from` and `to`. See the same method on 92 + [`Node`](https://prosemirror.net/docs/ref/#model.Node.textBetween). 93 + */ 94 + textBetween(from, to, blockSeparator, leafText) { 95 + let text = "", first = true; 96 + this.nodesBetween(from, to, (node, pos) => { 97 + let nodeText = node.isText ? node.text.slice(Math.max(from, pos) - pos, to - pos) : !node.isLeaf ? "" : leafText ? typeof leafText === "function" ? leafText(node) : leafText : node.type.spec.leafText ? node.type.spec.leafText(node) : ""; 98 + if (node.isBlock && (node.isLeaf && nodeText || node.isTextblock) && blockSeparator) { 99 + if (first) 100 + first = false; 101 + else 102 + text += blockSeparator; 103 + } 104 + text += nodeText; 105 + }, 0); 106 + return text; 107 + } 108 + /** 109 + Create a new fragment containing the combined content of this 110 + fragment and the other. 111 + */ 112 + append(other) { 113 + if (!other.size) 114 + return this; 115 + if (!this.size) 116 + return other; 117 + let last = this.lastChild, first = other.firstChild, content = this.content.slice(), i = 0; 118 + if (last.isText && last.sameMarkup(first)) { 119 + content[content.length - 1] = last.withText(last.text + first.text); 120 + i = 1; 121 + } 122 + for (; i < other.content.length; i++) 123 + content.push(other.content[i]); 124 + return new _Fragment(content, this.size + other.size); 125 + } 126 + /** 127 + Cut out the sub-fragment between the two given positions. 128 + */ 129 + cut(from, to = this.size) { 130 + if (from == 0 && to == this.size) 131 + return this; 132 + let result = [], size = 0; 133 + if (to > from) 134 + for (let i = 0, pos = 0; pos < to; i++) { 135 + let child = this.content[i], end = pos + child.nodeSize; 136 + if (end > from) { 137 + if (pos < from || end > to) { 138 + if (child.isText) 139 + child = child.cut(Math.max(0, from - pos), Math.min(child.text.length, to - pos)); 140 + else 141 + child = child.cut(Math.max(0, from - pos - 1), Math.min(child.content.size, to - pos - 1)); 142 + } 143 + result.push(child); 144 + size += child.nodeSize; 145 + } 146 + pos = end; 147 + } 148 + return new _Fragment(result, size); 149 + } 150 + /** 151 + @internal 152 + */ 153 + cutByIndex(from, to) { 154 + if (from == to) 155 + return _Fragment.empty; 156 + if (from == 0 && to == this.content.length) 157 + return this; 158 + return new _Fragment(this.content.slice(from, to)); 159 + } 160 + /** 161 + Create a new fragment in which the node at the given index is 162 + replaced by the given node. 163 + */ 164 + replaceChild(index, node) { 165 + let current = this.content[index]; 166 + if (current == node) 167 + return this; 168 + let copy = this.content.slice(); 169 + let size = this.size + node.nodeSize - current.nodeSize; 170 + copy[index] = node; 171 + return new _Fragment(copy, size); 172 + } 173 + /** 174 + Create a new fragment by prepending the given node to this 175 + fragment. 176 + */ 177 + addToStart(node) { 178 + return new _Fragment([node].concat(this.content), this.size + node.nodeSize); 179 + } 180 + /** 181 + Create a new fragment by appending the given node to this 182 + fragment. 183 + */ 184 + addToEnd(node) { 185 + return new _Fragment(this.content.concat(node), this.size + node.nodeSize); 186 + } 187 + /** 188 + Compare this fragment to another one. 189 + */ 190 + eq(other) { 191 + if (this.content.length != other.content.length) 192 + return false; 193 + for (let i = 0; i < this.content.length; i++) 194 + if (!this.content[i].eq(other.content[i])) 195 + return false; 196 + return true; 197 + } 198 + /** 199 + The first child of the fragment, or `null` if it is empty. 200 + */ 201 + get firstChild() { 202 + return this.content.length ? this.content[0] : null; 203 + } 204 + /** 205 + The last child of the fragment, or `null` if it is empty. 206 + */ 207 + get lastChild() { 208 + return this.content.length ? this.content[this.content.length - 1] : null; 209 + } 210 + /** 211 + The number of child nodes in this fragment. 212 + */ 213 + get childCount() { 214 + return this.content.length; 215 + } 216 + /** 217 + Get the child node at the given index. Raise an error when the 218 + index is out of range. 219 + */ 220 + child(index) { 221 + let found2 = this.content[index]; 222 + if (!found2) 223 + throw new RangeError("Index " + index + " out of range for " + this); 224 + return found2; 225 + } 226 + /** 227 + Get the child node at the given index, if it exists. 228 + */ 229 + maybeChild(index) { 230 + return this.content[index] || null; 231 + } 232 + /** 233 + Call `f` for every child node, passing the node, its offset 234 + into this parent node, and its index. 235 + */ 236 + forEach(f) { 237 + for (let i = 0, p = 0; i < this.content.length; i++) { 238 + let child = this.content[i]; 239 + f(child, p, i); 240 + p += child.nodeSize; 241 + } 242 + } 243 + /** 244 + Find the first position at which this fragment and another 245 + fragment differ, or `null` if they are the same. 246 + */ 247 + findDiffStart(other, pos = 0) { 248 + return findDiffStart(this, other, pos); 249 + } 250 + /** 251 + Find the first position, searching from the end, at which this 252 + fragment and the given fragment differ, or `null` if they are 253 + the same. Since this position will not be the same in both 254 + nodes, an object with two separate positions is returned. 255 + */ 256 + findDiffEnd(other, pos = this.size, otherPos = other.size) { 257 + return findDiffEnd(this, other, pos, otherPos); 258 + } 259 + /** 260 + Find the index and inner offset corresponding to a given relative 261 + position in this fragment. The result object will be reused 262 + (overwritten) the next time the function is called. @internal 263 + */ 264 + findIndex(pos) { 265 + if (pos == 0) 266 + return retIndex(0, pos); 267 + if (pos == this.size) 268 + return retIndex(this.content.length, pos); 269 + if (pos > this.size || pos < 0) 270 + throw new RangeError(`Position ${pos} outside of fragment (${this})`); 271 + for (let i = 0, curPos = 0; ; i++) { 272 + let cur = this.child(i), end = curPos + cur.nodeSize; 273 + if (end >= pos) { 274 + if (end == pos) 275 + return retIndex(i + 1, end); 276 + return retIndex(i, curPos); 277 + } 278 + curPos = end; 279 + } 280 + } 281 + /** 282 + Return a debugging string that describes this fragment. 283 + */ 284 + toString() { 285 + return "<" + this.toStringInner() + ">"; 286 + } 287 + /** 288 + @internal 289 + */ 290 + toStringInner() { 291 + return this.content.join(", "); 292 + } 293 + /** 294 + Create a JSON-serializeable representation of this fragment. 295 + */ 296 + toJSON() { 297 + return this.content.length ? this.content.map((n) => n.toJSON()) : null; 298 + } 299 + /** 300 + Deserialize a fragment from its JSON representation. 301 + */ 302 + static fromJSON(schema, value) { 303 + if (!value) 304 + return _Fragment.empty; 305 + if (!Array.isArray(value)) 306 + throw new RangeError("Invalid input for Fragment.fromJSON"); 307 + return new _Fragment(value.map(schema.nodeFromJSON)); 308 + } 309 + /** 310 + Build a fragment from an array of nodes. Ensures that adjacent 311 + text nodes with the same marks are joined together. 312 + */ 313 + static fromArray(array) { 314 + if (!array.length) 315 + return _Fragment.empty; 316 + let joined, size = 0; 317 + for (let i = 0; i < array.length; i++) { 318 + let node = array[i]; 319 + size += node.nodeSize; 320 + if (i && node.isText && array[i - 1].sameMarkup(node)) { 321 + if (!joined) 322 + joined = array.slice(0, i); 323 + joined[joined.length - 1] = node.withText(joined[joined.length - 1].text + node.text); 324 + } else if (joined) { 325 + joined.push(node); 326 + } 327 + } 328 + return new _Fragment(joined || array, size); 329 + } 330 + /** 331 + Create a fragment from something that can be interpreted as a 332 + set of nodes. For `null`, it returns the empty fragment. For a 333 + fragment, the fragment itself. For a node or array of nodes, a 334 + fragment containing those nodes. 335 + */ 336 + static from(nodes) { 337 + if (!nodes) 338 + return _Fragment.empty; 339 + if (nodes instanceof _Fragment) 340 + return nodes; 341 + if (Array.isArray(nodes)) 342 + return this.fromArray(nodes); 343 + if (nodes.attrs) 344 + return new _Fragment([nodes], nodes.nodeSize); 345 + throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : "")); 346 + } 347 + }; 348 + Fragment.empty = new Fragment([], 0); 349 + var found = { index: 0, offset: 0 }; 350 + function retIndex(index, offset) { 351 + found.index = index; 352 + found.offset = offset; 353 + return found; 354 + } 355 + function compareDeep(a, b) { 356 + if (a === b) 357 + return true; 358 + if (!(a && typeof a == "object") || !(b && typeof b == "object")) 359 + return false; 360 + let array = Array.isArray(a); 361 + if (Array.isArray(b) != array) 362 + return false; 363 + if (array) { 364 + if (a.length != b.length) 365 + return false; 366 + for (let i = 0; i < a.length; i++) 367 + if (!compareDeep(a[i], b[i])) 368 + return false; 369 + } else { 370 + for (let p in a) 371 + if (!(p in b) || !compareDeep(a[p], b[p])) 372 + return false; 373 + for (let p in b) 374 + if (!(p in a)) 375 + return false; 376 + } 377 + return true; 378 + } 379 + var Mark = class _Mark { 380 + /** 381 + @internal 382 + */ 383 + constructor(type, attrs) { 384 + this.type = type; 385 + this.attrs = attrs; 386 + } 387 + /** 388 + Given a set of marks, create a new set which contains this one as 389 + well, in the right position. If this mark is already in the set, 390 + the set itself is returned. If any marks that are set to be 391 + [exclusive](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) with this mark are present, 392 + those are replaced by this one. 393 + */ 394 + addToSet(set) { 395 + let copy, placed = false; 396 + for (let i = 0; i < set.length; i++) { 397 + let other = set[i]; 398 + if (this.eq(other)) 399 + return set; 400 + if (this.type.excludes(other.type)) { 401 + if (!copy) 402 + copy = set.slice(0, i); 403 + } else if (other.type.excludes(this.type)) { 404 + return set; 405 + } else { 406 + if (!placed && other.type.rank > this.type.rank) { 407 + if (!copy) 408 + copy = set.slice(0, i); 409 + copy.push(this); 410 + placed = true; 411 + } 412 + if (copy) 413 + copy.push(other); 414 + } 415 + } 416 + if (!copy) 417 + copy = set.slice(); 418 + if (!placed) 419 + copy.push(this); 420 + return copy; 421 + } 422 + /** 423 + Remove this mark from the given set, returning a new set. If this 424 + mark is not in the set, the set itself is returned. 425 + */ 426 + removeFromSet(set) { 427 + for (let i = 0; i < set.length; i++) 428 + if (this.eq(set[i])) 429 + return set.slice(0, i).concat(set.slice(i + 1)); 430 + return set; 431 + } 432 + /** 433 + Test whether this mark is in the given set of marks. 434 + */ 435 + isInSet(set) { 436 + for (let i = 0; i < set.length; i++) 437 + if (this.eq(set[i])) 438 + return true; 439 + return false; 440 + } 441 + /** 442 + Test whether this mark has the same type and attributes as 443 + another mark. 444 + */ 445 + eq(other) { 446 + return this == other || this.type == other.type && compareDeep(this.attrs, other.attrs); 447 + } 448 + /** 449 + Convert this mark to a JSON-serializeable representation. 450 + */ 451 + toJSON() { 452 + let obj = { type: this.type.name }; 453 + for (let _ in this.attrs) { 454 + obj.attrs = this.attrs; 455 + break; 456 + } 457 + return obj; 458 + } 459 + /** 460 + Deserialize a mark from JSON. 461 + */ 462 + static fromJSON(schema, json) { 463 + if (!json) 464 + throw new RangeError("Invalid input for Mark.fromJSON"); 465 + let type = schema.marks[json.type]; 466 + if (!type) 467 + throw new RangeError(`There is no mark type ${json.type} in this schema`); 468 + let mark = type.create(json.attrs); 469 + type.checkAttrs(mark.attrs); 470 + return mark; 471 + } 472 + /** 473 + Test whether two sets of marks are identical. 474 + */ 475 + static sameSet(a, b) { 476 + if (a == b) 477 + return true; 478 + if (a.length != b.length) 479 + return false; 480 + for (let i = 0; i < a.length; i++) 481 + if (!a[i].eq(b[i])) 482 + return false; 483 + return true; 484 + } 485 + /** 486 + Create a properly sorted mark set from null, a single mark, or an 487 + unsorted array of marks. 488 + */ 489 + static setFrom(marks) { 490 + if (!marks || Array.isArray(marks) && marks.length == 0) 491 + return _Mark.none; 492 + if (marks instanceof _Mark) 493 + return [marks]; 494 + let copy = marks.slice(); 495 + copy.sort((a, b) => a.type.rank - b.type.rank); 496 + return copy; 497 + } 498 + }; 499 + Mark.none = []; 500 + var ReplaceError = class extends Error { 501 + }; 502 + var Slice = class _Slice { 503 + /** 504 + Create a slice. When specifying a non-zero open depth, you must 505 + make sure that there are nodes of at least that depth at the 506 + appropriate side of the fragment—i.e. if the fragment is an 507 + empty paragraph node, `openStart` and `openEnd` can't be greater 508 + than 1. 509 + 510 + It is not necessary for the content of open nodes to conform to 511 + the schema's content constraints, though it should be a valid 512 + start/end/middle for such a node, depending on which sides are 513 + open. 514 + */ 515 + constructor(content, openStart, openEnd) { 516 + this.content = content; 517 + this.openStart = openStart; 518 + this.openEnd = openEnd; 519 + } 520 + /** 521 + The size this slice would add when inserted into a document. 522 + */ 523 + get size() { 524 + return this.content.size - this.openStart - this.openEnd; 525 + } 526 + /** 527 + @internal 528 + */ 529 + insertAt(pos, fragment) { 530 + let content = insertInto(this.content, pos + this.openStart, fragment); 531 + return content && new _Slice(content, this.openStart, this.openEnd); 532 + } 533 + /** 534 + @internal 535 + */ 536 + removeBetween(from, to) { 537 + return new _Slice(removeRange(this.content, from + this.openStart, to + this.openStart), this.openStart, this.openEnd); 538 + } 539 + /** 540 + Tests whether this slice is equal to another slice. 541 + */ 542 + eq(other) { 543 + return this.content.eq(other.content) && this.openStart == other.openStart && this.openEnd == other.openEnd; 544 + } 545 + /** 546 + @internal 547 + */ 548 + toString() { 549 + return this.content + "(" + this.openStart + "," + this.openEnd + ")"; 550 + } 551 + /** 552 + Convert a slice to a JSON-serializable representation. 553 + */ 554 + toJSON() { 555 + if (!this.content.size) 556 + return null; 557 + let json = { content: this.content.toJSON() }; 558 + if (this.openStart > 0) 559 + json.openStart = this.openStart; 560 + if (this.openEnd > 0) 561 + json.openEnd = this.openEnd; 562 + return json; 563 + } 564 + /** 565 + Deserialize a slice from its JSON representation. 566 + */ 567 + static fromJSON(schema, json) { 568 + if (!json) 569 + return _Slice.empty; 570 + let openStart = json.openStart || 0, openEnd = json.openEnd || 0; 571 + if (typeof openStart != "number" || typeof openEnd != "number") 572 + throw new RangeError("Invalid input for Slice.fromJSON"); 573 + return new _Slice(Fragment.fromJSON(schema, json.content), openStart, openEnd); 574 + } 575 + /** 576 + Create a slice from a fragment by taking the maximum possible 577 + open value on both side of the fragment. 578 + */ 579 + static maxOpen(fragment, openIsolating = true) { 580 + let openStart = 0, openEnd = 0; 581 + for (let n = fragment.firstChild; n && !n.isLeaf && (openIsolating || !n.type.spec.isolating); n = n.firstChild) 582 + openStart++; 583 + for (let n = fragment.lastChild; n && !n.isLeaf && (openIsolating || !n.type.spec.isolating); n = n.lastChild) 584 + openEnd++; 585 + return new _Slice(fragment, openStart, openEnd); 586 + } 587 + }; 588 + Slice.empty = new Slice(Fragment.empty, 0, 0); 589 + function removeRange(content, from, to) { 590 + let { index, offset } = content.findIndex(from), child = content.maybeChild(index); 591 + let { index: indexTo, offset: offsetTo } = content.findIndex(to); 592 + if (offset == from || child.isText) { 593 + if (offsetTo != to && !content.child(indexTo).isText) 594 + throw new RangeError("Removing non-flat range"); 595 + return content.cut(0, from).append(content.cut(to)); 596 + } 597 + if (index != indexTo) 598 + throw new RangeError("Removing non-flat range"); 599 + return content.replaceChild(index, child.copy(removeRange(child.content, from - offset - 1, to - offset - 1))); 600 + } 601 + function insertInto(content, dist, insert, parent) { 602 + let { index, offset } = content.findIndex(dist), child = content.maybeChild(index); 603 + if (offset == dist || child.isText) { 604 + if (parent && !parent.canReplace(index, index, insert)) 605 + return null; 606 + return content.cut(0, dist).append(insert).append(content.cut(dist)); 607 + } 608 + let inner = insertInto(child.content, dist - offset - 1, insert, child); 609 + return inner && content.replaceChild(index, child.copy(inner)); 610 + } 611 + function replace($from, $to, slice) { 612 + if (slice.openStart > $from.depth) 613 + throw new ReplaceError("Inserted content deeper than insertion position"); 614 + if ($from.depth - slice.openStart != $to.depth - slice.openEnd) 615 + throw new ReplaceError("Inconsistent open depths"); 616 + return replaceOuter($from, $to, slice, 0); 617 + } 618 + function replaceOuter($from, $to, slice, depth) { 619 + let index = $from.index(depth), node = $from.node(depth); 620 + if (index == $to.index(depth) && depth < $from.depth - slice.openStart) { 621 + let inner = replaceOuter($from, $to, slice, depth + 1); 622 + return node.copy(node.content.replaceChild(index, inner)); 623 + } else if (!slice.content.size) { 624 + return close(node, replaceTwoWay($from, $to, depth)); 625 + } else if (!slice.openStart && !slice.openEnd && $from.depth == depth && $to.depth == depth) { 626 + let parent = $from.parent, content = parent.content; 627 + return close(parent, content.cut(0, $from.parentOffset).append(slice.content).append(content.cut($to.parentOffset))); 628 + } else { 629 + let { start, end } = prepareSliceForReplace(slice, $from); 630 + return close(node, replaceThreeWay($from, start, end, $to, depth)); 631 + } 632 + } 633 + function checkJoin(main, sub) { 634 + if (!sub.type.compatibleContent(main.type)) 635 + throw new ReplaceError("Cannot join " + sub.type.name + " onto " + main.type.name); 636 + } 637 + function joinable($before, $after, depth) { 638 + let node = $before.node(depth); 639 + checkJoin(node, $after.node(depth)); 640 + return node; 641 + } 642 + function addNode(child, target) { 643 + let last = target.length - 1; 644 + if (last >= 0 && child.isText && child.sameMarkup(target[last])) 645 + target[last] = child.withText(target[last].text + child.text); 646 + else 647 + target.push(child); 648 + } 649 + function addRange($start, $end, depth, target) { 650 + let node = ($end || $start).node(depth); 651 + let startIndex = 0, endIndex = $end ? $end.index(depth) : node.childCount; 652 + if ($start) { 653 + startIndex = $start.index(depth); 654 + if ($start.depth > depth) { 655 + startIndex++; 656 + } else if ($start.textOffset) { 657 + addNode($start.nodeAfter, target); 658 + startIndex++; 659 + } 660 + } 661 + for (let i = startIndex; i < endIndex; i++) 662 + addNode(node.child(i), target); 663 + if ($end && $end.depth == depth && $end.textOffset) 664 + addNode($end.nodeBefore, target); 665 + } 666 + function close(node, content) { 667 + node.type.checkContent(content); 668 + return node.copy(content); 669 + } 670 + function replaceThreeWay($from, $start, $end, $to, depth) { 671 + let openStart = $from.depth > depth && joinable($from, $start, depth + 1); 672 + let openEnd = $to.depth > depth && joinable($end, $to, depth + 1); 673 + let content = []; 674 + addRange(null, $from, depth, content); 675 + if (openStart && openEnd && $start.index(depth) == $end.index(depth)) { 676 + checkJoin(openStart, openEnd); 677 + addNode(close(openStart, replaceThreeWay($from, $start, $end, $to, depth + 1)), content); 678 + } else { 679 + if (openStart) 680 + addNode(close(openStart, replaceTwoWay($from, $start, depth + 1)), content); 681 + addRange($start, $end, depth, content); 682 + if (openEnd) 683 + addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content); 684 + } 685 + addRange($to, null, depth, content); 686 + return new Fragment(content); 687 + } 688 + function replaceTwoWay($from, $to, depth) { 689 + let content = []; 690 + addRange(null, $from, depth, content); 691 + if ($from.depth > depth) { 692 + let type = joinable($from, $to, depth + 1); 693 + addNode(close(type, replaceTwoWay($from, $to, depth + 1)), content); 694 + } 695 + addRange($to, null, depth, content); 696 + return new Fragment(content); 697 + } 698 + function prepareSliceForReplace(slice, $along) { 699 + let extra = $along.depth - slice.openStart, parent = $along.node(extra); 700 + let node = parent.copy(slice.content); 701 + for (let i = extra - 1; i >= 0; i--) 702 + node = $along.node(i).copy(Fragment.from(node)); 703 + return { 704 + start: node.resolveNoCache(slice.openStart + extra), 705 + end: node.resolveNoCache(node.content.size - slice.openEnd - extra) 706 + }; 707 + } 708 + var ResolvedPos = class _ResolvedPos { 709 + /** 710 + @internal 711 + */ 712 + constructor(pos, path, parentOffset) { 713 + this.pos = pos; 714 + this.path = path; 715 + this.parentOffset = parentOffset; 716 + this.depth = path.length / 3 - 1; 717 + } 718 + /** 719 + @internal 720 + */ 721 + resolveDepth(val) { 722 + if (val == null) 723 + return this.depth; 724 + if (val < 0) 725 + return this.depth + val; 726 + return val; 727 + } 728 + /** 729 + The parent node that the position points into. Note that even if 730 + a position points into a text node, that node is not considered 731 + the parent—text nodes are ‘flat’ in this model, and have no content. 732 + */ 733 + get parent() { 734 + return this.node(this.depth); 735 + } 736 + /** 737 + The root node in which the position was resolved. 738 + */ 739 + get doc() { 740 + return this.node(0); 741 + } 742 + /** 743 + The ancestor node at the given level. `p.node(p.depth)` is the 744 + same as `p.parent`. 745 + */ 746 + node(depth) { 747 + return this.path[this.resolveDepth(depth) * 3]; 748 + } 749 + /** 750 + The index into the ancestor at the given level. If this points 751 + at the 3rd node in the 2nd paragraph on the top level, for 752 + example, `p.index(0)` is 1 and `p.index(1)` is 2. 753 + */ 754 + index(depth) { 755 + return this.path[this.resolveDepth(depth) * 3 + 1]; 756 + } 757 + /** 758 + The index pointing after this position into the ancestor at the 759 + given level. 760 + */ 761 + indexAfter(depth) { 762 + depth = this.resolveDepth(depth); 763 + return this.index(depth) + (depth == this.depth && !this.textOffset ? 0 : 1); 764 + } 765 + /** 766 + The (absolute) position at the start of the node at the given 767 + level. 768 + */ 769 + start(depth) { 770 + depth = this.resolveDepth(depth); 771 + return depth == 0 ? 0 : this.path[depth * 3 - 1] + 1; 772 + } 773 + /** 774 + The (absolute) position at the end of the node at the given 775 + level. 776 + */ 777 + end(depth) { 778 + depth = this.resolveDepth(depth); 779 + return this.start(depth) + this.node(depth).content.size; 780 + } 781 + /** 782 + The (absolute) position directly before the wrapping node at the 783 + given level, or, when `depth` is `this.depth + 1`, the original 784 + position. 785 + */ 786 + before(depth) { 787 + depth = this.resolveDepth(depth); 788 + if (!depth) 789 + throw new RangeError("There is no position before the top-level node"); 790 + return depth == this.depth + 1 ? this.pos : this.path[depth * 3 - 1]; 791 + } 792 + /** 793 + The (absolute) position directly after the wrapping node at the 794 + given level, or the original position when `depth` is `this.depth + 1`. 795 + */ 796 + after(depth) { 797 + depth = this.resolveDepth(depth); 798 + if (!depth) 799 + throw new RangeError("There is no position after the top-level node"); 800 + return depth == this.depth + 1 ? this.pos : this.path[depth * 3 - 1] + this.path[depth * 3].nodeSize; 801 + } 802 + /** 803 + When this position points into a text node, this returns the 804 + distance between the position and the start of the text node. 805 + Will be zero for positions that point between nodes. 806 + */ 807 + get textOffset() { 808 + return this.pos - this.path[this.path.length - 1]; 809 + } 810 + /** 811 + Get the node directly after the position, if any. If the position 812 + points into a text node, only the part of that node after the 813 + position is returned. 814 + */ 815 + get nodeAfter() { 816 + let parent = this.parent, index = this.index(this.depth); 817 + if (index == parent.childCount) 818 + return null; 819 + let dOff = this.pos - this.path[this.path.length - 1], child = parent.child(index); 820 + return dOff ? parent.child(index).cut(dOff) : child; 821 + } 822 + /** 823 + Get the node directly before the position, if any. If the 824 + position points into a text node, only the part of that node 825 + before the position is returned. 826 + */ 827 + get nodeBefore() { 828 + let index = this.index(this.depth); 829 + let dOff = this.pos - this.path[this.path.length - 1]; 830 + if (dOff) 831 + return this.parent.child(index).cut(0, dOff); 832 + return index == 0 ? null : this.parent.child(index - 1); 833 + } 834 + /** 835 + Get the position at the given index in the parent node at the 836 + given depth (which defaults to `this.depth`). 837 + */ 838 + posAtIndex(index, depth) { 839 + depth = this.resolveDepth(depth); 840 + let node = this.path[depth * 3], pos = depth == 0 ? 0 : this.path[depth * 3 - 1] + 1; 841 + for (let i = 0; i < index; i++) 842 + pos += node.child(i).nodeSize; 843 + return pos; 844 + } 845 + /** 846 + Get the marks at this position, factoring in the surrounding 847 + marks' [`inclusive`](https://prosemirror.net/docs/ref/#model.MarkSpec.inclusive) property. If the 848 + position is at the start of a non-empty node, the marks of the 849 + node after it (if any) are returned. 850 + */ 851 + marks() { 852 + let parent = this.parent, index = this.index(); 853 + if (parent.content.size == 0) 854 + return Mark.none; 855 + if (this.textOffset) 856 + return parent.child(index).marks; 857 + let main = parent.maybeChild(index - 1), other = parent.maybeChild(index); 858 + if (!main) { 859 + let tmp = main; 860 + main = other; 861 + other = tmp; 862 + } 863 + let marks = main.marks; 864 + for (var i = 0; i < marks.length; i++) 865 + if (marks[i].type.spec.inclusive === false && (!other || !marks[i].isInSet(other.marks))) 866 + marks = marks[i--].removeFromSet(marks); 867 + return marks; 868 + } 869 + /** 870 + Get the marks after the current position, if any, except those 871 + that are non-inclusive and not present at position `$end`. This 872 + is mostly useful for getting the set of marks to preserve after a 873 + deletion. Will return `null` if this position is at the end of 874 + its parent node or its parent node isn't a textblock (in which 875 + case no marks should be preserved). 876 + */ 877 + marksAcross($end) { 878 + let after = this.parent.maybeChild(this.index()); 879 + if (!after || !after.isInline) 880 + return null; 881 + let marks = after.marks, next = $end.parent.maybeChild($end.index()); 882 + for (var i = 0; i < marks.length; i++) 883 + if (marks[i].type.spec.inclusive === false && (!next || !marks[i].isInSet(next.marks))) 884 + marks = marks[i--].removeFromSet(marks); 885 + return marks; 886 + } 887 + /** 888 + The depth up to which this position and the given (non-resolved) 889 + position share the same parent nodes. 890 + */ 891 + sharedDepth(pos) { 892 + for (let depth = this.depth; depth > 0; depth--) 893 + if (this.start(depth) <= pos && this.end(depth) >= pos) 894 + return depth; 895 + return 0; 896 + } 897 + /** 898 + Returns a range based on the place where this position and the 899 + given position diverge around block content. If both point into 900 + the same textblock, for example, a range around that textblock 901 + will be returned. If they point into different blocks, the range 902 + around those blocks in their shared ancestor is returned. You can 903 + pass in an optional predicate that will be called with a parent 904 + node to see if a range into that parent is acceptable. 905 + */ 906 + blockRange(other = this, pred) { 907 + if (other.pos < this.pos) 908 + return other.blockRange(this); 909 + for (let d = this.depth - (this.parent.inlineContent || this.pos == other.pos ? 1 : 0); d >= 0; d--) 910 + if (other.pos <= this.end(d) && (!pred || pred(this.node(d)))) 911 + return new NodeRange(this, other, d); 912 + return null; 913 + } 914 + /** 915 + Query whether the given position shares the same parent node. 916 + */ 917 + sameParent(other) { 918 + return this.pos - this.parentOffset == other.pos - other.parentOffset; 919 + } 920 + /** 921 + Return the greater of this and the given position. 922 + */ 923 + max(other) { 924 + return other.pos > this.pos ? other : this; 925 + } 926 + /** 927 + Return the smaller of this and the given position. 928 + */ 929 + min(other) { 930 + return other.pos < this.pos ? other : this; 931 + } 932 + /** 933 + @internal 934 + */ 935 + toString() { 936 + let str = ""; 937 + for (let i = 1; i <= this.depth; i++) 938 + str += (str ? "/" : "") + this.node(i).type.name + "_" + this.index(i - 1); 939 + return str + ":" + this.parentOffset; 940 + } 941 + /** 942 + @internal 943 + */ 944 + static resolve(doc, pos) { 945 + if (!(pos >= 0 && pos <= doc.content.size)) 946 + throw new RangeError("Position " + pos + " out of range"); 947 + let path = []; 948 + let start = 0, parentOffset = pos; 949 + for (let node = doc; ; ) { 950 + let { index, offset } = node.content.findIndex(parentOffset); 951 + let rem = parentOffset - offset; 952 + path.push(node, index, start + offset); 953 + if (!rem) 954 + break; 955 + node = node.child(index); 956 + if (node.isText) 957 + break; 958 + parentOffset = rem - 1; 959 + start += offset + 1; 960 + } 961 + return new _ResolvedPos(pos, path, parentOffset); 962 + } 963 + /** 964 + @internal 965 + */ 966 + static resolveCached(doc, pos) { 967 + let cache = resolveCache.get(doc); 968 + if (cache) { 969 + for (let i = 0; i < cache.elts.length; i++) { 970 + let elt = cache.elts[i]; 971 + if (elt.pos == pos) 972 + return elt; 973 + } 974 + } else { 975 + resolveCache.set(doc, cache = new ResolveCache()); 976 + } 977 + let result = cache.elts[cache.i] = _ResolvedPos.resolve(doc, pos); 978 + cache.i = (cache.i + 1) % resolveCacheSize; 979 + return result; 980 + } 981 + }; 982 + var ResolveCache = class { 983 + constructor() { 984 + this.elts = []; 985 + this.i = 0; 986 + } 987 + }; 988 + var resolveCacheSize = 12; 989 + var resolveCache = /* @__PURE__ */ new WeakMap(); 990 + var NodeRange = class { 991 + /** 992 + Construct a node range. `$from` and `$to` should point into the 993 + same node until at least the given `depth`, since a node range 994 + denotes an adjacent set of nodes in a single parent node. 995 + */ 996 + constructor($from, $to, depth) { 997 + this.$from = $from; 998 + this.$to = $to; 999 + this.depth = depth; 1000 + } 1001 + /** 1002 + The position at the start of the range. 1003 + */ 1004 + get start() { 1005 + return this.$from.before(this.depth + 1); 1006 + } 1007 + /** 1008 + The position at the end of the range. 1009 + */ 1010 + get end() { 1011 + return this.$to.after(this.depth + 1); 1012 + } 1013 + /** 1014 + The parent node that the range points into. 1015 + */ 1016 + get parent() { 1017 + return this.$from.node(this.depth); 1018 + } 1019 + /** 1020 + The start index of the range in the parent node. 1021 + */ 1022 + get startIndex() { 1023 + return this.$from.index(this.depth); 1024 + } 1025 + /** 1026 + The end index of the range in the parent node. 1027 + */ 1028 + get endIndex() { 1029 + return this.$to.indexAfter(this.depth); 1030 + } 1031 + }; 1032 + var emptyAttrs = /* @__PURE__ */ Object.create(null); 1033 + var Node = class _Node { 1034 + /** 1035 + @internal 1036 + */ 1037 + constructor(type, attrs, content, marks = Mark.none) { 1038 + this.type = type; 1039 + this.attrs = attrs; 1040 + this.marks = marks; 1041 + this.content = content || Fragment.empty; 1042 + } 1043 + /** 1044 + The array of this node's child nodes. 1045 + */ 1046 + get children() { 1047 + return this.content.content; 1048 + } 1049 + /** 1050 + The size of this node, as defined by the integer-based [indexing 1051 + scheme](https://prosemirror.net/docs/guide/#doc.indexing). For text nodes, this is the 1052 + amount of characters. For other leaf nodes, it is one. For 1053 + non-leaf nodes, it is the size of the content plus two (the 1054 + start and end token). 1055 + */ 1056 + get nodeSize() { 1057 + return this.isLeaf ? 1 : 2 + this.content.size; 1058 + } 1059 + /** 1060 + The number of children that the node has. 1061 + */ 1062 + get childCount() { 1063 + return this.content.childCount; 1064 + } 1065 + /** 1066 + Get the child node at the given index. Raises an error when the 1067 + index is out of range. 1068 + */ 1069 + child(index) { 1070 + return this.content.child(index); 1071 + } 1072 + /** 1073 + Get the child node at the given index, if it exists. 1074 + */ 1075 + maybeChild(index) { 1076 + return this.content.maybeChild(index); 1077 + } 1078 + /** 1079 + Call `f` for every child node, passing the node, its offset 1080 + into this parent node, and its index. 1081 + */ 1082 + forEach(f) { 1083 + this.content.forEach(f); 1084 + } 1085 + /** 1086 + Invoke a callback for all descendant nodes recursively between 1087 + the given two positions that are relative to start of this 1088 + node's content. The callback is invoked with the node, its 1089 + position relative to the original node (method receiver), 1090 + its parent node, and its child index. When the callback returns 1091 + false for a given node, that node's children will not be 1092 + recursed over. The last parameter can be used to specify a 1093 + starting position to count from. 1094 + */ 1095 + nodesBetween(from, to, f, startPos = 0) { 1096 + this.content.nodesBetween(from, to, f, startPos, this); 1097 + } 1098 + /** 1099 + Call the given callback for every descendant node. Doesn't 1100 + descend into a node when the callback returns `false`. 1101 + */ 1102 + descendants(f) { 1103 + this.nodesBetween(0, this.content.size, f); 1104 + } 1105 + /** 1106 + Concatenates all the text nodes found in this fragment and its 1107 + children. 1108 + */ 1109 + get textContent() { 1110 + return this.isLeaf && this.type.spec.leafText ? this.type.spec.leafText(this) : this.textBetween(0, this.content.size, ""); 1111 + } 1112 + /** 1113 + Get all text between positions `from` and `to`. When 1114 + `blockSeparator` is given, it will be inserted to separate text 1115 + from different block nodes. If `leafText` is given, it'll be 1116 + inserted for every non-text leaf node encountered, otherwise 1117 + [`leafText`](https://prosemirror.net/docs/ref/#model.NodeSpec.leafText) will be used. 1118 + */ 1119 + textBetween(from, to, blockSeparator, leafText) { 1120 + return this.content.textBetween(from, to, blockSeparator, leafText); 1121 + } 1122 + /** 1123 + Returns this node's first child, or `null` if there are no 1124 + children. 1125 + */ 1126 + get firstChild() { 1127 + return this.content.firstChild; 1128 + } 1129 + /** 1130 + Returns this node's last child, or `null` if there are no 1131 + children. 1132 + */ 1133 + get lastChild() { 1134 + return this.content.lastChild; 1135 + } 1136 + /** 1137 + Test whether two nodes represent the same piece of document. 1138 + */ 1139 + eq(other) { 1140 + return this == other || this.sameMarkup(other) && this.content.eq(other.content); 1141 + } 1142 + /** 1143 + Compare the markup (type, attributes, and marks) of this node to 1144 + those of another. Returns `true` if both have the same markup. 1145 + */ 1146 + sameMarkup(other) { 1147 + return this.hasMarkup(other.type, other.attrs, other.marks); 1148 + } 1149 + /** 1150 + Check whether this node's markup correspond to the given type, 1151 + attributes, and marks. 1152 + */ 1153 + hasMarkup(type, attrs, marks) { 1154 + return this.type == type && compareDeep(this.attrs, attrs || type.defaultAttrs || emptyAttrs) && Mark.sameSet(this.marks, marks || Mark.none); 1155 + } 1156 + /** 1157 + Create a new node with the same markup as this node, containing 1158 + the given content (or empty, if no content is given). 1159 + */ 1160 + copy(content = null) { 1161 + if (content == this.content) 1162 + return this; 1163 + return new _Node(this.type, this.attrs, content, this.marks); 1164 + } 1165 + /** 1166 + Create a copy of this node, with the given set of marks instead 1167 + of the node's own marks. 1168 + */ 1169 + mark(marks) { 1170 + return marks == this.marks ? this : new _Node(this.type, this.attrs, this.content, marks); 1171 + } 1172 + /** 1173 + Create a copy of this node with only the content between the 1174 + given positions. If `to` is not given, it defaults to the end of 1175 + the node. 1176 + */ 1177 + cut(from, to = this.content.size) { 1178 + if (from == 0 && to == this.content.size) 1179 + return this; 1180 + return this.copy(this.content.cut(from, to)); 1181 + } 1182 + /** 1183 + Cut out the part of the document between the given positions, and 1184 + return it as a `Slice` object. 1185 + */ 1186 + slice(from, to = this.content.size, includeParents = false) { 1187 + if (from == to) 1188 + return Slice.empty; 1189 + let $from = this.resolve(from), $to = this.resolve(to); 1190 + let depth = includeParents ? 0 : $from.sharedDepth(to); 1191 + let start = $from.start(depth), node = $from.node(depth); 1192 + let content = node.content.cut($from.pos - start, $to.pos - start); 1193 + return new Slice(content, $from.depth - depth, $to.depth - depth); 1194 + } 1195 + /** 1196 + Replace the part of the document between the given positions with 1197 + the given slice. The slice must 'fit', meaning its open sides 1198 + must be able to connect to the surrounding content, and its 1199 + content nodes must be valid children for the node they are placed 1200 + into. If any of this is violated, an error of type 1201 + [`ReplaceError`](https://prosemirror.net/docs/ref/#model.ReplaceError) is thrown. 1202 + */ 1203 + replace(from, to, slice) { 1204 + return replace(this.resolve(from), this.resolve(to), slice); 1205 + } 1206 + /** 1207 + Find the node directly after the given position. 1208 + */ 1209 + nodeAt(pos) { 1210 + for (let node = this; ; ) { 1211 + let { index, offset } = node.content.findIndex(pos); 1212 + node = node.maybeChild(index); 1213 + if (!node) 1214 + return null; 1215 + if (offset == pos || node.isText) 1216 + return node; 1217 + pos -= offset + 1; 1218 + } 1219 + } 1220 + /** 1221 + Find the (direct) child node after the given offset, if any, 1222 + and return it along with its index and offset relative to this 1223 + node. 1224 + */ 1225 + childAfter(pos) { 1226 + let { index, offset } = this.content.findIndex(pos); 1227 + return { node: this.content.maybeChild(index), index, offset }; 1228 + } 1229 + /** 1230 + Find the (direct) child node before the given offset, if any, 1231 + and return it along with its index and offset relative to this 1232 + node. 1233 + */ 1234 + childBefore(pos) { 1235 + if (pos == 0) 1236 + return { node: null, index: 0, offset: 0 }; 1237 + let { index, offset } = this.content.findIndex(pos); 1238 + if (offset < pos) 1239 + return { node: this.content.child(index), index, offset }; 1240 + let node = this.content.child(index - 1); 1241 + return { node, index: index - 1, offset: offset - node.nodeSize }; 1242 + } 1243 + /** 1244 + Resolve the given position in the document, returning an 1245 + [object](https://prosemirror.net/docs/ref/#model.ResolvedPos) with information about its context. 1246 + */ 1247 + resolve(pos) { 1248 + return ResolvedPos.resolveCached(this, pos); 1249 + } 1250 + /** 1251 + @internal 1252 + */ 1253 + resolveNoCache(pos) { 1254 + return ResolvedPos.resolve(this, pos); 1255 + } 1256 + /** 1257 + Test whether a given mark or mark type occurs in this document 1258 + between the two given positions. 1259 + */ 1260 + rangeHasMark(from, to, type) { 1261 + let found2 = false; 1262 + if (to > from) 1263 + this.nodesBetween(from, to, (node) => { 1264 + if (type.isInSet(node.marks)) 1265 + found2 = true; 1266 + return !found2; 1267 + }); 1268 + return found2; 1269 + } 1270 + /** 1271 + True when this is a block (non-inline node) 1272 + */ 1273 + get isBlock() { 1274 + return this.type.isBlock; 1275 + } 1276 + /** 1277 + True when this is a textblock node, a block node with inline 1278 + content. 1279 + */ 1280 + get isTextblock() { 1281 + return this.type.isTextblock; 1282 + } 1283 + /** 1284 + True when this node allows inline content. 1285 + */ 1286 + get inlineContent() { 1287 + return this.type.inlineContent; 1288 + } 1289 + /** 1290 + True when this is an inline node (a text node or a node that can 1291 + appear among text). 1292 + */ 1293 + get isInline() { 1294 + return this.type.isInline; 1295 + } 1296 + /** 1297 + True when this is a text node. 1298 + */ 1299 + get isText() { 1300 + return this.type.isText; 1301 + } 1302 + /** 1303 + True when this is a leaf node. 1304 + */ 1305 + get isLeaf() { 1306 + return this.type.isLeaf; 1307 + } 1308 + /** 1309 + True when this is an atom, i.e. when it does not have directly 1310 + editable content. This is usually the same as `isLeaf`, but can 1311 + be configured with the [`atom` property](https://prosemirror.net/docs/ref/#model.NodeSpec.atom) 1312 + on a node's spec (typically used when the node is displayed as 1313 + an uneditable [node view](https://prosemirror.net/docs/ref/#view.NodeView)). 1314 + */ 1315 + get isAtom() { 1316 + return this.type.isAtom; 1317 + } 1318 + /** 1319 + Return a string representation of this node for debugging 1320 + purposes. 1321 + */ 1322 + toString() { 1323 + if (this.type.spec.toDebugString) 1324 + return this.type.spec.toDebugString(this); 1325 + let name = this.type.name; 1326 + if (this.content.size) 1327 + name += "(" + this.content.toStringInner() + ")"; 1328 + return wrapMarks(this.marks, name); 1329 + } 1330 + /** 1331 + Get the content match in this node at the given index. 1332 + */ 1333 + contentMatchAt(index) { 1334 + let match = this.type.contentMatch.matchFragment(this.content, 0, index); 1335 + if (!match) 1336 + throw new Error("Called contentMatchAt on a node with invalid content"); 1337 + return match; 1338 + } 1339 + /** 1340 + Test whether replacing the range between `from` and `to` (by 1341 + child index) with the given replacement fragment (which defaults 1342 + to the empty fragment) would leave the node's content valid. You 1343 + can optionally pass `start` and `end` indices into the 1344 + replacement fragment. 1345 + */ 1346 + canReplace(from, to, replacement = Fragment.empty, start = 0, end = replacement.childCount) { 1347 + let one = this.contentMatchAt(from).matchFragment(replacement, start, end); 1348 + let two = one && one.matchFragment(this.content, to); 1349 + if (!two || !two.validEnd) 1350 + return false; 1351 + for (let i = start; i < end; i++) 1352 + if (!this.type.allowsMarks(replacement.child(i).marks)) 1353 + return false; 1354 + return true; 1355 + } 1356 + /** 1357 + Test whether replacing the range `from` to `to` (by index) with 1358 + a node of the given type would leave the node's content valid. 1359 + */ 1360 + canReplaceWith(from, to, type, marks) { 1361 + if (marks && !this.type.allowsMarks(marks)) 1362 + return false; 1363 + let start = this.contentMatchAt(from).matchType(type); 1364 + let end = start && start.matchFragment(this.content, to); 1365 + return end ? end.validEnd : false; 1366 + } 1367 + /** 1368 + Test whether the given node's content could be appended to this 1369 + node. If that node is empty, this will only return true if there 1370 + is at least one node type that can appear in both nodes (to avoid 1371 + merging completely incompatible nodes). 1372 + */ 1373 + canAppend(other) { 1374 + if (other.content.size) 1375 + return this.canReplace(this.childCount, this.childCount, other.content); 1376 + else 1377 + return this.type.compatibleContent(other.type); 1378 + } 1379 + /** 1380 + Check whether this node and its descendants conform to the 1381 + schema, and raise an exception when they do not. 1382 + */ 1383 + check() { 1384 + this.type.checkContent(this.content); 1385 + this.type.checkAttrs(this.attrs); 1386 + let copy = Mark.none; 1387 + for (let i = 0; i < this.marks.length; i++) { 1388 + let mark = this.marks[i]; 1389 + mark.type.checkAttrs(mark.attrs); 1390 + copy = mark.addToSet(copy); 1391 + } 1392 + if (!Mark.sameSet(copy, this.marks)) 1393 + throw new RangeError(`Invalid collection of marks for node ${this.type.name}: ${this.marks.map((m) => m.type.name)}`); 1394 + this.content.forEach((node) => node.check()); 1395 + } 1396 + /** 1397 + Return a JSON-serializeable representation of this node. 1398 + */ 1399 + toJSON() { 1400 + let obj = { type: this.type.name }; 1401 + for (let _ in this.attrs) { 1402 + obj.attrs = this.attrs; 1403 + break; 1404 + } 1405 + if (this.content.size) 1406 + obj.content = this.content.toJSON(); 1407 + if (this.marks.length) 1408 + obj.marks = this.marks.map((n) => n.toJSON()); 1409 + return obj; 1410 + } 1411 + /** 1412 + Deserialize a node from its JSON representation. 1413 + */ 1414 + static fromJSON(schema, json) { 1415 + if (!json) 1416 + throw new RangeError("Invalid input for Node.fromJSON"); 1417 + let marks = void 0; 1418 + if (json.marks) { 1419 + if (!Array.isArray(json.marks)) 1420 + throw new RangeError("Invalid mark data for Node.fromJSON"); 1421 + marks = json.marks.map(schema.markFromJSON); 1422 + } 1423 + if (json.type == "text") { 1424 + if (typeof json.text != "string") 1425 + throw new RangeError("Invalid text node in JSON"); 1426 + return schema.text(json.text, marks); 1427 + } 1428 + let content = Fragment.fromJSON(schema, json.content); 1429 + let node = schema.nodeType(json.type).create(json.attrs, content, marks); 1430 + node.type.checkAttrs(node.attrs); 1431 + return node; 1432 + } 1433 + }; 1434 + Node.prototype.text = void 0; 1435 + function wrapMarks(marks, str) { 1436 + for (let i = marks.length - 1; i >= 0; i--) 1437 + str = marks[i].type.name + "(" + str + ")"; 1438 + return str; 1439 + } 1440 + var ContentMatch = class _ContentMatch { 1441 + /** 1442 + @internal 1443 + */ 1444 + constructor(validEnd) { 1445 + this.validEnd = validEnd; 1446 + this.next = []; 1447 + this.wrapCache = []; 1448 + } 1449 + /** 1450 + @internal 1451 + */ 1452 + static parse(string, nodeTypes) { 1453 + let stream = new TokenStream(string, nodeTypes); 1454 + if (stream.next == null) 1455 + return _ContentMatch.empty; 1456 + let expr = parseExpr(stream); 1457 + if (stream.next) 1458 + stream.err("Unexpected trailing text"); 1459 + let match = dfa(nfa(expr)); 1460 + checkForDeadEnds(match, stream); 1461 + return match; 1462 + } 1463 + /** 1464 + Match a node type, returning a match after that node if 1465 + successful. 1466 + */ 1467 + matchType(type) { 1468 + for (let i = 0; i < this.next.length; i++) 1469 + if (this.next[i].type == type) 1470 + return this.next[i].next; 1471 + return null; 1472 + } 1473 + /** 1474 + Try to match a fragment. Returns the resulting match when 1475 + successful. 1476 + */ 1477 + matchFragment(frag, start = 0, end = frag.childCount) { 1478 + let cur = this; 1479 + for (let i = start; cur && i < end; i++) 1480 + cur = cur.matchType(frag.child(i).type); 1481 + return cur; 1482 + } 1483 + /** 1484 + @internal 1485 + */ 1486 + get inlineContent() { 1487 + return this.next.length != 0 && this.next[0].type.isInline; 1488 + } 1489 + /** 1490 + Get the first matching node type at this match position that can 1491 + be generated. 1492 + */ 1493 + get defaultType() { 1494 + for (let i = 0; i < this.next.length; i++) { 1495 + let { type } = this.next[i]; 1496 + if (!(type.isText || type.hasRequiredAttrs())) 1497 + return type; 1498 + } 1499 + return null; 1500 + } 1501 + /** 1502 + @internal 1503 + */ 1504 + compatible(other) { 1505 + for (let i = 0; i < this.next.length; i++) 1506 + for (let j = 0; j < other.next.length; j++) 1507 + if (this.next[i].type == other.next[j].type) 1508 + return true; 1509 + return false; 1510 + } 1511 + /** 1512 + Try to match the given fragment, and if that fails, see if it can 1513 + be made to match by inserting nodes in front of it. When 1514 + successful, return a fragment of inserted nodes (which may be 1515 + empty if nothing had to be inserted). When `toEnd` is true, only 1516 + return a fragment if the resulting match goes to the end of the 1517 + content expression. 1518 + */ 1519 + fillBefore(after, toEnd = false, startIndex = 0) { 1520 + let seen = [this]; 1521 + function search(match, types) { 1522 + let finished = match.matchFragment(after, startIndex); 1523 + if (finished && (!toEnd || finished.validEnd)) 1524 + return Fragment.from(types.map((tp) => tp.createAndFill())); 1525 + for (let i = 0; i < match.next.length; i++) { 1526 + let { type, next } = match.next[i]; 1527 + if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) { 1528 + seen.push(next); 1529 + let found2 = search(next, types.concat(type)); 1530 + if (found2) 1531 + return found2; 1532 + } 1533 + } 1534 + return null; 1535 + } 1536 + return search(this, []); 1537 + } 1538 + /** 1539 + Find a set of wrapping node types that would allow a node of the 1540 + given type to appear at this position. The result may be empty 1541 + (when it fits directly) and will be null when no such wrapping 1542 + exists. 1543 + */ 1544 + findWrapping(target) { 1545 + for (let i = 0; i < this.wrapCache.length; i += 2) 1546 + if (this.wrapCache[i] == target) 1547 + return this.wrapCache[i + 1]; 1548 + let computed = this.computeWrapping(target); 1549 + this.wrapCache.push(target, computed); 1550 + return computed; 1551 + } 1552 + /** 1553 + @internal 1554 + */ 1555 + computeWrapping(target) { 1556 + let seen = /* @__PURE__ */ Object.create(null), active = [{ match: this, type: null, via: null }]; 1557 + while (active.length) { 1558 + let current = active.shift(), match = current.match; 1559 + if (match.matchType(target)) { 1560 + let result = []; 1561 + for (let obj = current; obj.type; obj = obj.via) 1562 + result.push(obj.type); 1563 + return result.reverse(); 1564 + } 1565 + for (let i = 0; i < match.next.length; i++) { 1566 + let { type, next } = match.next[i]; 1567 + if (!type.isLeaf && !type.hasRequiredAttrs() && !(type.name in seen) && (!current.type || next.validEnd)) { 1568 + active.push({ match: type.contentMatch, type, via: current }); 1569 + seen[type.name] = true; 1570 + } 1571 + } 1572 + } 1573 + return null; 1574 + } 1575 + /** 1576 + The number of outgoing edges this node has in the finite 1577 + automaton that describes the content expression. 1578 + */ 1579 + get edgeCount() { 1580 + return this.next.length; 1581 + } 1582 + /** 1583 + Get the _n_​th outgoing edge from this node in the finite 1584 + automaton that describes the content expression. 1585 + */ 1586 + edge(n) { 1587 + if (n >= this.next.length) 1588 + throw new RangeError(`There's no ${n}th edge in this content match`); 1589 + return this.next[n]; 1590 + } 1591 + /** 1592 + @internal 1593 + */ 1594 + toString() { 1595 + let seen = []; 1596 + function scan(m) { 1597 + seen.push(m); 1598 + for (let i = 0; i < m.next.length; i++) 1599 + if (seen.indexOf(m.next[i].next) == -1) 1600 + scan(m.next[i].next); 1601 + } 1602 + scan(this); 1603 + return seen.map((m, i) => { 1604 + let out = i + (m.validEnd ? "*" : " ") + " "; 1605 + for (let i2 = 0; i2 < m.next.length; i2++) 1606 + out += (i2 ? ", " : "") + m.next[i2].type.name + "->" + seen.indexOf(m.next[i2].next); 1607 + return out; 1608 + }).join("\n"); 1609 + } 1610 + }; 1611 + ContentMatch.empty = new ContentMatch(true); 1612 + var TokenStream = class { 1613 + constructor(string, nodeTypes) { 1614 + this.string = string; 1615 + this.nodeTypes = nodeTypes; 1616 + this.inline = null; 1617 + this.pos = 0; 1618 + this.tokens = string.split(/\s*(?=\b|\W|$)/); 1619 + if (this.tokens[this.tokens.length - 1] == "") 1620 + this.tokens.pop(); 1621 + if (this.tokens[0] == "") 1622 + this.tokens.shift(); 1623 + } 1624 + get next() { 1625 + return this.tokens[this.pos]; 1626 + } 1627 + eat(tok) { 1628 + return this.next == tok && (this.pos++ || true); 1629 + } 1630 + err(str) { 1631 + throw new SyntaxError(str + " (in content expression '" + this.string + "')"); 1632 + } 1633 + }; 1634 + function parseExpr(stream) { 1635 + let exprs = []; 1636 + do { 1637 + exprs.push(parseExprSeq(stream)); 1638 + } while (stream.eat("|")); 1639 + return exprs.length == 1 ? exprs[0] : { type: "choice", exprs }; 1640 + } 1641 + function parseExprSeq(stream) { 1642 + let exprs = []; 1643 + do { 1644 + exprs.push(parseExprSubscript(stream)); 1645 + } while (stream.next && stream.next != ")" && stream.next != "|"); 1646 + return exprs.length == 1 ? exprs[0] : { type: "seq", exprs }; 1647 + } 1648 + function parseExprSubscript(stream) { 1649 + let expr = parseExprAtom(stream); 1650 + for (; ; ) { 1651 + if (stream.eat("+")) 1652 + expr = { type: "plus", expr }; 1653 + else if (stream.eat("*")) 1654 + expr = { type: "star", expr }; 1655 + else if (stream.eat("?")) 1656 + expr = { type: "opt", expr }; 1657 + else if (stream.eat("{")) 1658 + expr = parseExprRange(stream, expr); 1659 + else 1660 + break; 1661 + } 1662 + return expr; 1663 + } 1664 + function parseNum(stream) { 1665 + if (/\D/.test(stream.next)) 1666 + stream.err("Expected number, got '" + stream.next + "'"); 1667 + let result = Number(stream.next); 1668 + stream.pos++; 1669 + return result; 1670 + } 1671 + function parseExprRange(stream, expr) { 1672 + let min = parseNum(stream), max = min; 1673 + if (stream.eat(",")) { 1674 + if (stream.next != "}") 1675 + max = parseNum(stream); 1676 + else 1677 + max = -1; 1678 + } 1679 + if (!stream.eat("}")) 1680 + stream.err("Unclosed braced range"); 1681 + return { type: "range", min, max, expr }; 1682 + } 1683 + function resolveName(stream, name) { 1684 + let types = stream.nodeTypes, type = types[name]; 1685 + if (type) 1686 + return [type]; 1687 + let result = []; 1688 + for (let typeName in types) { 1689 + let type2 = types[typeName]; 1690 + if (type2.isInGroup(name)) 1691 + result.push(type2); 1692 + } 1693 + if (result.length == 0) 1694 + stream.err("No node type or group '" + name + "' found"); 1695 + return result; 1696 + } 1697 + function parseExprAtom(stream) { 1698 + if (stream.eat("(")) { 1699 + let expr = parseExpr(stream); 1700 + if (!stream.eat(")")) 1701 + stream.err("Missing closing paren"); 1702 + return expr; 1703 + } else if (!/\W/.test(stream.next)) { 1704 + let exprs = resolveName(stream, stream.next).map((type) => { 1705 + if (stream.inline == null) 1706 + stream.inline = type.isInline; 1707 + else if (stream.inline != type.isInline) 1708 + stream.err("Mixing inline and block content"); 1709 + return { type: "name", value: type }; 1710 + }); 1711 + stream.pos++; 1712 + return exprs.length == 1 ? exprs[0] : { type: "choice", exprs }; 1713 + } else { 1714 + stream.err("Unexpected token '" + stream.next + "'"); 1715 + } 1716 + } 1717 + function nfa(expr) { 1718 + let nfa2 = [[]]; 1719 + connect(compile(expr, 0), node()); 1720 + return nfa2; 1721 + function node() { 1722 + return nfa2.push([]) - 1; 1723 + } 1724 + function edge(from, to, term) { 1725 + let edge2 = { term, to }; 1726 + nfa2[from].push(edge2); 1727 + return edge2; 1728 + } 1729 + function connect(edges, to) { 1730 + edges.forEach((edge2) => edge2.to = to); 1731 + } 1732 + function compile(expr2, from) { 1733 + if (expr2.type == "choice") { 1734 + return expr2.exprs.reduce((out, expr3) => out.concat(compile(expr3, from)), []); 1735 + } else if (expr2.type == "seq") { 1736 + for (let i = 0; ; i++) { 1737 + let next = compile(expr2.exprs[i], from); 1738 + if (i == expr2.exprs.length - 1) 1739 + return next; 1740 + connect(next, from = node()); 1741 + } 1742 + } else if (expr2.type == "star") { 1743 + let loop = node(); 1744 + edge(from, loop); 1745 + connect(compile(expr2.expr, loop), loop); 1746 + return [edge(loop)]; 1747 + } else if (expr2.type == "plus") { 1748 + let loop = node(); 1749 + connect(compile(expr2.expr, from), loop); 1750 + connect(compile(expr2.expr, loop), loop); 1751 + return [edge(loop)]; 1752 + } else if (expr2.type == "opt") { 1753 + return [edge(from)].concat(compile(expr2.expr, from)); 1754 + } else if (expr2.type == "range") { 1755 + let cur = from; 1756 + for (let i = 0; i < expr2.min; i++) { 1757 + let next = node(); 1758 + connect(compile(expr2.expr, cur), next); 1759 + cur = next; 1760 + } 1761 + if (expr2.max == -1) { 1762 + connect(compile(expr2.expr, cur), cur); 1763 + } else { 1764 + for (let i = expr2.min; i < expr2.max; i++) { 1765 + let next = node(); 1766 + edge(cur, next); 1767 + connect(compile(expr2.expr, cur), next); 1768 + cur = next; 1769 + } 1770 + } 1771 + return [edge(cur)]; 1772 + } else if (expr2.type == "name") { 1773 + return [edge(from, void 0, expr2.value)]; 1774 + } else { 1775 + throw new Error("Unknown expr type"); 1776 + } 1777 + } 1778 + } 1779 + function cmp(a, b) { 1780 + return b - a; 1781 + } 1782 + function nullFrom(nfa2, node) { 1783 + let result = []; 1784 + scan(node); 1785 + return result.sort(cmp); 1786 + function scan(node2) { 1787 + let edges = nfa2[node2]; 1788 + if (edges.length == 1 && !edges[0].term) 1789 + return scan(edges[0].to); 1790 + result.push(node2); 1791 + for (let i = 0; i < edges.length; i++) { 1792 + let { term, to } = edges[i]; 1793 + if (!term && result.indexOf(to) == -1) 1794 + scan(to); 1795 + } 1796 + } 1797 + } 1798 + function dfa(nfa2) { 1799 + let labeled = /* @__PURE__ */ Object.create(null); 1800 + return explore(nullFrom(nfa2, 0)); 1801 + function explore(states) { 1802 + let out = []; 1803 + states.forEach((node) => { 1804 + nfa2[node].forEach(({ term, to }) => { 1805 + if (!term) 1806 + return; 1807 + let set; 1808 + for (let i = 0; i < out.length; i++) 1809 + if (out[i][0] == term) 1810 + set = out[i][1]; 1811 + nullFrom(nfa2, to).forEach((node2) => { 1812 + if (!set) 1813 + out.push([term, set = []]); 1814 + if (set.indexOf(node2) == -1) 1815 + set.push(node2); 1816 + }); 1817 + }); 1818 + }); 1819 + let state = labeled[states.join(",")] = new ContentMatch(states.indexOf(nfa2.length - 1) > -1); 1820 + for (let i = 0; i < out.length; i++) { 1821 + let states2 = out[i][1].sort(cmp); 1822 + state.next.push({ type: out[i][0], next: labeled[states2.join(",")] || explore(states2) }); 1823 + } 1824 + return state; 1825 + } 1826 + } 1827 + function checkForDeadEnds(match, stream) { 1828 + for (let i = 0, work = [match]; i < work.length; i++) { 1829 + let state = work[i], dead = !state.validEnd, nodes = []; 1830 + for (let j = 0; j < state.next.length; j++) { 1831 + let { type, next } = state.next[j]; 1832 + nodes.push(type.name); 1833 + if (dead && !(type.isText || type.hasRequiredAttrs())) 1834 + dead = false; 1835 + if (work.indexOf(next) == -1) 1836 + work.push(next); 1837 + } 1838 + if (dead) 1839 + stream.err("Only non-generatable nodes (" + nodes.join(", ") + ") in a required position (see https://prosemirror.net/docs/guide/#generatable)"); 1840 + } 1841 + } 1842 + 1843 + // node_modules/prosemirror-transform/dist/index.js 1844 + var lower16 = 65535; 1845 + var factor16 = Math.pow(2, 16); 1846 + function makeRecover(index, offset) { 1847 + return index + offset * factor16; 1848 + } 1849 + function recoverIndex(value) { 1850 + return value & lower16; 1851 + } 1852 + function recoverOffset(value) { 1853 + return (value - (value & lower16)) / factor16; 1854 + } 1855 + var DEL_BEFORE = 1; 1856 + var DEL_AFTER = 2; 1857 + var DEL_ACROSS = 4; 1858 + var DEL_SIDE = 8; 1859 + var MapResult = class { 1860 + /** 1861 + @internal 1862 + */ 1863 + constructor(pos, delInfo, recover) { 1864 + this.pos = pos; 1865 + this.delInfo = delInfo; 1866 + this.recover = recover; 1867 + } 1868 + /** 1869 + Tells you whether the position was deleted, that is, whether the 1870 + step removed the token on the side queried (via the `assoc`) 1871 + argument from the document. 1872 + */ 1873 + get deleted() { 1874 + return (this.delInfo & DEL_SIDE) > 0; 1875 + } 1876 + /** 1877 + Tells you whether the token before the mapped position was deleted. 1878 + */ 1879 + get deletedBefore() { 1880 + return (this.delInfo & (DEL_BEFORE | DEL_ACROSS)) > 0; 1881 + } 1882 + /** 1883 + True when the token after the mapped position was deleted. 1884 + */ 1885 + get deletedAfter() { 1886 + return (this.delInfo & (DEL_AFTER | DEL_ACROSS)) > 0; 1887 + } 1888 + /** 1889 + Tells whether any of the steps mapped through deletes across the 1890 + position (including both the token before and after the 1891 + position). 1892 + */ 1893 + get deletedAcross() { 1894 + return (this.delInfo & DEL_ACROSS) > 0; 1895 + } 1896 + }; 1897 + var StepMap = class _StepMap { 1898 + /** 1899 + Create a position map. The modifications to the document are 1900 + represented as an array of numbers, in which each group of three 1901 + represents a modified chunk as `[start, oldSize, newSize]`. 1902 + */ 1903 + constructor(ranges, inverted = false) { 1904 + this.ranges = ranges; 1905 + this.inverted = inverted; 1906 + if (!ranges.length && _StepMap.empty) 1907 + return _StepMap.empty; 1908 + } 1909 + /** 1910 + @internal 1911 + */ 1912 + recover(value) { 1913 + let diff = 0, index = recoverIndex(value); 1914 + if (!this.inverted) 1915 + for (let i = 0; i < index; i++) 1916 + diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1]; 1917 + return this.ranges[index * 3] + diff + recoverOffset(value); 1918 + } 1919 + mapResult(pos, assoc = 1) { 1920 + return this._map(pos, assoc, false); 1921 + } 1922 + map(pos, assoc = 1) { 1923 + return this._map(pos, assoc, true); 1924 + } 1925 + /** 1926 + @internal 1927 + */ 1928 + _map(pos, assoc, simple) { 1929 + let diff = 0, oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2; 1930 + for (let i = 0; i < this.ranges.length; i += 3) { 1931 + let start = this.ranges[i] - (this.inverted ? diff : 0); 1932 + if (start > pos) 1933 + break; 1934 + let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize; 1935 + if (pos <= end) { 1936 + let side = !oldSize ? assoc : pos == start ? -1 : pos == end ? 1 : assoc; 1937 + let result = start + diff + (side < 0 ? 0 : newSize); 1938 + if (simple) 1939 + return result; 1940 + let recover = pos == (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start); 1941 + let del = pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS; 1942 + if (assoc < 0 ? pos != start : pos != end) 1943 + del |= DEL_SIDE; 1944 + return new MapResult(result, del, recover); 1945 + } 1946 + diff += newSize - oldSize; 1947 + } 1948 + return simple ? pos + diff : new MapResult(pos + diff, 0, null); 1949 + } 1950 + /** 1951 + @internal 1952 + */ 1953 + touches(pos, recover) { 1954 + let diff = 0, index = recoverIndex(recover); 1955 + let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2; 1956 + for (let i = 0; i < this.ranges.length; i += 3) { 1957 + let start = this.ranges[i] - (this.inverted ? diff : 0); 1958 + if (start > pos) 1959 + break; 1960 + let oldSize = this.ranges[i + oldIndex], end = start + oldSize; 1961 + if (pos <= end && i == index * 3) 1962 + return true; 1963 + diff += this.ranges[i + newIndex] - oldSize; 1964 + } 1965 + return false; 1966 + } 1967 + /** 1968 + Calls the given function on each of the changed ranges included in 1969 + this map. 1970 + */ 1971 + forEach(f) { 1972 + let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2; 1973 + for (let i = 0, diff = 0; i < this.ranges.length; i += 3) { 1974 + let start = this.ranges[i], oldStart = start - (this.inverted ? diff : 0), newStart = start + (this.inverted ? 0 : diff); 1975 + let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex]; 1976 + f(oldStart, oldStart + oldSize, newStart, newStart + newSize); 1977 + diff += newSize - oldSize; 1978 + } 1979 + } 1980 + /** 1981 + Create an inverted version of this map. The result can be used to 1982 + map positions in the post-step document to the pre-step document. 1983 + */ 1984 + invert() { 1985 + return new _StepMap(this.ranges, !this.inverted); 1986 + } 1987 + /** 1988 + @internal 1989 + */ 1990 + toString() { 1991 + return (this.inverted ? "-" : "") + JSON.stringify(this.ranges); 1992 + } 1993 + /** 1994 + Create a map that moves all positions by offset `n` (which may be 1995 + negative). This can be useful when applying steps meant for a 1996 + sub-document to a larger document, or vice-versa. 1997 + */ 1998 + static offset(n) { 1999 + return n == 0 ? _StepMap.empty : new _StepMap(n < 0 ? [0, -n, 0] : [0, 0, n]); 2000 + } 2001 + }; 2002 + StepMap.empty = new StepMap([]); 2003 + var stepsByID = /* @__PURE__ */ Object.create(null); 2004 + var Step = class { 2005 + /** 2006 + Get the step map that represents the changes made by this step, 2007 + and which can be used to transform between positions in the old 2008 + and the new document. 2009 + */ 2010 + getMap() { 2011 + return StepMap.empty; 2012 + } 2013 + /** 2014 + Try to merge this step with another one, to be applied directly 2015 + after it. Returns the merged step when possible, null if the 2016 + steps can't be merged. 2017 + */ 2018 + merge(other) { 2019 + return null; 2020 + } 2021 + /** 2022 + Deserialize a step from its JSON representation. Will call 2023 + through to the step class' own implementation of this method. 2024 + */ 2025 + static fromJSON(schema, json) { 2026 + if (!json || !json.stepType) 2027 + throw new RangeError("Invalid input for Step.fromJSON"); 2028 + let type = stepsByID[json.stepType]; 2029 + if (!type) 2030 + throw new RangeError(`No step type ${json.stepType} defined`); 2031 + return type.fromJSON(schema, json); 2032 + } 2033 + /** 2034 + To be able to serialize steps to JSON, each step needs a string 2035 + ID to attach to its JSON representation. Use this method to 2036 + register an ID for your step classes. Try to pick something 2037 + that's unlikely to clash with steps from other modules. 2038 + */ 2039 + static jsonID(id, stepClass) { 2040 + if (id in stepsByID) 2041 + throw new RangeError("Duplicate use of step JSON ID " + id); 2042 + stepsByID[id] = stepClass; 2043 + stepClass.prototype.jsonID = id; 2044 + return stepClass; 2045 + } 2046 + }; 2047 + var StepResult = class _StepResult { 2048 + /** 2049 + @internal 2050 + */ 2051 + constructor(doc, failed) { 2052 + this.doc = doc; 2053 + this.failed = failed; 2054 + } 2055 + /** 2056 + Create a successful step result. 2057 + */ 2058 + static ok(doc) { 2059 + return new _StepResult(doc, null); 2060 + } 2061 + /** 2062 + Create a failed step result. 2063 + */ 2064 + static fail(message) { 2065 + return new _StepResult(null, message); 2066 + } 2067 + /** 2068 + Call [`Node.replace`](https://prosemirror.net/docs/ref/#model.Node.replace) with the given 2069 + arguments. Create a successful result if it succeeds, and a 2070 + failed one if it throws a `ReplaceError`. 2071 + */ 2072 + static fromReplace(doc, from, to, slice) { 2073 + try { 2074 + return _StepResult.ok(doc.replace(from, to, slice)); 2075 + } catch (e) { 2076 + if (e instanceof ReplaceError) 2077 + return _StepResult.fail(e.message); 2078 + throw e; 2079 + } 2080 + } 2081 + }; 2082 + function mapFragment(fragment, f, parent) { 2083 + let mapped = []; 2084 + for (let i = 0; i < fragment.childCount; i++) { 2085 + let child = fragment.child(i); 2086 + if (child.content.size) 2087 + child = child.copy(mapFragment(child.content, f, child)); 2088 + if (child.isInline) 2089 + child = f(child, parent, i); 2090 + mapped.push(child); 2091 + } 2092 + return Fragment.fromArray(mapped); 2093 + } 2094 + var AddMarkStep = class _AddMarkStep extends Step { 2095 + /** 2096 + Create a mark step. 2097 + */ 2098 + constructor(from, to, mark) { 2099 + super(); 2100 + this.from = from; 2101 + this.to = to; 2102 + this.mark = mark; 2103 + } 2104 + apply(doc) { 2105 + let oldSlice = doc.slice(this.from, this.to), $from = doc.resolve(this.from); 2106 + let parent = $from.node($from.sharedDepth(this.to)); 2107 + let slice = new Slice(mapFragment(oldSlice.content, (node, parent2) => { 2108 + if (!node.isAtom || !parent2.type.allowsMarkType(this.mark.type)) 2109 + return node; 2110 + return node.mark(this.mark.addToSet(node.marks)); 2111 + }, parent), oldSlice.openStart, oldSlice.openEnd); 2112 + return StepResult.fromReplace(doc, this.from, this.to, slice); 2113 + } 2114 + invert() { 2115 + return new RemoveMarkStep(this.from, this.to, this.mark); 2116 + } 2117 + map(mapping) { 2118 + let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1); 2119 + if (from.deleted && to.deleted || from.pos >= to.pos) 2120 + return null; 2121 + return new _AddMarkStep(from.pos, to.pos, this.mark); 2122 + } 2123 + merge(other) { 2124 + if (other instanceof _AddMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from) 2125 + return new _AddMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark); 2126 + return null; 2127 + } 2128 + toJSON() { 2129 + return { 2130 + stepType: "addMark", 2131 + mark: this.mark.toJSON(), 2132 + from: this.from, 2133 + to: this.to 2134 + }; 2135 + } 2136 + /** 2137 + @internal 2138 + */ 2139 + static fromJSON(schema, json) { 2140 + if (typeof json.from != "number" || typeof json.to != "number") 2141 + throw new RangeError("Invalid input for AddMarkStep.fromJSON"); 2142 + return new _AddMarkStep(json.from, json.to, schema.markFromJSON(json.mark)); 2143 + } 2144 + }; 2145 + Step.jsonID("addMark", AddMarkStep); 2146 + var RemoveMarkStep = class _RemoveMarkStep extends Step { 2147 + /** 2148 + Create a mark-removing step. 2149 + */ 2150 + constructor(from, to, mark) { 2151 + super(); 2152 + this.from = from; 2153 + this.to = to; 2154 + this.mark = mark; 2155 + } 2156 + apply(doc) { 2157 + let oldSlice = doc.slice(this.from, this.to); 2158 + let slice = new Slice(mapFragment(oldSlice.content, (node) => { 2159 + return node.mark(this.mark.removeFromSet(node.marks)); 2160 + }, doc), oldSlice.openStart, oldSlice.openEnd); 2161 + return StepResult.fromReplace(doc, this.from, this.to, slice); 2162 + } 2163 + invert() { 2164 + return new AddMarkStep(this.from, this.to, this.mark); 2165 + } 2166 + map(mapping) { 2167 + let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1); 2168 + if (from.deleted && to.deleted || from.pos >= to.pos) 2169 + return null; 2170 + return new _RemoveMarkStep(from.pos, to.pos, this.mark); 2171 + } 2172 + merge(other) { 2173 + if (other instanceof _RemoveMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from) 2174 + return new _RemoveMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark); 2175 + return null; 2176 + } 2177 + toJSON() { 2178 + return { 2179 + stepType: "removeMark", 2180 + mark: this.mark.toJSON(), 2181 + from: this.from, 2182 + to: this.to 2183 + }; 2184 + } 2185 + /** 2186 + @internal 2187 + */ 2188 + static fromJSON(schema, json) { 2189 + if (typeof json.from != "number" || typeof json.to != "number") 2190 + throw new RangeError("Invalid input for RemoveMarkStep.fromJSON"); 2191 + return new _RemoveMarkStep(json.from, json.to, schema.markFromJSON(json.mark)); 2192 + } 2193 + }; 2194 + Step.jsonID("removeMark", RemoveMarkStep); 2195 + var AddNodeMarkStep = class _AddNodeMarkStep extends Step { 2196 + /** 2197 + Create a node mark step. 2198 + */ 2199 + constructor(pos, mark) { 2200 + super(); 2201 + this.pos = pos; 2202 + this.mark = mark; 2203 + } 2204 + apply(doc) { 2205 + let node = doc.nodeAt(this.pos); 2206 + if (!node) 2207 + return StepResult.fail("No node at mark step's position"); 2208 + let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks)); 2209 + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); 2210 + } 2211 + invert(doc) { 2212 + let node = doc.nodeAt(this.pos); 2213 + if (node) { 2214 + let newSet = this.mark.addToSet(node.marks); 2215 + if (newSet.length == node.marks.length) { 2216 + for (let i = 0; i < node.marks.length; i++) 2217 + if (!node.marks[i].isInSet(newSet)) 2218 + return new _AddNodeMarkStep(this.pos, node.marks[i]); 2219 + return new _AddNodeMarkStep(this.pos, this.mark); 2220 + } 2221 + } 2222 + return new RemoveNodeMarkStep(this.pos, this.mark); 2223 + } 2224 + map(mapping) { 2225 + let pos = mapping.mapResult(this.pos, 1); 2226 + return pos.deletedAfter ? null : new _AddNodeMarkStep(pos.pos, this.mark); 2227 + } 2228 + toJSON() { 2229 + return { stepType: "addNodeMark", pos: this.pos, mark: this.mark.toJSON() }; 2230 + } 2231 + /** 2232 + @internal 2233 + */ 2234 + static fromJSON(schema, json) { 2235 + if (typeof json.pos != "number") 2236 + throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON"); 2237 + return new _AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark)); 2238 + } 2239 + }; 2240 + Step.jsonID("addNodeMark", AddNodeMarkStep); 2241 + var RemoveNodeMarkStep = class _RemoveNodeMarkStep extends Step { 2242 + /** 2243 + Create a mark-removing step. 2244 + */ 2245 + constructor(pos, mark) { 2246 + super(); 2247 + this.pos = pos; 2248 + this.mark = mark; 2249 + } 2250 + apply(doc) { 2251 + let node = doc.nodeAt(this.pos); 2252 + if (!node) 2253 + return StepResult.fail("No node at mark step's position"); 2254 + let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks)); 2255 + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); 2256 + } 2257 + invert(doc) { 2258 + let node = doc.nodeAt(this.pos); 2259 + if (!node || !this.mark.isInSet(node.marks)) 2260 + return this; 2261 + return new AddNodeMarkStep(this.pos, this.mark); 2262 + } 2263 + map(mapping) { 2264 + let pos = mapping.mapResult(this.pos, 1); 2265 + return pos.deletedAfter ? null : new _RemoveNodeMarkStep(pos.pos, this.mark); 2266 + } 2267 + toJSON() { 2268 + return { stepType: "removeNodeMark", pos: this.pos, mark: this.mark.toJSON() }; 2269 + } 2270 + /** 2271 + @internal 2272 + */ 2273 + static fromJSON(schema, json) { 2274 + if (typeof json.pos != "number") 2275 + throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON"); 2276 + return new _RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark)); 2277 + } 2278 + }; 2279 + Step.jsonID("removeNodeMark", RemoveNodeMarkStep); 2280 + var ReplaceStep = class _ReplaceStep extends Step { 2281 + /** 2282 + The given `slice` should fit the 'gap' between `from` and 2283 + `to`—the depths must line up, and the surrounding nodes must be 2284 + able to be joined with the open sides of the slice. When 2285 + `structure` is true, the step will fail if the content between 2286 + from and to is not just a sequence of closing and then opening 2287 + tokens (this is to guard against rebased replace steps 2288 + overwriting something they weren't supposed to). 2289 + */ 2290 + constructor(from, to, slice, structure = false) { 2291 + super(); 2292 + this.from = from; 2293 + this.to = to; 2294 + this.slice = slice; 2295 + this.structure = structure; 2296 + } 2297 + apply(doc) { 2298 + if (this.structure && contentBetween(doc, this.from, this.to)) 2299 + return StepResult.fail("Structure replace would overwrite content"); 2300 + return StepResult.fromReplace(doc, this.from, this.to, this.slice); 2301 + } 2302 + getMap() { 2303 + return new StepMap([this.from, this.to - this.from, this.slice.size]); 2304 + } 2305 + invert(doc) { 2306 + return new _ReplaceStep(this.from, this.from + this.slice.size, doc.slice(this.from, this.to)); 2307 + } 2308 + map(mapping) { 2309 + let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1); 2310 + if (from.deletedAcross && to.deletedAcross) 2311 + return null; 2312 + return new _ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice, this.structure); 2313 + } 2314 + merge(other) { 2315 + if (!(other instanceof _ReplaceStep) || other.structure || this.structure) 2316 + return null; 2317 + if (this.from + this.slice.size == other.from && !this.slice.openEnd && !other.slice.openStart) { 2318 + let slice = this.slice.size + other.slice.size == 0 ? Slice.empty : new Slice(this.slice.content.append(other.slice.content), this.slice.openStart, other.slice.openEnd); 2319 + return new _ReplaceStep(this.from, this.to + (other.to - other.from), slice, this.structure); 2320 + } else if (other.to == this.from && !this.slice.openStart && !other.slice.openEnd) { 2321 + let slice = this.slice.size + other.slice.size == 0 ? Slice.empty : new Slice(other.slice.content.append(this.slice.content), other.slice.openStart, this.slice.openEnd); 2322 + return new _ReplaceStep(other.from, this.to, slice, this.structure); 2323 + } else { 2324 + return null; 2325 + } 2326 + } 2327 + toJSON() { 2328 + let json = { stepType: "replace", from: this.from, to: this.to }; 2329 + if (this.slice.size) 2330 + json.slice = this.slice.toJSON(); 2331 + if (this.structure) 2332 + json.structure = true; 2333 + return json; 2334 + } 2335 + /** 2336 + @internal 2337 + */ 2338 + static fromJSON(schema, json) { 2339 + if (typeof json.from != "number" || typeof json.to != "number") 2340 + throw new RangeError("Invalid input for ReplaceStep.fromJSON"); 2341 + return new _ReplaceStep(json.from, json.to, Slice.fromJSON(schema, json.slice), !!json.structure); 2342 + } 2343 + }; 2344 + Step.jsonID("replace", ReplaceStep); 2345 + var ReplaceAroundStep = class _ReplaceAroundStep extends Step { 2346 + /** 2347 + Create a replace-around step with the given range and gap. 2348 + `insert` should be the point in the slice into which the content 2349 + of the gap should be moved. `structure` has the same meaning as 2350 + it has in the [`ReplaceStep`](https://prosemirror.net/docs/ref/#transform.ReplaceStep) class. 2351 + */ 2352 + constructor(from, to, gapFrom, gapTo, slice, insert, structure = false) { 2353 + super(); 2354 + this.from = from; 2355 + this.to = to; 2356 + this.gapFrom = gapFrom; 2357 + this.gapTo = gapTo; 2358 + this.slice = slice; 2359 + this.insert = insert; 2360 + this.structure = structure; 2361 + } 2362 + apply(doc) { 2363 + if (this.structure && (contentBetween(doc, this.from, this.gapFrom) || contentBetween(doc, this.gapTo, this.to))) 2364 + return StepResult.fail("Structure gap-replace would overwrite content"); 2365 + let gap = doc.slice(this.gapFrom, this.gapTo); 2366 + if (gap.openStart || gap.openEnd) 2367 + return StepResult.fail("Gap is not a flat range"); 2368 + let inserted = this.slice.insertAt(this.insert, gap.content); 2369 + if (!inserted) 2370 + return StepResult.fail("Content does not fit in gap"); 2371 + return StepResult.fromReplace(doc, this.from, this.to, inserted); 2372 + } 2373 + getMap() { 2374 + return new StepMap([ 2375 + this.from, 2376 + this.gapFrom - this.from, 2377 + this.insert, 2378 + this.gapTo, 2379 + this.to - this.gapTo, 2380 + this.slice.size - this.insert 2381 + ]); 2382 + } 2383 + invert(doc) { 2384 + let gap = this.gapTo - this.gapFrom; 2385 + return new _ReplaceAroundStep(this.from, this.from + this.slice.size + gap, this.from + this.insert, this.from + this.insert + gap, doc.slice(this.from, this.to).removeBetween(this.gapFrom - this.from, this.gapTo - this.from), this.gapFrom - this.from, this.structure); 2386 + } 2387 + map(mapping) { 2388 + let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1); 2389 + let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1); 2390 + let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1); 2391 + if (from.deletedAcross && to.deletedAcross || gapFrom < from.pos || gapTo > to.pos) 2392 + return null; 2393 + return new _ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure); 2394 + } 2395 + toJSON() { 2396 + let json = { 2397 + stepType: "replaceAround", 2398 + from: this.from, 2399 + to: this.to, 2400 + gapFrom: this.gapFrom, 2401 + gapTo: this.gapTo, 2402 + insert: this.insert 2403 + }; 2404 + if (this.slice.size) 2405 + json.slice = this.slice.toJSON(); 2406 + if (this.structure) 2407 + json.structure = true; 2408 + return json; 2409 + } 2410 + /** 2411 + @internal 2412 + */ 2413 + static fromJSON(schema, json) { 2414 + if (typeof json.from != "number" || typeof json.to != "number" || typeof json.gapFrom != "number" || typeof json.gapTo != "number" || typeof json.insert != "number") 2415 + throw new RangeError("Invalid input for ReplaceAroundStep.fromJSON"); 2416 + return new _ReplaceAroundStep(json.from, json.to, json.gapFrom, json.gapTo, Slice.fromJSON(schema, json.slice), json.insert, !!json.structure); 2417 + } 2418 + }; 2419 + Step.jsonID("replaceAround", ReplaceAroundStep); 2420 + function contentBetween(doc, from, to) { 2421 + let $from = doc.resolve(from), dist = to - from, depth = $from.depth; 2422 + while (dist > 0 && depth > 0 && $from.indexAfter(depth) == $from.node(depth).childCount) { 2423 + depth--; 2424 + dist--; 2425 + } 2426 + if (dist > 0) { 2427 + let next = $from.node(depth).maybeChild($from.indexAfter(depth)); 2428 + while (dist > 0) { 2429 + if (!next || next.isLeaf) 2430 + return true; 2431 + next = next.firstChild; 2432 + dist--; 2433 + } 2434 + } 2435 + return false; 2436 + } 2437 + var AttrStep = class _AttrStep extends Step { 2438 + /** 2439 + Construct an attribute step. 2440 + */ 2441 + constructor(pos, attr, value) { 2442 + super(); 2443 + this.pos = pos; 2444 + this.attr = attr; 2445 + this.value = value; 2446 + } 2447 + apply(doc) { 2448 + let node = doc.nodeAt(this.pos); 2449 + if (!node) 2450 + return StepResult.fail("No node at attribute step's position"); 2451 + let attrs = /* @__PURE__ */ Object.create(null); 2452 + for (let name in node.attrs) 2453 + attrs[name] = node.attrs[name]; 2454 + attrs[this.attr] = this.value; 2455 + let updated = node.type.create(attrs, null, node.marks); 2456 + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); 2457 + } 2458 + getMap() { 2459 + return StepMap.empty; 2460 + } 2461 + invert(doc) { 2462 + return new _AttrStep(this.pos, this.attr, doc.nodeAt(this.pos).attrs[this.attr]); 2463 + } 2464 + map(mapping) { 2465 + let pos = mapping.mapResult(this.pos, 1); 2466 + return pos.deletedAfter ? null : new _AttrStep(pos.pos, this.attr, this.value); 2467 + } 2468 + toJSON() { 2469 + return { stepType: "attr", pos: this.pos, attr: this.attr, value: this.value }; 2470 + } 2471 + static fromJSON(schema, json) { 2472 + if (typeof json.pos != "number" || typeof json.attr != "string") 2473 + throw new RangeError("Invalid input for AttrStep.fromJSON"); 2474 + return new _AttrStep(json.pos, json.attr, json.value); 2475 + } 2476 + }; 2477 + Step.jsonID("attr", AttrStep); 2478 + var DocAttrStep = class _DocAttrStep extends Step { 2479 + /** 2480 + Construct an attribute step. 2481 + */ 2482 + constructor(attr, value) { 2483 + super(); 2484 + this.attr = attr; 2485 + this.value = value; 2486 + } 2487 + apply(doc) { 2488 + let attrs = /* @__PURE__ */ Object.create(null); 2489 + for (let name in doc.attrs) 2490 + attrs[name] = doc.attrs[name]; 2491 + attrs[this.attr] = this.value; 2492 + let updated = doc.type.create(attrs, doc.content, doc.marks); 2493 + return StepResult.ok(updated); 2494 + } 2495 + getMap() { 2496 + return StepMap.empty; 2497 + } 2498 + invert(doc) { 2499 + return new _DocAttrStep(this.attr, doc.attrs[this.attr]); 2500 + } 2501 + map(mapping) { 2502 + return this; 2503 + } 2504 + toJSON() { 2505 + return { stepType: "docAttr", attr: this.attr, value: this.value }; 2506 + } 2507 + static fromJSON(schema, json) { 2508 + if (typeof json.attr != "string") 2509 + throw new RangeError("Invalid input for DocAttrStep.fromJSON"); 2510 + return new _DocAttrStep(json.attr, json.value); 2511 + } 2512 + }; 2513 + Step.jsonID("docAttr", DocAttrStep); 2514 + var TransformError = class extends Error { 2515 + }; 2516 + TransformError = function TransformError2(message) { 2517 + let err = Error.call(this, message); 2518 + err.__proto__ = TransformError2.prototype; 2519 + return err; 2520 + }; 2521 + TransformError.prototype = Object.create(Error.prototype); 2522 + TransformError.prototype.constructor = TransformError; 2523 + TransformError.prototype.name = "TransformError"; 2524 + 2525 + // node_modules/prosemirror-state/dist/index.js 2526 + var classesById = /* @__PURE__ */ Object.create(null); 2527 + var Selection = class { 2528 + /** 2529 + Initialize a selection with the head and anchor and ranges. If no 2530 + ranges are given, constructs a single range across `$anchor` and 2531 + `$head`. 2532 + */ 2533 + constructor($anchor, $head, ranges) { 2534 + this.$anchor = $anchor; 2535 + this.$head = $head; 2536 + this.ranges = ranges || [new SelectionRange($anchor.min($head), $anchor.max($head))]; 2537 + } 2538 + /** 2539 + The selection's anchor, as an unresolved position. 2540 + */ 2541 + get anchor() { 2542 + return this.$anchor.pos; 2543 + } 2544 + /** 2545 + The selection's head. 2546 + */ 2547 + get head() { 2548 + return this.$head.pos; 2549 + } 2550 + /** 2551 + The lower bound of the selection's main range. 2552 + */ 2553 + get from() { 2554 + return this.$from.pos; 2555 + } 2556 + /** 2557 + The upper bound of the selection's main range. 2558 + */ 2559 + get to() { 2560 + return this.$to.pos; 2561 + } 2562 + /** 2563 + The resolved lower bound of the selection's main range. 2564 + */ 2565 + get $from() { 2566 + return this.ranges[0].$from; 2567 + } 2568 + /** 2569 + The resolved upper bound of the selection's main range. 2570 + */ 2571 + get $to() { 2572 + return this.ranges[0].$to; 2573 + } 2574 + /** 2575 + Indicates whether the selection contains any content. 2576 + */ 2577 + get empty() { 2578 + let ranges = this.ranges; 2579 + for (let i = 0; i < ranges.length; i++) 2580 + if (ranges[i].$from.pos != ranges[i].$to.pos) 2581 + return false; 2582 + return true; 2583 + } 2584 + /** 2585 + Get the content of this selection as a slice. 2586 + */ 2587 + content() { 2588 + return this.$from.doc.slice(this.from, this.to, true); 2589 + } 2590 + /** 2591 + Replace the selection with a slice or, if no slice is given, 2592 + delete the selection. Will append to the given transaction. 2593 + */ 2594 + replace(tr, content = Slice.empty) { 2595 + let lastNode = content.content.lastChild, lastParent = null; 2596 + for (let i = 0; i < content.openEnd; i++) { 2597 + lastParent = lastNode; 2598 + lastNode = lastNode.lastChild; 2599 + } 2600 + let mapFrom = tr.steps.length, ranges = this.ranges; 2601 + for (let i = 0; i < ranges.length; i++) { 2602 + let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom); 2603 + tr.replaceRange(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content); 2604 + if (i == 0) 2605 + selectionToInsertionEnd(tr, mapFrom, (lastNode ? lastNode.isInline : lastParent && lastParent.isTextblock) ? -1 : 1); 2606 + } 2607 + } 2608 + /** 2609 + Replace the selection with the given node, appending the changes 2610 + to the given transaction. 2611 + */ 2612 + replaceWith(tr, node) { 2613 + let mapFrom = tr.steps.length, ranges = this.ranges; 2614 + for (let i = 0; i < ranges.length; i++) { 2615 + let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom); 2616 + let from = mapping.map($from.pos), to = mapping.map($to.pos); 2617 + if (i) { 2618 + tr.deleteRange(from, to); 2619 + } else { 2620 + tr.replaceRangeWith(from, to, node); 2621 + selectionToInsertionEnd(tr, mapFrom, node.isInline ? -1 : 1); 2622 + } 2623 + } 2624 + } 2625 + /** 2626 + Find a valid cursor or leaf node selection starting at the given 2627 + position and searching back if `dir` is negative, and forward if 2628 + positive. When `textOnly` is true, only consider cursor 2629 + selections. Will return null when no valid selection position is 2630 + found. 2631 + */ 2632 + static findFrom($pos, dir, textOnly = false) { 2633 + let inner = $pos.parent.inlineContent ? new TextSelection($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly); 2634 + if (inner) 2635 + return inner; 2636 + for (let depth = $pos.depth - 1; depth >= 0; depth--) { 2637 + let found2 = dir < 0 ? findSelectionIn($pos.node(0), $pos.node(depth), $pos.before(depth + 1), $pos.index(depth), dir, textOnly) : findSelectionIn($pos.node(0), $pos.node(depth), $pos.after(depth + 1), $pos.index(depth) + 1, dir, textOnly); 2638 + if (found2) 2639 + return found2; 2640 + } 2641 + return null; 2642 + } 2643 + /** 2644 + Find a valid cursor or leaf node selection near the given 2645 + position. Searches forward first by default, but if `bias` is 2646 + negative, it will search backwards first. 2647 + */ 2648 + static near($pos, bias = 1) { 2649 + return this.findFrom($pos, bias) || this.findFrom($pos, -bias) || new AllSelection($pos.node(0)); 2650 + } 2651 + /** 2652 + Find the cursor or leaf node selection closest to the start of 2653 + the given document. Will return an 2654 + [`AllSelection`](https://prosemirror.net/docs/ref/#state.AllSelection) if no valid position 2655 + exists. 2656 + */ 2657 + static atStart(doc) { 2658 + return findSelectionIn(doc, doc, 0, 0, 1) || new AllSelection(doc); 2659 + } 2660 + /** 2661 + Find the cursor or leaf node selection closest to the end of the 2662 + given document. 2663 + */ 2664 + static atEnd(doc) { 2665 + return findSelectionIn(doc, doc, doc.content.size, doc.childCount, -1) || new AllSelection(doc); 2666 + } 2667 + /** 2668 + Deserialize the JSON representation of a selection. Must be 2669 + implemented for custom classes (as a static class method). 2670 + */ 2671 + static fromJSON(doc, json) { 2672 + if (!json || !json.type) 2673 + throw new RangeError("Invalid input for Selection.fromJSON"); 2674 + let cls = classesById[json.type]; 2675 + if (!cls) 2676 + throw new RangeError(`No selection type ${json.type} defined`); 2677 + return cls.fromJSON(doc, json); 2678 + } 2679 + /** 2680 + To be able to deserialize selections from JSON, custom selection 2681 + classes must register themselves with an ID string, so that they 2682 + can be disambiguated. Try to pick something that's unlikely to 2683 + clash with classes from other modules. 2684 + */ 2685 + static jsonID(id, selectionClass) { 2686 + if (id in classesById) 2687 + throw new RangeError("Duplicate use of selection JSON ID " + id); 2688 + classesById[id] = selectionClass; 2689 + selectionClass.prototype.jsonID = id; 2690 + return selectionClass; 2691 + } 2692 + /** 2693 + Get a [bookmark](https://prosemirror.net/docs/ref/#state.SelectionBookmark) for this selection, 2694 + which is a value that can be mapped without having access to a 2695 + current document, and later resolved to a real selection for a 2696 + given document again. (This is used mostly by the history to 2697 + track and restore old selections.) The default implementation of 2698 + this method just converts the selection to a text selection and 2699 + returns the bookmark for that. 2700 + */ 2701 + getBookmark() { 2702 + return TextSelection.between(this.$anchor, this.$head).getBookmark(); 2703 + } 2704 + }; 2705 + Selection.prototype.visible = true; 2706 + var SelectionRange = class { 2707 + /** 2708 + Create a range. 2709 + */ 2710 + constructor($from, $to) { 2711 + this.$from = $from; 2712 + this.$to = $to; 2713 + } 2714 + }; 2715 + var warnedAboutTextSelection = false; 2716 + function checkTextSelection($pos) { 2717 + if (!warnedAboutTextSelection && !$pos.parent.inlineContent) { 2718 + warnedAboutTextSelection = true; 2719 + console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")"); 2720 + } 2721 + } 2722 + var TextSelection = class _TextSelection extends Selection { 2723 + /** 2724 + Construct a text selection between the given points. 2725 + */ 2726 + constructor($anchor, $head = $anchor) { 2727 + checkTextSelection($anchor); 2728 + checkTextSelection($head); 2729 + super($anchor, $head); 2730 + } 2731 + /** 2732 + Returns a resolved position if this is a cursor selection (an 2733 + empty text selection), and null otherwise. 2734 + */ 2735 + get $cursor() { 2736 + return this.$anchor.pos == this.$head.pos ? this.$head : null; 2737 + } 2738 + map(doc, mapping) { 2739 + let $head = doc.resolve(mapping.map(this.head)); 2740 + if (!$head.parent.inlineContent) 2741 + return Selection.near($head); 2742 + let $anchor = doc.resolve(mapping.map(this.anchor)); 2743 + return new _TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head); 2744 + } 2745 + replace(tr, content = Slice.empty) { 2746 + super.replace(tr, content); 2747 + if (content == Slice.empty) { 2748 + let marks = this.$from.marksAcross(this.$to); 2749 + if (marks) 2750 + tr.ensureMarks(marks); 2751 + } 2752 + } 2753 + eq(other) { 2754 + return other instanceof _TextSelection && other.anchor == this.anchor && other.head == this.head; 2755 + } 2756 + getBookmark() { 2757 + return new TextBookmark(this.anchor, this.head); 2758 + } 2759 + toJSON() { 2760 + return { type: "text", anchor: this.anchor, head: this.head }; 2761 + } 2762 + /** 2763 + @internal 2764 + */ 2765 + static fromJSON(doc, json) { 2766 + if (typeof json.anchor != "number" || typeof json.head != "number") 2767 + throw new RangeError("Invalid input for TextSelection.fromJSON"); 2768 + return new _TextSelection(doc.resolve(json.anchor), doc.resolve(json.head)); 2769 + } 2770 + /** 2771 + Create a text selection from non-resolved positions. 2772 + */ 2773 + static create(doc, anchor, head = anchor) { 2774 + let $anchor = doc.resolve(anchor); 2775 + return new this($anchor, head == anchor ? $anchor : doc.resolve(head)); 2776 + } 2777 + /** 2778 + Return a text selection that spans the given positions or, if 2779 + they aren't text positions, find a text selection near them. 2780 + `bias` determines whether the method searches forward (default) 2781 + or backwards (negative number) first. Will fall back to calling 2782 + [`Selection.near`](https://prosemirror.net/docs/ref/#state.Selection^near) when the document 2783 + doesn't contain a valid text position. 2784 + */ 2785 + static between($anchor, $head, bias) { 2786 + let dPos = $anchor.pos - $head.pos; 2787 + if (!bias || dPos) 2788 + bias = dPos >= 0 ? 1 : -1; 2789 + if (!$head.parent.inlineContent) { 2790 + let found2 = Selection.findFrom($head, bias, true) || Selection.findFrom($head, -bias, true); 2791 + if (found2) 2792 + $head = found2.$head; 2793 + else 2794 + return Selection.near($head, bias); 2795 + } 2796 + if (!$anchor.parent.inlineContent) { 2797 + if (dPos == 0) { 2798 + $anchor = $head; 2799 + } else { 2800 + $anchor = (Selection.findFrom($anchor, -bias, true) || Selection.findFrom($anchor, bias, true)).$anchor; 2801 + if ($anchor.pos < $head.pos != dPos < 0) 2802 + $anchor = $head; 2803 + } 2804 + } 2805 + return new _TextSelection($anchor, $head); 2806 + } 2807 + }; 2808 + Selection.jsonID("text", TextSelection); 2809 + var TextBookmark = class _TextBookmark { 2810 + constructor(anchor, head) { 2811 + this.anchor = anchor; 2812 + this.head = head; 2813 + } 2814 + map(mapping) { 2815 + return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head)); 2816 + } 2817 + resolve(doc) { 2818 + return TextSelection.between(doc.resolve(this.anchor), doc.resolve(this.head)); 2819 + } 2820 + }; 2821 + var NodeSelection = class _NodeSelection extends Selection { 2822 + /** 2823 + Create a node selection. Does not verify the validity of its 2824 + argument. 2825 + */ 2826 + constructor($pos) { 2827 + let node = $pos.nodeAfter; 2828 + let $end = $pos.node(0).resolve($pos.pos + node.nodeSize); 2829 + super($pos, $end); 2830 + this.node = node; 2831 + } 2832 + map(doc, mapping) { 2833 + let { deleted, pos } = mapping.mapResult(this.anchor); 2834 + let $pos = doc.resolve(pos); 2835 + if (deleted) 2836 + return Selection.near($pos); 2837 + return new _NodeSelection($pos); 2838 + } 2839 + content() { 2840 + return new Slice(Fragment.from(this.node), 0, 0); 2841 + } 2842 + eq(other) { 2843 + return other instanceof _NodeSelection && other.anchor == this.anchor; 2844 + } 2845 + toJSON() { 2846 + return { type: "node", anchor: this.anchor }; 2847 + } 2848 + getBookmark() { 2849 + return new NodeBookmark(this.anchor); 2850 + } 2851 + /** 2852 + @internal 2853 + */ 2854 + static fromJSON(doc, json) { 2855 + if (typeof json.anchor != "number") 2856 + throw new RangeError("Invalid input for NodeSelection.fromJSON"); 2857 + return new _NodeSelection(doc.resolve(json.anchor)); 2858 + } 2859 + /** 2860 + Create a node selection from non-resolved positions. 2861 + */ 2862 + static create(doc, from) { 2863 + return new _NodeSelection(doc.resolve(from)); 2864 + } 2865 + /** 2866 + Determines whether the given node may be selected as a node 2867 + selection. 2868 + */ 2869 + static isSelectable(node) { 2870 + return !node.isText && node.type.spec.selectable !== false; 2871 + } 2872 + }; 2873 + NodeSelection.prototype.visible = false; 2874 + Selection.jsonID("node", NodeSelection); 2875 + var NodeBookmark = class _NodeBookmark { 2876 + constructor(anchor) { 2877 + this.anchor = anchor; 2878 + } 2879 + map(mapping) { 2880 + let { deleted, pos } = mapping.mapResult(this.anchor); 2881 + return deleted ? new TextBookmark(pos, pos) : new _NodeBookmark(pos); 2882 + } 2883 + resolve(doc) { 2884 + let $pos = doc.resolve(this.anchor), node = $pos.nodeAfter; 2885 + if (node && NodeSelection.isSelectable(node)) 2886 + return new NodeSelection($pos); 2887 + return Selection.near($pos); 2888 + } 2889 + }; 2890 + var AllSelection = class _AllSelection extends Selection { 2891 + /** 2892 + Create an all-selection over the given document. 2893 + */ 2894 + constructor(doc) { 2895 + super(doc.resolve(0), doc.resolve(doc.content.size)); 2896 + } 2897 + replace(tr, content = Slice.empty) { 2898 + if (content == Slice.empty) { 2899 + tr.delete(0, tr.doc.content.size); 2900 + let sel = Selection.atStart(tr.doc); 2901 + if (!sel.eq(tr.selection)) 2902 + tr.setSelection(sel); 2903 + } else { 2904 + super.replace(tr, content); 2905 + } 2906 + } 2907 + toJSON() { 2908 + return { type: "all" }; 2909 + } 2910 + /** 2911 + @internal 2912 + */ 2913 + static fromJSON(doc) { 2914 + return new _AllSelection(doc); 2915 + } 2916 + map(doc) { 2917 + return new _AllSelection(doc); 2918 + } 2919 + eq(other) { 2920 + return other instanceof _AllSelection; 2921 + } 2922 + getBookmark() { 2923 + return AllBookmark; 2924 + } 2925 + }; 2926 + Selection.jsonID("all", AllSelection); 2927 + var AllBookmark = { 2928 + map() { 2929 + return this; 2930 + }, 2931 + resolve(doc) { 2932 + return new AllSelection(doc); 2933 + } 2934 + }; 2935 + function findSelectionIn(doc, node, pos, index, dir, text = false) { 2936 + if (node.inlineContent) 2937 + return TextSelection.create(doc, pos); 2938 + for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) { 2939 + let child = node.child(i); 2940 + if (!child.isAtom) { 2941 + let inner = findSelectionIn(doc, child, pos + dir, dir < 0 ? child.childCount : 0, dir, text); 2942 + if (inner) 2943 + return inner; 2944 + } else if (!text && NodeSelection.isSelectable(child)) { 2945 + return NodeSelection.create(doc, pos - (dir < 0 ? child.nodeSize : 0)); 2946 + } 2947 + pos += child.nodeSize * dir; 2948 + } 2949 + return null; 2950 + } 2951 + function selectionToInsertionEnd(tr, startLen, bias) { 2952 + let last = tr.steps.length - 1; 2953 + if (last < startLen) 2954 + return; 2955 + let step = tr.steps[last]; 2956 + if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) 2957 + return; 2958 + let map = tr.mapping.maps[last], end; 2959 + map.forEach((_from, _to, _newFrom, newTo) => { 2960 + if (end == null) 2961 + end = newTo; 2962 + }); 2963 + tr.setSelection(Selection.near(tr.doc.resolve(end), bias)); 2964 + } 2965 + function bind(f, self) { 2966 + return !self || !f ? f : f.bind(self); 2967 + } 2968 + var FieldDesc = class { 2969 + constructor(name, desc, self) { 2970 + this.name = name; 2971 + this.init = bind(desc.init, self); 2972 + this.apply = bind(desc.apply, self); 2973 + } 2974 + }; 2975 + var baseFields = [ 2976 + new FieldDesc("doc", { 2977 + init(config) { 2978 + return config.doc || config.schema.topNodeType.createAndFill(); 2979 + }, 2980 + apply(tr) { 2981 + return tr.doc; 2982 + } 2983 + }), 2984 + new FieldDesc("selection", { 2985 + init(config, instance) { 2986 + return config.selection || Selection.atStart(instance.doc); 2987 + }, 2988 + apply(tr) { 2989 + return tr.selection; 2990 + } 2991 + }), 2992 + new FieldDesc("storedMarks", { 2993 + init(config) { 2994 + return config.storedMarks || null; 2995 + }, 2996 + apply(tr, _marks, _old, state) { 2997 + return state.selection.$cursor ? tr.storedMarks : null; 2998 + } 2999 + }), 3000 + new FieldDesc("scrollToSelection", { 3001 + init() { 3002 + return 0; 3003 + }, 3004 + apply(tr, prev) { 3005 + return tr.scrolledIntoView ? prev + 1 : prev; 3006 + } 3007 + }) 3008 + ]; 3009 + function bindProps(obj, self, target) { 3010 + for (let prop in obj) { 3011 + let val = obj[prop]; 3012 + if (val instanceof Function) 3013 + val = val.bind(self); 3014 + else if (prop == "handleDOMEvents") 3015 + val = bindProps(val, self, {}); 3016 + target[prop] = val; 3017 + } 3018 + return target; 3019 + } 3020 + var Plugin = class { 3021 + /** 3022 + Create a plugin. 3023 + */ 3024 + constructor(spec) { 3025 + this.spec = spec; 3026 + this.props = {}; 3027 + if (spec.props) 3028 + bindProps(spec.props, this, this.props); 3029 + this.key = spec.key ? spec.key.key : createKey("plugin"); 3030 + } 3031 + /** 3032 + Extract the plugin's state field from an editor state. 3033 + */ 3034 + getState(state) { 3035 + return state[this.key]; 3036 + } 3037 + }; 3038 + var keys = /* @__PURE__ */ Object.create(null); 3039 + function createKey(name) { 3040 + if (name in keys) 3041 + return name + "$" + ++keys[name]; 3042 + keys[name] = 0; 3043 + return name + "$"; 3044 + } 3045 + var PluginKey = class { 3046 + /** 3047 + Create a plugin key. 3048 + */ 3049 + constructor(name = "key") { 3050 + this.key = createKey(name); 3051 + } 3052 + /** 3053 + Get the active plugin with this key, if any, from an editor 3054 + state. 3055 + */ 3056 + get(state) { 3057 + return state.config.pluginsByKey[this.key]; 3058 + } 3059 + /** 3060 + Get the plugin's state from an editor state. 3061 + */ 3062 + getState(state) { 3063 + return state[this.key]; 3064 + } 3065 + }; 3066 + 3067 + // node_modules/prosemirror-collab/dist/index.js 3068 + var Rebaseable = class { 3069 + constructor(step, inverted, origin) { 3070 + this.step = step; 3071 + this.inverted = inverted; 3072 + this.origin = origin; 3073 + } 3074 + }; 3075 + function rebaseSteps(steps, over, transform) { 3076 + for (let i = steps.length - 1; i >= 0; i--) 3077 + transform.step(steps[i].inverted); 3078 + for (let i = 0; i < over.length; i++) 3079 + transform.step(over[i]); 3080 + let result = []; 3081 + for (let i = 0, mapFrom = steps.length; i < steps.length; i++) { 3082 + let mapped = steps[i].step.map(transform.mapping.slice(mapFrom)); 3083 + mapFrom--; 3084 + if (mapped && !transform.maybeStep(mapped).failed) { 3085 + transform.mapping.setMirror(mapFrom, transform.steps.length - 1); 3086 + result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[i].origin)); 3087 + } 3088 + } 3089 + return result; 3090 + } 3091 + var CollabState = class { 3092 + constructor(version, unconfirmed) { 3093 + this.version = version; 3094 + this.unconfirmed = unconfirmed; 3095 + } 3096 + }; 3097 + function unconfirmedFrom(transform) { 3098 + let result = []; 3099 + for (let i = 0; i < transform.steps.length; i++) 3100 + result.push(new Rebaseable(transform.steps[i], transform.steps[i].invert(transform.docs[i]), transform)); 3101 + return result; 3102 + } 3103 + var collabKey = new PluginKey("collab"); 3104 + function collab(config = {}) { 3105 + let conf = { 3106 + version: config.version || 0, 3107 + clientID: config.clientID == null ? Math.floor(Math.random() * 4294967295) : config.clientID 3108 + }; 3109 + return new Plugin({ 3110 + key: collabKey, 3111 + state: { 3112 + init: () => new CollabState(conf.version, []), 3113 + apply(tr, collab2) { 3114 + let newState = tr.getMeta(collabKey); 3115 + if (newState) 3116 + return newState; 3117 + if (tr.docChanged) 3118 + return new CollabState(collab2.version, collab2.unconfirmed.concat(unconfirmedFrom(tr))); 3119 + return collab2; 3120 + } 3121 + }, 3122 + config: conf, 3123 + // This is used to notify the history plugin to not merge steps, 3124 + // so that the history can be rebased. 3125 + historyPreserveItems: true 3126 + }); 3127 + } 3128 + function receiveTransaction(state, steps, clientIDs, options = {}) { 3129 + let collabState = collabKey.getState(state); 3130 + let version = collabState.version + steps.length; 3131 + let ourID = collabKey.get(state).spec.config.clientID; 3132 + let ours = 0; 3133 + while (ours < clientIDs.length && clientIDs[ours] == ourID) 3134 + ++ours; 3135 + let unconfirmed = collabState.unconfirmed.slice(ours); 3136 + steps = ours ? steps.slice(ours) : steps; 3137 + if (!steps.length) 3138 + return state.tr.setMeta(collabKey, new CollabState(version, unconfirmed)); 3139 + let nUnconfirmed = unconfirmed.length; 3140 + let tr = state.tr; 3141 + if (nUnconfirmed) { 3142 + unconfirmed = rebaseSteps(unconfirmed, steps, tr); 3143 + } else { 3144 + for (let i = 0; i < steps.length; i++) 3145 + tr.step(steps[i]); 3146 + unconfirmed = []; 3147 + } 3148 + let newCollabState = new CollabState(version, unconfirmed); 3149 + if (options && options.mapSelectionBackward && state.selection instanceof TextSelection) { 3150 + tr.setSelection(TextSelection.between(tr.doc.resolve(tr.mapping.map(state.selection.anchor, -1)), tr.doc.resolve(tr.mapping.map(state.selection.head, -1)), -1)); 3151 + tr.updated &= ~1; 3152 + } 3153 + return tr.setMeta("rebased", nUnconfirmed).setMeta("addToHistory", false).setMeta(collabKey, newCollabState); 3154 + } 3155 + function sendableSteps(state) { 3156 + let collabState = collabKey.getState(state); 3157 + if (collabState.unconfirmed.length == 0) 3158 + return null; 3159 + return { 3160 + version: collabState.version, 3161 + steps: collabState.unconfirmed.map((s) => s.step), 3162 + clientID: collabKey.get(state).spec.config.clientID, 3163 + get origins() { 3164 + return this._origins || (this._origins = collabState.unconfirmed.map((s) => s.origin)); 3165 + } 3166 + }; 3167 + } 3168 + function getVersion(state) { 3169 + return collabKey.getState(state).version; 3170 + } 3171 + export { 3172 + collab, 3173 + getVersion, 3174 + rebaseSteps, 3175 + receiveTransaction, 3176 + sendableSteps 3177 + };