Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol diffdown.com
at main 3177 lines 100 kB view raw
1// node_modules/prosemirror-model/dist/index.js 2function 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} 26function 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} 56var 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}; 348Fragment.empty = new Fragment([], 0); 349var found = { index: 0, offset: 0 }; 350function retIndex(index, offset) { 351 found.index = index; 352 found.offset = offset; 353 return found; 354} 355function 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} 379var 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}; 499Mark.none = []; 500var ReplaceError = class extends Error { 501}; 502var 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}; 588Slice.empty = new Slice(Fragment.empty, 0, 0); 589function 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} 601function 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} 611function 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} 618function 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} 633function checkJoin(main, sub) { 634 if (!sub.type.compatibleContent(main.type)) 635 throw new ReplaceError("Cannot join " + sub.type.name + " onto " + main.type.name); 636} 637function joinable($before, $after, depth) { 638 let node = $before.node(depth); 639 checkJoin(node, $after.node(depth)); 640 return node; 641} 642function 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} 649function 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} 666function close(node, content) { 667 node.type.checkContent(content); 668 return node.copy(content); 669} 670function 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} 688function 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} 698function 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} 708var 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}; 982var ResolveCache = class { 983 constructor() { 984 this.elts = []; 985 this.i = 0; 986 } 987}; 988var resolveCacheSize = 12; 989var resolveCache = /* @__PURE__ */ new WeakMap(); 990var 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}; 1032var emptyAttrs = /* @__PURE__ */ Object.create(null); 1033var 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}; 1434Node.prototype.text = void 0; 1435function wrapMarks(marks, str) { 1436 for (let i = marks.length - 1; i >= 0; i--) 1437 str = marks[i].type.name + "(" + str + ")"; 1438 return str; 1439} 1440var 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}; 1611ContentMatch.empty = new ContentMatch(true); 1612var 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}; 1634function 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} 1641function 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} 1648function 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} 1664function 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} 1671function 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} 1683function 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} 1697function 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} 1717function 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} 1779function cmp(a, b) { 1780 return b - a; 1781} 1782function 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} 1798function 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} 1827function 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 1844var lower16 = 65535; 1845var factor16 = Math.pow(2, 16); 1846function makeRecover(index, offset) { 1847 return index + offset * factor16; 1848} 1849function recoverIndex(value) { 1850 return value & lower16; 1851} 1852function recoverOffset(value) { 1853 return (value - (value & lower16)) / factor16; 1854} 1855var DEL_BEFORE = 1; 1856var DEL_AFTER = 2; 1857var DEL_ACROSS = 4; 1858var DEL_SIDE = 8; 1859var 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}; 1897var 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}; 2002StepMap.empty = new StepMap([]); 2003var stepsByID = /* @__PURE__ */ Object.create(null); 2004var 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}; 2047var 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}; 2082function 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} 2094var 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}; 2145Step.jsonID("addMark", AddMarkStep); 2146var 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}; 2194Step.jsonID("removeMark", RemoveMarkStep); 2195var 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}; 2240Step.jsonID("addNodeMark", AddNodeMarkStep); 2241var 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}; 2279Step.jsonID("removeNodeMark", RemoveNodeMarkStep); 2280var 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}; 2344Step.jsonID("replace", ReplaceStep); 2345var 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}; 2419Step.jsonID("replaceAround", ReplaceAroundStep); 2420function 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} 2437var 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}; 2477Step.jsonID("attr", AttrStep); 2478var 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}; 2513Step.jsonID("docAttr", DocAttrStep); 2514var TransformError = class extends Error { 2515}; 2516TransformError = function TransformError2(message) { 2517 let err = Error.call(this, message); 2518 err.__proto__ = TransformError2.prototype; 2519 return err; 2520}; 2521TransformError.prototype = Object.create(Error.prototype); 2522TransformError.prototype.constructor = TransformError; 2523TransformError.prototype.name = "TransformError"; 2524 2525// node_modules/prosemirror-state/dist/index.js 2526var classesById = /* @__PURE__ */ Object.create(null); 2527var 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}; 2705Selection.prototype.visible = true; 2706var SelectionRange = class { 2707 /** 2708 Create a range. 2709 */ 2710 constructor($from, $to) { 2711 this.$from = $from; 2712 this.$to = $to; 2713 } 2714}; 2715var warnedAboutTextSelection = false; 2716function 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} 2722var 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}; 2808Selection.jsonID("text", TextSelection); 2809var 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}; 2821var 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}; 2873NodeSelection.prototype.visible = false; 2874Selection.jsonID("node", NodeSelection); 2875var 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}; 2890var 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}; 2926Selection.jsonID("all", AllSelection); 2927var AllBookmark = { 2928 map() { 2929 return this; 2930 }, 2931 resolve(doc) { 2932 return new AllSelection(doc); 2933 } 2934}; 2935function 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} 2951function 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} 2965function bind(f, self) { 2966 return !self || !f ? f : f.bind(self); 2967} 2968var 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}; 2975var 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]; 3009function 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} 3020var 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}; 3038var keys = /* @__PURE__ */ Object.create(null); 3039function createKey(name) { 3040 if (name in keys) 3041 return name + "$" + ++keys[name]; 3042 keys[name] = 0; 3043 return name + "$"; 3044} 3045var 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 3068var Rebaseable = class { 3069 constructor(step, inverted, origin) { 3070 this.step = step; 3071 this.inverted = inverted; 3072 this.origin = origin; 3073 } 3074}; 3075function 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} 3091var CollabState = class { 3092 constructor(version, unconfirmed) { 3093 this.version = version; 3094 this.unconfirmed = unconfirmed; 3095 } 3096}; 3097function 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} 3103var collabKey = new PluginKey("collab"); 3104function 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} 3128function 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} 3155function 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} 3168function getVersion(state) { 3169 return collabKey.getState(state).version; 3170} 3171export { 3172 collab, 3173 getVersion, 3174 rebaseSteps, 3175 receiveTransaction, 3176 sendableSteps 3177};