PageSourceSearch

https://zerowaste.org/assets/prosemirror-transform-97402577.js

js zerowaste.org collected 2026-09-25 23:57:46 UTC 84,535 bytes, 2,213 lines download raw bytes

vendor: 4,367 bytes, lines 1-122
1// [email protected] downloaded from https://cdn.jsdelivr.net/npm/[email protected]/dist/index.js
2
3import { ReplaceError, Slice, Fragment, MarkType, Mark } from 'prosemirror-model';
4
5// Recovery values encode a range index and an offset. They are
6// represented as numbers, because tons of them will be created when
7// mapping, for example, a large number of decorations. The number's
8// lower 16 bits provide the index, the remaining bits the offset.
9//
10// Note: We intentionally don't use bit shift operators to en- and
11// decode these, since those clip to 32 bits, which we might in rare
12// cases want to overflow. A 64-bit float can represent 48-bit
13// integers precisely.
14const lower16 = 0xffff;
15const factor16 = Math.pow(2, 16);
16function makeRecover(index, offset) { return index + offset * factor16; }
17function recoverIndex(value) { return value & lower16; }
18function recoverOffset(value) { return (value - (value & lower16)) / factor16; }
19const DEL_BEFORE = 1, DEL_AFTER = 2, DEL_ACROSS = 4, DEL_SIDE = 8;
20/**
21An object representing a mapped position with extra
22information.
23*/
24class MapResult {
25    /**
26    @internal
27    */
28    constructor(
29    /**
30    The mapped version of the position.
31    */
32    pos, 
33    /**
34    @internal
35    */
36    delInfo, 
37    /**
38    @internal
39    */
40    recover) {
41        this.pos = pos;
42        this.delInfo = delInfo;
43        this.recover = recover;
44    }
45    /**
46    Tells you whether the position was deleted, that is, whether the
47    step removed the token on the side queried (via the `assoc`)
48    argument from the document.
49    */
50    get deleted() { return (this.delInfo & DEL_SIDE) > 0; }
51    /**
52    Tells you whether the token before the mapped position was deleted.
53    */
54    get deletedBefore() { return (this.delInfo & (DEL_BEFORE | DEL_ACROSS)) > 0; }
55    /**
56    True when the token after the mapped position was deleted.
57    */
58    get deletedAfter() { return (this.delInfo & (DEL_AFTER | DEL_ACROSS)) > 0; }
59    /**
60    Tells whether any of the steps mapped through deletes across the
61    position (including both the token before and after the
62    position).
63    */
64    get deletedAcross() { return (this.delInfo & DEL_ACROSS) > 0; }
65}
66/**
67A map describing the deletions and insertions made by a step, which
68can be used to find the correspondence between positions in the
69pre-step version of a document and the same position in the
70post-step version.
71*/
72class StepMap {
73    /**
74    Create a position map. The modifications to the document are
75    represented as an array of numbers, in which each group of three
76    represents a modified chunk as `[start, oldSize, newSize]`.
77    */
78    constructor(
79    /**
80    @internal
81    */
82    ranges, 
83    /**
84    @internal
85    */
86    inverted = false) {
87        this.ranges = ranges;
88        this.inverted = inverted;
89        if (!ranges.length && StepMap.empty)
90            return StepMap.empty;
91    }
92    /**
93    @internal
94    */
95    recover(value) {
96        let diff = 0, index = recoverIndex(value);
97        if (!this.inverted)
98            for (let i = 0; i < index; i++)
99                diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1];
100        return this.ranges[index * 3] + diff + recoverOffset(value);
101    }
102    mapResult(pos, assoc = 1) { return this._map(pos, assoc, false); }
103    map(pos, assoc = 1) { return this._map(pos, assoc, true); }
104    /**
105    @internal
106    */
107    _map(pos, assoc, simple) {
108        let diff = 0, oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
109        for (let i = 0; i < this.ranges.length; i += 3) {
110            let start = this.ranges[i] - (this.inverted ? diff : 0);
111            if (start > pos)
112                break;
113            let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize;
114            if (pos <= end) {
115                let side = !oldSize ? assoc : pos == start ? -1 : pos == end ? 1 : assoc;
116                let result = start + diff + (side < 0 ? 0 : newSize);
117                if (simple)
118                    return result;
119                let recover = pos == (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start);
120                let del = pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS;
121                if (assoc < 0 ? pos != start : pos != end)
122                    del |= DEL_SIDE;
vendor: 42,719 bytes, lines 122-1290
122
123                return new MapResult(result, del, recover);
124            }
125            diff += newSize - oldSize;
126        }
127        return simple ? pos + diff : new MapResult(pos + diff, 0, null);
128    }
129    /**
130    @internal
131    */
132    touches(pos, recover) {
133        let diff = 0, index = recoverIndex(recover);
134        let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
135        for (let i = 0; i < this.ranges.length; i += 3) {
136            let start = this.ranges[i] - (this.inverted ? diff : 0);
137            if (start > pos)
138                break;
139            let oldSize = this.ranges[i + oldIndex], end = start + oldSize;
140            if (pos <= end && i == index * 3)
141                return true;
142            diff += this.ranges[i + newIndex] - oldSize;
143        }
144        return false;
145    }
146    /**
147    Calls the given function on each of the changed ranges included in
148    this map.
149    */
150    forEach(f) {
151        let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
152        for (let i = 0, diff = 0; i < this.ranges.length; i += 3) {
153            let start = this.ranges[i], oldStart = start - (this.inverted ? diff : 0), newStart = start + (this.inverted ? 0 : diff);
154            let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex];
155            f(oldStart, oldStart + oldSize, newStart, newStart + newSize);
156            diff += newSize - oldSize;
157        }
158    }
159    /**
160    Create an inverted version of this map. The result can be used to
161    map positions in the post-step document to the pre-step document.
162    */
163    invert() {
164        return new StepMap(this.ranges, !this.inverted);
165    }
166    /**
167    @internal
168    */
169    toString() {
170        return (this.inverted ? "-" : "") + JSON.stringify(this.ranges);
171    }
172    /**
173    Create a map that moves all positions by offset `n` (which may be
174    negative). This can be useful when applying steps meant for a
175    sub-document to a larger document, or vice-versa.
176    */
177    static offset(n) {
178        return n == 0 ? StepMap.empty : new StepMap(n < 0 ? [0, -n, 0] : [0, 0, n]);
179    }
180}
181/**
182A StepMap that contains no changed ranges.
183*/
184StepMap.empty = new StepMap([]);
185/**
186A mapping represents a pipeline of zero or more [step
187maps](https://prosemirror.net/docs/ref/#transform.StepMap). It has special provisions for losslessly
188handling mapping positions through a series of steps in which some
189steps are inverted versions of earlier steps. (This comes up when
190‘[rebasing](https://prosemirror.net/docs/guide/#transform.rebasing)’ steps for
191collaboration or history management.)
192*/
193class Mapping {
194    /**
195    Create a new mapping with the given position maps.
196    */
197    constructor(maps, 
198    /**
199    @internal
200    */
201    mirror, 
202    /**
203    The starting position in the `maps` array, used when `map` or
204    `mapResult` is called.
205    */
206    from = 0, 
207    /**
208    The end position in the `maps` array.
209    */
210    to = maps ? maps.length : 0) {
211        this.mirror = mirror;
212        this.from = from;
213        this.to = to;
214        this._maps = maps || [];
215        this.ownData = !(maps || mirror);
216    }
217    /**
218    The step maps in this mapping.
219    */
220    get maps() { return this._maps; }
221    /**
222    Create a mapping that maps only through a part of this one.
223    */
224    slice(from = 0, to = this.maps.length) {
225        return new Mapping(this._maps, this.mirror, from, to);
226    }
227    /**
228    Add a step map to the end of this mapping. If `mirrors` is
229    given, it should be the index of the step map that is the mirror
230    image of this one.
231    */
232    appendMap(map, mirrors) {
233        if (!this.ownData) {
234            this._maps = this._maps.slice();
235            this.mirror = this.mirror && this.mirror.slice();
236            this.ownData = true;
237        }
238        this.to = this._maps.push(map);
239        if (mirrors != null)
240            this.setMirror(this._maps.length - 1, mirrors);
241    }
242    /**
243    Add all the step maps in a given mapping to this one (preserving
244    mirroring information).
245    */
246    appendMapping(mapping) {
247        for (let i = 0, startSize = this._maps.length; i < mapping._maps.length; i++) {
248            let mirr = mapping.getMirror(i);
249            this.appendMap(mapping._maps[i], mirr != null && mirr < i ? startSize + mirr : undefined);
250        }
251    }
252    /**
253    Finds the offset of the step map that mirrors the map at the
254    given offset, in this mapping (as per the second argument to
255    `appendMap`).
256    */
257    getMirror(n) {
258        if (this.mirror)
259            for (let i = 0; i < this.mirror.length; i++)
260                if (this.mirror[i] == n)
261                    return this.mirror[i + (i % 2 ? -1 : 1)];
262    }
263    /**
264    @internal
265    */
266    setMirror(n, m) {
267        if (!this.mirror)
268            this.mirror = [];
269        this.mirror.push(n, m);
270    }
271    /**
272    Append the inverse of the given mapping to this one.
273    */
274    appendMappingInverted(mapping) {
275        for (let i = mapping.maps.length - 1, totalSize = this._maps.length + mapping._maps.length; i >= 0; i--) {
276            let mirr = mapping.getMirror(i);
277            this.appendMap(mapping._maps[i].invert(), mirr != null && mirr > i ? totalSize - mirr - 1 : undefined);
278        }
279    }
280    /**
281    Create an inverted version of this mapping.
282    */
283    invert() {
284        let inverse = new Mapping;
285        inverse.appendMappingInverted(this);
286        return inverse;
287    }
288    /**
289    Map a position through this mapping.
290    */
291    map(pos, assoc = 1) {
292        if (this.mirror)
293            return this._map(pos, assoc, true);
294        for (let i = this.from; i < this.to; i++)
295            pos = this._maps[i].map(pos, assoc);
296        return pos;
297    }
298    /**
299    Map a position through this mapping, returning a mapping
300    result.
301    */
302    mapResult(pos, assoc = 1) { return this._map(pos, assoc, false); }
303    /**
304    @internal
305    */
306    _map(pos, assoc, simple) {
307        let delInfo = 0;
308        for (let i = this.from; i < this.to; i++) {
309            let map = this._maps[i], result = map.mapResult(pos, assoc);
310            if (result.recover != null) {
311                let corr = this.getMirror(i);
312                if (corr != null && corr > i && corr < this.to) {
313                    i = corr;
314                    pos = this._maps[corr].recover(result.recover);
315                    continue;
316                }
317            }
318            delInfo |= result.delInfo;
319            pos = result.pos;
320        }
321        return simple ? pos : new MapResult(pos, delInfo, null);
322    }
323}
324
325const stepsByID = Object.create(null);
326/**
327A step object represents an atomic change. It generally applies
328only to the document it was created for, since the positions
329stored in it will only make sense for that document.
330
331New steps are defined by creating classes that extend `Step`,
332overriding the `apply`, `invert`, `map`, `getMap` and `fromJSON`
333methods, and registering your class with a unique
334JSON-serialization identifier using
335[`Step.jsonID`](https://prosemirror.net/docs/ref/#transform.Step^jsonID).
336*/
337class Step {
338    /**
339    Get the step map that represents the changes made by this step,
340    and which can be used to transform between positions in the old
341    and the new document.
342    */
343    getMap() { return StepMap.empty; }
344    /**
345    Try to merge this step with another one, to be applied directly
346    after it. Returns the merged step when possible, null if the
347    steps can't be merged.
348    */
349    merge(other) { return null; }
350    /**
351    Deserialize a step from its JSON representation. Will call
352    through to the step class' own implementation of this method.
353    */
354    static fromJSON(schema, json) {
355        if (!json || !json.stepType)
356            throw new RangeError("Invalid input for Step.fromJSON");
357        let type = stepsByID[json.stepType];
358        if (!type)
359            throw new RangeError(`No step type ${json.stepType} defined`);
360        return type.fromJSON(schema, json);
361    }
362    /**
363    To be able to serialize steps to JSON, each step needs a string
364    ID to attach to its JSON representation. Use this method to
365    register an ID for your step classes. Try to pick something
366    that's unlikely to clash with steps from other modules.
367    */
368    static jsonID(id, stepClass) {
369        if (id in stepsByID)
370            throw new RangeError("Duplicate use of step JSON ID " + id);
371        stepsByID[id] = stepClass;
372        stepClass.prototype.jsonID = id;
373        return stepClass;
374    }
375}
376/**
377The result of [applying](https://prosemirror.net/docs/ref/#transform.Step.apply) a step. Contains either a
378new document or a failure value.
379*/
380class StepResult {
381    /**
382    @internal
383    */
384    constructor(
385    /**
386    The transformed document, if successful.
387    */
388    doc, 
389    /**
390    The failure message, if unsuccessful.
391    */
392    failed) {
393        this.doc = doc;
394        this.failed = failed;
395    }
396    /**
397    Create a successful step result.
398    */
399    static ok(doc) { return new StepResult(doc, null); }
400    /**
401    Create a failed step result.
402    */
403    static fail(message) { return new StepResult(null, message); }
404    /**
405    Call [`Node.replace`](https://prosemirror.net/docs/ref/#model.Node.replace) with the given
406    arguments. Create a successful result if it succeeds, and a
407    failed one if it throws a `ReplaceError`.
408    */
409    static fromReplace(doc, from, to, slice) {
410        try {
411            return StepResult.ok(doc.replace(from, to, slice));
412        }
413        catch (e) {
414            if (e instanceof ReplaceError)
415                return StepResult.fail(e.message);
416            throw e;
417        }
418    }
419}
420
421function mapFragment(fragment, f, parent) {
422    let mapped = [];
423    for (let i = 0; i < fragment.childCount; i++) {
424        let child = fragment.child(i);
425        if (child.content.size)
426            child = child.copy(mapFragment(child.content, f, child));
427        if (child.isInline)
428            child = f(child, parent, i);
429        mapped.push(child);
430    }
431    return Fragment.fromArray(mapped);
432}
433/**
434Add a mark to all inline content between two positions.
435*/
436class AddMarkStep extends Step {
437    /**
438    Create a mark step.
439    */
440    constructor(
441    /**
442    The start of the marked range.
443    */
444    from, 
445    /**
446    The end of the marked range.
447    */
448    to, 
449    /**
450    The mark to add.
451    */
452    mark) {
453        super();
454        this.from = from;
455        this.to = to;
456        this.mark = mark;
457    }
458    apply(doc) {
459        let oldSlice = doc.slice(this.from, this.to), $from = doc.resolve(this.from);
460        let parent = $from.node($from.sharedDepth(this.to));
461        let slice = new Slice(mapFragment(oldSlice.content, (node, parent) => {
462            if (!node.isAtom || !parent.type.allowsMarkType(this.mark.type))
463                return node;
464            return node.mark(this.mark.addToSet(node.marks));
465        }, parent), oldSlice.openStart, oldSlice.openEnd);
466        return StepResult.fromReplace(doc, this.from, this.to, slice);
467    }
468    invert() {
469        return new RemoveMarkStep(this.from, this.to, this.mark);
470    }
471    map(mapping) {
472        let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
473        if (from.deleted && to.deleted || from.pos >= to.pos)
474            return null;
475        return new AddMarkStep(from.pos, to.pos, this.mark);
476    }
477    merge(other) {
478        if (other instanceof AddMarkStep &&
479            other.mark.eq(this.mark) &&
480            this.from <= other.to && this.to >= other.from)
481            return new AddMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark);
482        return null;
483    }
484    toJSON() {
485        return { stepType: "addMark", mark: this.mark.toJSON(),
486            from: this.from, to: this.to };
487    }
488    /**
489    @internal
490    */
491    static fromJSON(schema, json) {
492        if (typeof json.from != "number" || typeof json.to != "number")
493            throw new RangeError("Invalid input for AddMarkStep.fromJSON");
494        return new AddMarkStep(json.from, json.to, schema.markFromJSON(json.mark));
495    }
496}
497Step.jsonID("addMark", AddMarkStep);
498/**
499Remove a mark from all inline content between two positions.
500*/
501class RemoveMarkStep extends Step {
502    /**
503    Create a mark-removing step.
504    */
505    constructor(
506    /**
507    The start of the unmarked range.
508    */
509    from, 
510    /**
511    The end of the unmarked range.
512    */
513    to, 
514    /**
515    The mark to remove.
516    */
517    mark) {
518        super();
519        this.from = from;
520        this.to = to;
521        this.mark = mark;
522    }
523    apply(doc) {
524        let oldSlice = doc.slice(this.from, this.to);
525        let slice = new Slice(mapFragment(oldSlice.content, node => {
526            return node.mark(this.mark.removeFromSet(node.marks));
527        }, doc), oldSlice.openStart, oldSlice.openEnd);
528        return StepResult.fromReplace(doc, this.from, this.to, slice);
529    }
530    invert() {
531        return new AddMarkStep(this.from, this.to, this.mark);
532    }
533    map(mapping) {
534        let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
535        if (from.deleted && to.deleted || from.pos >= to.pos)
536            return null;
537        return new RemoveMarkStep(from.pos, to.pos, this.mark);
538    }
539    merge(other) {
540        if (other instanceof RemoveMarkStep &&
541            other.mark.eq(this.mark) &&
542            this.from <= other.to && this.to >= other.from)
543            return new RemoveMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark);
544        return null;
545    }
546    toJSON() {
547        return { stepType: "removeMark", mark: this.mark.toJSON(),
548            from: this.from, to: this.to };
549    }
550    /**
551    @internal
552    */
553    static fromJSON(schema, json) {
554        if (typeof json.from != "number" || typeof json.to != "number")
555            throw new RangeError("Invalid input for RemoveMarkStep.fromJSON");
556        return new RemoveMarkStep(json.from, json.to, schema.markFromJSON(json.mark));
557    }
558}
559Step.jsonID("removeMark", RemoveMarkStep);
560/**
561Add a mark to a specific node.
562*/
563class AddNodeMarkStep extends Step {
564    /**
565    Create a node mark step.
566    */
567    constructor(
568    /**
569    The position of the target node.
570    */
571    pos, 
572    /**
573    The mark to add.
574    */
575    mark) {
576        super();
577        this.pos = pos;
578        this.mark = mark;
579    }
580    apply(doc) {
581        let node = doc.nodeAt(this.pos);
582        if (!node)
583            return StepResult.fail("No node at mark step's position");
584        let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
585        return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
586    }
587    invert(doc) {
588        let node = doc.nodeAt(this.pos);
589        if (node) {
590            let newSet = this.mark.addToSet(node.marks);
591            if (newSet.length == node.marks.length) {
592                for (let i = 0; i < node.marks.length; i++)
593                    if (!node.marks[i].isInSet(newSet))
594                        return new AddNodeMarkStep(this.pos, node.marks[i]);
595                return new AddNodeMarkStep(this.pos, this.mark);
596            }
597        }
598        return new RemoveNodeMarkStep(this.pos, this.mark);
599    }
600    map(mapping) {
601        let pos = mapping.mapResult(this.pos, 1);
602        return pos.deletedAfter ? null : new AddNodeMarkStep(pos.pos, this.mark);
603    }
604    toJSON() {
605        return { stepType: "addNodeMark", pos: this.pos, mark: this.mark.toJSON() };
606    }
607    /**
608    @internal
609    */
610    static fromJSON(schema, json) {
611        if (typeof json.pos != "number")
612            throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON");
613        return new AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
614    }
615}
616Step.jsonID("addNodeMark", AddNodeMarkStep);
617/**
618Remove a mark from a specific node.
619*/
620class RemoveNodeMarkStep extends Step {
621    /**
622    Create a mark-removing step.
623    */
624    constructor(
625    /**
626    The position of the target node.
627    */
628    pos, 
629    /**
630    The mark to remove.
631    */
632    mark) {
633        super();
634        this.pos = pos;
635        this.mark = mark;
636    }
637    apply(doc) {
638        let node = doc.nodeAt(this.pos);
639        if (!node)
640            return StepResult.fail("No node at mark step's position");
641        let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
642        return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
643    }
644    invert(doc) {
645        let node = doc.nodeAt(this.pos);
646        if (!node || !this.mark.isInSet(node.marks))
647            return this;
648        return new AddNodeMarkStep(this.pos, this.mark);
649    }
650    map(mapping) {
651        let pos = mapping.mapResult(this.pos, 1);
652        return pos.deletedAfter ? null : new RemoveNodeMarkStep(pos.pos, this.mark);
653    }
654    toJSON() {
655        return { stepType: "removeNodeMark", pos: this.pos, mark: this.mark.toJSON() };
656    }
657    /**
658    @internal
659    */
660    static fromJSON(schema, json) {
661        if (typeof json.pos != "number")
662            throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON");
663        return new RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
664    }
665}
666Step.jsonID("removeNodeMark", RemoveNodeMarkStep);
667
668/**
669Replace a part of the document with a slice of new content.
670*/
671class ReplaceStep extends Step {
672    /**
673    The given `slice` should fit the 'gap' between `from` and
674    `to`—the depths must line up, and the surrounding nodes must be
675    able to be joined with the open sides of the slice. When
676    `structure` is true, the step will fail if the content between
677    from and to is not just a sequence of closing and then opening
678    tokens (this is to guard against rebased replace steps
679    overwriting something they weren't supposed to).
680    */
681    constructor(
682    /**
683    The start position of the replaced range.
684    */
685    from, 
686    /**
687    The end position of the replaced range.
688    */
689    to, 
690    /**
691    The slice to insert.
692    */
693    slice, 
694    /**
695    @internal
696    */
697    structure = false) {
698        super();
699        this.from = from;
700        this.to = to;
701        this.slice = slice;
702        this.structure = structure;
703    }
704    apply(doc) {
705        if (this.structure && contentBetween(doc, this.from, this.to))
706            return StepResult.fail("Structure replace would overwrite content");
707        return StepResult.fromReplace(doc, this.from, this.to, this.slice);
708    }
709    getMap() {
710        return new StepMap([this.from, this.to - this.from, this.slice.size]);
711    }
712    invert(doc) {
713        return new ReplaceStep(this.from, this.from + this.slice.size, doc.slice(this.from, this.to));
714    }
715    map(mapping) {
716        let to = mapping.mapResult(this.to, -1);
717        let from = this.from == this.to && ReplaceStep.MAP_BIAS < 0 ? to : mapping.mapResult(this.from, 1);
718        if (from.deletedAcross && to.deletedAcross)
719            return null;
720        return new ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice, this.structure);
721    }
722    merge(other) {
723        if (!(other instanceof ReplaceStep) || other.structure || this.structure)
724            return null;
725        if (this.from + this.slice.size == other.from && !this.slice.openEnd && !other.slice.openStart) {
726            let slice = this.slice.size + other.slice.size == 0 ? Slice.empty
727                : new Slice(this.slice.content.append(other.slice.content), this.slice.openStart, other.slice.openEnd);
728            return new ReplaceStep(this.from, this.to + (other.to - other.from), slice, this.structure);
729        }
730        else if (other.to == this.from && !this.slice.openStart && !other.slice.openEnd) {
731            let slice = this.slice.size + other.slice.size == 0 ? Slice.empty
732                : new Slice(other.slice.content.append(this.slice.content), other.slice.openStart, this.slice.openEnd);
733            return new ReplaceStep(other.from, this.to, slice, this.structure);
734        }
735        else {
736            return null;
737        }
738    }
739    toJSON() {
740        let json = { stepType: "replace", from: this.from, to: this.to };
741        if (this.slice.size)
742            json.slice = this.slice.toJSON();
743        if (this.structure)
744            json.structure = true;
745        return json;
746    }
747    /**
748    @internal
749    */
750    static fromJSON(schema, json) {
751        if (typeof json.from != "number" || typeof json.to != "number")
752            throw new RangeError("Invalid input for ReplaceStep.fromJSON");
753        return new ReplaceStep(json.from, json.to, Slice.fromJSON(schema, json.slice), !!json.structure);
754    }
755}
756/**
757By default, for backwards compatibility, an inserting step
758mapped over an insertion at that same position fill move after
759the inserted content. In a collaborative editing situation, that
760can make redone insertions appear in unexpected places. You can
761set this to -1 to make such mapping keep the step before the
762insertion instead.
763*/
764ReplaceStep.MAP_BIAS = 1;
765Step.jsonID("replace", ReplaceStep);
766/**
767Replace a part of the document with a slice of content, but
768preserve a range of the replaced content by moving it into the
769slice.
770*/
771class ReplaceAroundStep extends Step {
772    /**
773    Create a replace-around step with the given range and gap.
774    `insert` should be the point in the slice into which the content
775    of the gap should be moved. `structure` has the same meaning as
776    it has in the [`ReplaceStep`](https://prosemirror.net/docs/ref/#transform.ReplaceStep) class.
777    */
778    constructor(
779    /**
780    The start position of the replaced range.
781    */
782    from, 
783    /**
784    The end position of the replaced range.
785    */
786    to, 
787    /**
788    The start of preserved range.
789    */
790    gapFrom, 
791    /**
792    The end of preserved range.
793    */
794    gapTo, 
795    /**
796    The slice to insert.
797    */
798    slice, 
799    /**
800    The position in the slice where the preserved range should be
801    inserted.
802    */
803    insert, 
804    /**
805    @internal
806    */
807    structure = false) {
808        super();
809        this.from = from;
810        this.to = to;
811        this.gapFrom = gapFrom;
812        this.gapTo = gapTo;
813        this.slice = slice;
814        this.insert = insert;
815        this.structure = structure;
816    }
817    apply(doc) {
818        if (this.structure && (contentBetween(doc, this.from, this.gapFrom) ||
819            contentBetween(doc, this.gapTo, this.to)))
820            return StepResult.fail("Structure gap-replace would overwrite content");
821        let gap = doc.slice(this.gapFrom, this.gapTo);
822        if (gap.openStart || gap.openEnd)
823            return StepResult.fail("Gap is not a flat range");
824        let inserted = this.slice.insertAt(this.insert, gap.content);
825        if (!inserted)
826            return StepResult.fail("Content does not fit in gap");
827        return StepResult.fromReplace(doc, this.from, this.to, inserted);
828    }
829    getMap() {
830        return new StepMap([this.from, this.gapFrom - this.from, this.insert,
831            this.gapTo, this.to - this.gapTo, this.slice.size - this.insert]);
832    }
833    invert(doc) {
834        let gap = this.gapTo - this.gapFrom;
835        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);
836    }
837    map(mapping) {
838        let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
839        let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
840        let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
841        if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos)
842            return null;
843        return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
844    }
845    toJSON() {
846        let json = { stepType: "replaceAround", from: this.from, to: this.to,
847            gapFrom: this.gapFrom, gapTo: this.gapTo, insert: this.insert };
848        if (this.slice.size)
849            json.slice = this.slice.toJSON();
850        if (this.structure)
851            json.structure = true;
852        return json;
853    }
854    /**
855    @internal
856    */
857    static fromJSON(schema, json) {
858        if (typeof json.from != "number" || typeof json.to != "number" ||
859            typeof json.gapFrom != "number" || typeof json.gapTo != "number" || typeof json.insert != "number")
860            throw new RangeError("Invalid input for ReplaceAroundStep.fromJSON");
861        return new ReplaceAroundStep(json.from, json.to, json.gapFrom, json.gapTo, Slice.fromJSON(schema, json.slice), json.insert, !!json.structure);
862    }
863}
864Step.jsonID("replaceAround", ReplaceAroundStep);
865function contentBetween(doc, from, to) {
866    let $from = doc.resolve(from), dist = to - from, depth = $from.depth;
867    while (dist > 0 && depth > 0 && $from.indexAfter(depth) == $from.node(depth).childCount) {
868        depth--;
869        dist--;
870    }
871    if (dist > 0) {
872        let next = $from.node(depth).maybeChild($from.indexAfter(depth));
873        while (dist > 0) {
874            if (!next || next.isLeaf)
875                return true;
876            next = next.firstChild;
877            dist--;
878        }
879    }
880    return false;
881}
882
883function addMark(tr, from, to, mark) {
884    let removed = [], added = [];
885    let removing, adding;
886    tr.doc.nodesBetween(from, to, (node, pos, parent) => {
887        if (!node.isInline)
888            return;
889        let marks = node.marks;
890        if (!mark.isInSet(marks) && parent.type.allowsMarkType(mark.type)) {
891            let start = Math.max(pos, from), end = Math.min(pos + node.nodeSize, to);
892            let newSet = mark.addToSet(marks);
893            for (let i = 0; i < marks.length; i++) {
894                if (!marks[i].isInSet(newSet)) {
895                    if (removing && removing.to == start && removing.mark.eq(marks[i]))
896                        removing.to = end;
897                    else
898                        removed.push(removing = new RemoveMarkStep(start, end, marks[i]));
899                }
900            }
901            if (adding && adding.to == start)
902                adding.to = end;
903            else
904                added.push(adding = new AddMarkStep(start, end, mark));
905        }
906    });
907    removed.forEach(s => tr.step(s));
908    added.forEach(s => tr.step(s));
909}
910function removeMark(tr, from, to, mark) {
911    let matched = [], step = 0;
912    tr.doc.nodesBetween(from, to, (node, pos) => {
913        if (!node.isInline)
914            return;
915        step++;
916        let toRemove = null;
917        if (mark instanceof MarkType) {
918            let set = node.marks, found;
919            while (found = mark.isInSet(set)) {
920                (toRemove || (toRemove = [])).push(found);
921                set = found.removeFromSet(set);
922            }
923        }
924        else if (mark) {
925            if (mark.isInSet(node.marks))
926                toRemove = [mark];
927        }
928        else {
929            toRemove = node.marks;
930        }
931        if (toRemove && toRemove.length) {
932            let end = Math.min(pos + node.nodeSize, to);
933            for (let i = 0; i < toRemove.length; i++) {
934                let style = toRemove[i], found;
935                for (let j = 0; j < matched.length; j++) {
936                    let m = matched[j];
937                    if (m.step == step - 1 && style.eq(matched[j].style))
938                        found = m;
939                }
940                if (found) {
941                    found.to = end;
942                    found.step = step;
943                }
944                else {
945                    matched.push({ style, from: Math.max(pos, from), to: end, step });
946                }
947            }
948        }
949    });
950    matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)));
951}
952function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
953    let node = tr.doc.nodeAt(pos);
954    let replSteps = [], cur = pos + 1;
955    for (let i = 0; i < node.childCount; i++) {
956        let child = node.child(i), end = cur + child.nodeSize;
957        let allowed = match.matchType(child.type);
958        if (!allowed) {
959            replSteps.push(new ReplaceStep(cur, end, Slice.empty));
960        }
961        else {
962            match = allowed;
963            for (let j = 0; j < child.marks.length; j++)
964                if (!parentType.allowsMarkType(child.marks[j].type))
965                    tr.step(new RemoveMarkStep(cur, end, child.marks[j]));
966            if (clearNewlines && child.isText && parentType.whitespace != "pre") {
967                let m, newline = /\r?\n|\r/g, slice;
968                while (m = newline.exec(child.text)) {
969                    if (!slice)
970                        slice = new Slice(Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))), 0, 0);
971                    replSteps.push(new ReplaceStep(cur + m.index, cur + m.index + m[0].length, slice));
972                }
973            }
974        }
975        cur = end;
976    }
977    if (!match.validEnd) {
978        let fill = match.fillBefore(Fragment.empty, true);
979        tr.replace(cur, cur, new Slice(fill, 0, 0));
980    }
981    for (let i = replSteps.length - 1; i >= 0; i--)
982        tr.step(replSteps[i]);
983}
984
985function canCut(node, start, end) {
986    return (start == 0 || node.canReplace(start, node.childCount)) &&
987        (end == node.childCount || node.canReplace(0, end));
988}
989/**
990Try to find a target depth to which the content in the given range
991can be lifted. Will not go across
992[isolating](https://prosemirror.net/docs/ref/#model.NodeSpec.isolating) parent nodes.
993*/
994function liftTarget(range) {
995    let parent = range.parent;
996    let content = parent.content.cutByIndex(range.startIndex, range.endIndex);
997    for (let depth = range.depth, contentBefore = 0, contentAfter = 0;; --depth) {
998        let node = range.$from.node(depth);
999        let index = range.$from.index(depth) + contentBefore, endIndex = range.$to.indexAfter(depth) - contentAfter;
1000        if (depth < range.depth && node.canReplace(index, endIndex, content))
1001            return depth;
1002        if (depth == 0 || node.type.spec.isolating || !canCut(node, index, endIndex))
1003            break;
1004        if (index)
1005            contentBefore = 1;
1006        if (endIndex < node.childCount)
1007            contentAfter = 1;
1008    }
1009    return null;
1010}
1011function lift(tr, range, target) {
1012    let { $from, $to, depth } = range;
1013    let gapStart = $from.before(depth + 1), gapEnd = $to.after(depth + 1);
1014    let start = gapStart, end = gapEnd;
1015    let before = Fragment.empty, openStart = 0;
1016    for (let d = depth, splitting = false; d > target; d--)
1017        if (splitting || $from.index(d) > 0) {
1018            splitting = true;
1019            before = Fragment.from($from.node(d).copy(before));
1020            openStart++;
1021        }
1022        else {
1023            start--;
1024        }
1025    let after = Fragment.empty, openEnd = 0;
1026    for (let d = depth, splitting = false; d > target; d--)
1027        if (splitting || $to.after(d + 1) < $to.end(d)) {
1028            splitting = true;
1029            after = Fragment.from($to.node(d).copy(after));
1030            openEnd++;
1031        }
1032        else {
1033            end++;
1034        }
1035    tr.step(new ReplaceAroundStep(start, end, gapStart, gapEnd, new Slice(before.append(after), openStart, openEnd), before.size - openStart, true));
1036}
1037/**
1038Try to find a valid way to wrap the content in the given range in a
1039node of the given type. May introduce extra nodes around and inside
1040the wrapper node, if necessary. Returns null if no valid wrapping
1041could be found. When `innerRange` is given, that range's content is
1042used as the content to fit into the wrapping, instead of the
1043content of `range`.
1044*/
1045function findWrapping(range, nodeType, attrs = null, innerRange = range) {
1046    let around = findWrappingOutside(range, nodeType);
1047    let inner = around && findWrappingInside(innerRange, nodeType);
1048    if (!inner)
1049        return null;
1050    return around.map(withAttrs)
1051        .concat({ type: nodeType, attrs }).concat(inner.map(withAttrs));
1052}
1053function withAttrs(type) { return { type, attrs: null }; }
1054function findWrappingOutside(range, type) {
1055    let { parent, startIndex, endIndex } = range;
1056    let around = parent.contentMatchAt(startIndex).findWrapping(type);
1057    if (!around)
1058        return null;
1059    let outer = around.length ? around[0] : type;
1060    return parent.canReplaceWith(startIndex, endIndex, outer) ? around : null;
1061}
1062function findWrappingInside(range, type) {
1063    let { parent, startIndex, endIndex } = range;
1064    let inner = parent.child(startIndex);
1065    let inside = type.contentMatch.findWrapping(inner.type);
1066    if (!inside)
1067        return null;
1068    let lastType = inside.length ? inside[inside.length - 1] : type;
1069    let innerMatch = lastType.contentMatch;
1070    for (let i = startIndex; innerMatch && i < endIndex; i++)
1071        innerMatch = innerMatch.matchType(parent.child(i).type);
1072    if (!innerMatch || !innerMatch.validEnd)
1073        return null;
1074    return inside;
1075}
1076function wrap(tr, range, wrappers) {
1077    let content = Fragment.empty;
1078    for (let i = wrappers.length - 1; i >= 0; i--) {
1079        if (content.size) {
1080            let match = wrappers[i].type.contentMatch.matchFragment(content);
1081            if (!match || !match.validEnd)
1082                throw new RangeError("Wrapper type given to Transform.wrap does not form valid content of its parent wrapper");
1083        }
1084        content = Fragment.from(wrappers[i].type.create(wrappers[i].attrs, content));
1085    }
1086    let start = range.start, end = range.end;
1087    tr.step(new ReplaceAroundStep(start, end, start, end, new Slice(content, 0, 0), wrappers.length, true));
1088}
1089function setBlockType(tr, from, to, type, attrs) {
1090    if (!type.isTextblock)
1091        throw new RangeError("Type given to setBlockType should be a textblock");
1092    let mapFrom = tr.steps.length;
1093    tr.doc.nodesBetween(from, to, (node, pos) => {
1094        let attrsHere = typeof attrs == "function" ? attrs(node) : attrs;
1095        if (node.isTextblock && !node.hasMarkup(type, attrsHere) &&
1096            canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
1097            let convertNewlines = null;
1098            if (type.schema.linebreakReplacement) {
1099                let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
1100                if (pre && !supportLinebreak)
1101                    convertNewlines = false;
1102                else if (!pre && supportLinebreak)
1103                    convertNewlines = true;
1104            }
1105            // Ensure all markup that isn't allowed in the new node type is cleared
1106            if (convertNewlines === false)
1107                replaceLinebreaks(tr, node, pos, mapFrom);
1108            clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
1109            let mapping = tr.mapping.slice(mapFrom);
1110            let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
1111            tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true));
1112            if (convertNewlines === true)
1113                replaceNewlines(tr, node, pos, mapFrom);
1114            return false;
1115        }
1116    });
1117}
1118function replaceNewlines(tr, node, pos, mapFrom) {
1119    node.forEach((child, offset) => {
1120        if (child.isText) {
1121            let m, newline = /\r?\n|\r/g;
1122            while (m = newline.exec(child.text)) {
1123                let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
1124                tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
1125            }
1126        }
1127    });
1128}
1129function replaceLinebreaks(tr, node, pos, mapFrom) {
1130    node.forEach((child, offset) => {
1131        if (child.type == child.type.schema.linebreakReplacement) {
1132            let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
1133            tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
1134        }
1135    });
1136}
1137function canChangeType(doc, pos, type) {
1138    let $pos = doc.resolve(pos), index = $pos.index();
1139    return $pos.parent.canReplaceWith(index, index + 1, type);
1140}
1141/**
1142Change the type, attributes, and/or marks of the node at `pos`.
1143When `type` isn't given, the existing node type is preserved,
1144*/
1145function setNodeMarkup(tr, pos, type, attrs, marks) {
1146    let node = tr.doc.nodeAt(pos);
1147    if (!node)
1148        throw new RangeError("No node at given position");
1149    if (!type)
1150        type = node.type;
1151    let newNode = type.create(attrs, null, marks || node.marks);
1152    if (node.isLeaf)
1153        return tr.replaceWith(pos, pos + node.nodeSize, newNode);
1154    if (!type.validContent(node.content))
1155        throw new RangeError("Invalid content for node type " + type.name);
1156    tr.step(new ReplaceAroundStep(pos, pos + node.nodeSize, pos + 1, pos + node.nodeSize - 1, new Slice(Fragment.from(newNode), 0, 0), 1, true));
1157}
1158/**
1159Check whether splitting at the given position is allowed.
1160*/
1161function canSplit(doc, pos, depth = 1, typesAfter) {
1162    let $pos = doc.resolve(pos), base = $pos.depth - depth;
1163    let innerType = (typesAfter && typesAfter[typesAfter.length - 1]) || $pos.parent;
1164    if (base < 0 || $pos.parent.type.spec.isolating ||
1165        !$pos.parent.canReplace($pos.index(), $pos.parent.childCount) ||
1166        !innerType.type.validContent($pos.parent.content.cutByIndex($pos.index(), $pos.parent.childCount)))
1167        return false;
1168    for (let d = $pos.depth - 1, i = depth - 2; d > base; d--, i--) {
1169        let node = $pos.node(d), index = $pos.index(d);
1170        if (node.type.spec.isolating)
1171            return false;
1172        let rest = node.content.cutByIndex(index, node.childCount);
1173        let overrideChild = typesAfter && typesAfter[i + 1];
1174        if (overrideChild)
1175            rest = rest.replaceChild(0, overrideChild.type.create(overrideChild.attrs));
1176        let after = (typesAfter && typesAfter[i]) || node;
1177        if (!node.canReplace(index + 1, node.childCount) || !after.type.validContent(rest))
1178            return false;
1179    }
1180    let index = $pos.indexAfter(base);
1181    let baseType = typesAfter && typesAfter[0];
1182    return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type);
1183}
1184function split(tr, pos, depth = 1, typesAfter) {
1185    let $pos = tr.doc.resolve(pos), before = Fragment.empty, after = Fragment.empty;
1186    for (let d = $pos.depth, e = $pos.depth - depth, i = depth - 1; d > e; d--, i--) {
1187        before = Fragment.from($pos.node(d).copy(before));
1188        let typeAfter = typesAfter && typesAfter[i];
1189        after = Fragment.from(typeAfter ? typeAfter.type.create(typeAfter.attrs, after) : $pos.node(d).copy(after));
1190    }
1191    tr.step(new ReplaceStep(pos, pos, new Slice(before.append(after), depth, depth), true));
1192}
1193/**
1194Test whether the blocks before and after a given position can be
1195joined.
1196*/
1197function canJoin(doc, pos) {
1198    let $pos = doc.resolve(pos), index = $pos.index();
1199    return joinable($pos.nodeBefore, $pos.nodeAfter) &&
1200        $pos.parent.canReplace(index, index + 1);
1201}
1202function canAppendWithSubstitutedLinebreaks(a, b) {
1203    if (!b.content.size)
1204        a.type.compatibleContent(b.type);
1205    let match = a.contentMatchAt(a.childCount);
1206    let { linebreakReplacement } = a.type.schema;
1207    for (let i = 0; i < b.childCount; i++) {
1208        let child = b.child(i);
1209        let type = child.type == linebreakReplacement ? a.type.schema.nodes.text : child.type;
1210        match = match.matchType(type);
1211        if (!match)
1212            return false;
1213        if (!a.type.allowsMarks(child.marks))
1214            return false;
1215    }
1216    return match.validEnd;
1217}
1218function joinable(a, b) {
1219    return !!(a && b && !a.isLeaf && canAppendWithSubstitutedLinebreaks(a, b));
1220}
1221/**
1222Find an ancestor of the given position that can be joined to the
1223block before (or after if `dir` is positive). Returns the joinable
1224point, if any.
1225*/
1226function joinPoint(doc, pos, dir = -1) {
1227    let $pos = doc.resolve(pos);
1228    for (let d = $pos.depth;; d--) {
1229        let before, after, index = $pos.index(d);
1230        if (d == $pos.depth) {
1231            before = $pos.nodeBefore;
1232            after = $pos.nodeAfter;
1233        }
1234        else if (dir > 0) {
1235            before = $pos.node(d + 1);
1236            index++;
1237            after = $pos.node(d).maybeChild(index);
1238        }
1239        else {
1240            before = $pos.node(d).maybeChild(index - 1);
1241            after = $pos.node(d + 1);
1242        }
1243        if (before && !before.isTextblock && joinable(before, after) &&
1244            $pos.node(d).canReplace(index, index + 1))
1245            return pos;
1246        if (d == 0)
1247            break;
1248        pos = dir < 0 ? $pos.before(d) : $pos.after(d);
1249    }
1250}
1251function join(tr, pos, depth) {
1252    let convertNewlines = null;
1253    let { linebreakReplacement } = tr.doc.type.schema;
1254    let $before = tr.doc.resolve(pos - depth), beforeType = $before.node().type;
1255    if (linebreakReplacement && beforeType.inlineContent) {
1256        let pre = beforeType.whitespace == "pre";
1257        let supportLinebreak = !!beforeType.contentMatch.matchType(linebreakReplacement);
1258        if (pre && !supportLinebreak)
1259            convertNewlines = false;
1260        else if (!pre && supportLinebreak)
1261            convertNewlines = true;
1262    }
1263    let mapFrom = tr.steps.length;
1264    if (convertNewlines === false) {
1265        let $after = tr.doc.resolve(pos + depth);
1266        replaceLinebreaks(tr, $after.node(), $after.before(), mapFrom);
1267    }
1268    if (beforeType.inlineContent)
1269        clearIncompatible(tr, pos + depth - 1, beforeType, $before.node().contentMatchAt($before.index()), convertNewlines == null);
1270    let mapping = tr.mapping.slice(mapFrom), start = mapping.map(pos - depth);
1271    tr.step(new ReplaceStep(start, mapping.map(pos + depth, -1), Slice.empty, true));
1272    if (convertNewlines === true) {
1273        let $full = tr.doc.resolve(start);
1274        replaceNewlines(tr, $full.node(), $full.before(), tr.steps.length);
1275    }
1276    return tr;
1277}
1278/**
1279Try to find a point where a node of the given type can be inserted
1280near `pos`, by searching up the node hierarchy when `pos` itself
1281isn't a valid place but is at the start or end of a node. Return
1282null if no position was found.
1283*/
1284function insertPoint(doc, pos, nodeType) {
1285    let $pos = doc.resolve(pos);
1286    if ($pos.parent.canReplaceWith($pos.index(), $pos.index(), nodeType))
1287        return pos;
1288    if ($pos.parentOffset == 0)
1289        for (let d = $pos.depth - 1; d >= 0; d--) {
1290            let index = $pos.index(d);
vendor: 13,288 bytes, lines 1291-1566
1291            if ($pos.node(d).canReplaceWith(index, index, nodeType))
1292                return $pos.before(d + 1);
1293            if (index > 0)
1294                return null;
1295        }
1296    if ($pos.parentOffset == $pos.parent.content.size)
1297        for (let d = $pos.depth - 1; d >= 0; d--) {
1298            let index = $pos.indexAfter(d);
1299            if ($pos.node(d).canReplaceWith(index, index, nodeType))
1300                return $pos.after(d + 1);
1301            if (index < $pos.node(d).childCount)
1302                return null;
1303        }
1304    return null;
1305}
1306/**
1307Finds a position at or around the given position where the given
1308slice can be inserted. Will look at parent nodes' nearest boundary
1309and try there, even if the original position wasn't directly at the
1310start or end of that node. Returns null when no position was found.
1311*/
1312function dropPoint(doc, pos, slice) {
1313    let $pos = doc.resolve(pos);
1314    if (!slice.content.size)
1315        return pos;
1316    let content = slice.content;
1317    for (let i = 0; i < slice.openStart; i++)
1318        content = content.firstChild.content;
1319    for (let pass = 1; pass <= (slice.openStart == 0 && slice.size ? 2 : 1); pass++) {
1320        for (let d = $pos.depth; d >= 0; d--) {
1321            let bias = d == $pos.depth ? 0 : $pos.pos <= ($pos.start(d + 1) + $pos.end(d + 1)) / 2 ? -1 : 1;
1322            let insertPos = $pos.index(d) + (bias > 0 ? 1 : 0);
1323            let parent = $pos.node(d), fits = false;
1324            if (pass == 1) {
1325                fits = parent.canReplace(insertPos, insertPos, content);
1326            }
1327            else {
1328                let wrapping = parent.contentMatchAt(insertPos).findWrapping(content.firstChild.type);
1329                fits = wrapping && parent.canReplaceWith(insertPos, insertPos, wrapping[0]);
1330            }
1331            if (fits)
1332                return bias == 0 ? $pos.pos : bias < 0 ? $pos.before(d + 1) : $pos.after(d + 1);
1333        }
1334    }
1335    return null;
1336}
1337
1338/**
1339‘Fit’ a slice into a given position in the document, producing a
1340[step](https://prosemirror.net/docs/ref/#transform.Step) that inserts it. Will return null if
1341there's no meaningful way to insert the slice here, or inserting it
1342would be a no-op (an empty slice over an empty range).
1343*/
1344function replaceStep(doc, from, to = from, slice = Slice.empty) {
1345    if (from == to && !slice.size)
1346        return null;
1347    let $from = doc.resolve(from), $to = doc.resolve(to);
1348    // Optimization -- avoid work if it's obvious that it's not needed.
1349    if (fitsTrivially($from, $to, slice))
1350        return new ReplaceStep(from, to, slice);
1351    return new Fitter($from, $to, slice).fit();
1352}
1353function fitsTrivially($from, $to, slice) {
1354    return !slice.openStart && !slice.openEnd && $from.start() == $to.start() &&
1355        $from.parent.canReplace($from.index(), $to.index(), slice.content);
1356}
1357// Algorithm for 'placing' the elements of a slice into a gap:
1358//
1359// We consider the content of each node that is open to the left to be
1360// independently placeable. I.e. in <p("foo"), p("bar")>, when the
1361// paragraph on the left is open, "foo" can be placed (somewhere on
1362// the left side of the replacement gap) independently from p("bar").
1363//
1364// This class tracks the state of the placement progress in the
1365// following properties:
1366//
1367//  - `frontier` holds a stack of `{type, match}` objects that
1368//    represent the open side of the replacement. It starts at
1369//    `$from`, then moves forward as content is placed, and is finally
1370//    reconciled with `$to`.
1371//
1372//  - `unplaced` is a slice that represents the content that hasn't
1373//    been placed yet.
1374//
1375//  - `placed` is a fragment of placed content. Its open-start value
1376//    is implicit in `$from`, and its open-end value in `frontier`.
1377class Fitter {
1378    constructor($from, $to, unplaced) {
1379        this.$from = $from;
1380        this.$to = $to;
1381        this.unplaced = unplaced;
1382        this.frontier = [];
1383        this.placed = Fragment.empty;
1384        for (let i = 0; i <= $from.depth; i++) {
1385            let node = $from.node(i);
1386            this.frontier.push({
1387                type: node.type,
1388                match: node.contentMatchAt($from.indexAfter(i))
1389            });
1390        }
1391        for (let i = $from.depth; i > 0; i--)
1392            this.placed = Fragment.from($from.node(i).copy(this.placed));
1393    }
1394    get depth() { return this.frontier.length - 1; }
1395    fit() {
1396        // As long as there's unplaced content, try to place some of it.
1397        // If that fails, either increase the open score of the unplaced
1398        // slice, or drop nodes from it, and then try again.
1399        while (this.unplaced.size) {
1400            let fit = this.findFittable();
1401            if (fit)
1402                this.placeNodes(fit);
1403            else
1404                this.openMore() || this.dropNode();
1405        }
1406        // When there's inline content directly after the frontier _and_
1407        // directly after `this.$to`, we must generate a `ReplaceAround`
1408        // step that pulls that content into the node after the frontier.
1409        // That means the fitting must be done to the end of the textblock
1410        // node after `this.$to`, not `this.$to` itself.
1411        let moveInline = this.mustMoveInline(), placedSize = this.placed.size - this.depth - this.$from.depth;
1412        let $from = this.$from, $to = this.close(moveInline < 0 ? this.$to : $from.doc.resolve(moveInline));
1413        if (!$to)
1414            return null;
1415        // If closing to `$to` succeeded, create a step
1416        let content = this.placed, openStart = $from.depth, openEnd = $to.depth;
1417        while (openStart && openEnd && content.childCount == 1) { // Normalize by dropping open parent nodes
1418            content = content.firstChild.content;
1419            openStart--;
1420            openEnd--;
1421        }
1422        let slice = new Slice(content, openStart, openEnd);
1423        if (moveInline > -1)
1424            return new ReplaceAroundStep($from.pos, moveInline, this.$to.pos, this.$to.end(), slice, placedSize);
1425        if (slice.size || $from.pos != this.$to.pos) // Don't generate no-op steps
1426            return new ReplaceStep($from.pos, $to.pos, slice);
1427        return null;
1428    }
1429    // Find a position on the start spine of `this.unplaced` that has
1430    // content that can be moved somewhere on the frontier. Returns two
1431    // depths, one for the slice and one for the frontier.
1432    findFittable() {
1433        let startDepth = this.unplaced.openStart;
1434        for (let cur = this.unplaced.content, d = 0, openEnd = this.unplaced.openEnd; d < startDepth; d++) {
1435            let node = cur.firstChild;
1436            if (cur.childCount > 1)
1437                openEnd = 0;
1438            if (node.type.spec.isolating && openEnd <= d) {
1439                startDepth = d;
1440                break;
1441            }
1442            cur = node.content;
1443        }
1444        // Only try wrapping nodes (pass 2) after finding a place without
1445        // wrapping failed.
1446        for (let pass = 1; pass <= 2; pass++) {
1447            for (let sliceDepth = pass == 1 ? startDepth : this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) {
1448                let fragment, parent = null;
1449                if (sliceDepth) {
1450                    parent = contentAt(this.unplaced.content, sliceDepth - 1).firstChild;
1451                    fragment = parent.content;
1452                }
1453                else {
1454                    fragment = this.unplaced.content;
1455                }
1456                let first = fragment.firstChild;
1457                for (let frontierDepth = this.depth; frontierDepth >= 0; frontierDepth--) {
1458                    let { type, match } = this.frontier[frontierDepth], wrap, inject = null;
1459                    // In pass 1, if the next node matches, or there is no next
1460                    // node but the parents look compatible, we've found a
1461                    // place.
1462                    if (pass == 1 && (first ? match.matchType(first.type) || (inject = match.fillBefore(Fragment.from(first), false))
1463                        : parent && type.compatibleContent(parent.type)))
1464                        return { sliceDepth, frontierDepth, parent, inject };
1465                    // In pass 2, look for a set of wrapping nodes that make
1466                    // `first` fit here.
1467                    else if (pass == 2 && first && (wrap = match.findWrapping(first.type)))
1468                        return { sliceDepth, frontierDepth, parent, wrap };
1469                    // Don't continue looking further up if the parent node
1470                    // would fit here.
1471                    if (parent && match.matchType(parent.type))
1472                        break;
1473                }
1474            }
1475        }
1476    }
1477    openMore() {
1478        let { content, openStart, openEnd } = this.unplaced;
1479        let inner = contentAt(content, openStart);
1480        if (!inner.childCount || inner.firstChild.isLeaf)
1481            return false;
1482        this.unplaced = new Slice(content, openStart + 1, Math.max(openEnd, inner.size + openStart >= content.size - openEnd ? openStart + 1 : 0));
1483        return true;
1484    }
1485    dropNode() {
1486        let { content, openStart, openEnd } = this.unplaced;
1487        let inner = contentAt(content, openStart);
1488        if (inner.childCount <= 1 && openStart > 0) {
1489            let openAtEnd = content.size - openStart <= openStart + inner.size;
1490            this.unplaced = new Slice(dropFromFragment(content, openStart - 1, 1), openStart - 1, openAtEnd ? openStart - 1 : openEnd);
1491        }
1492        else {
1493            this.unplaced = new Slice(dropFromFragment(content, openStart, 1), openStart, openEnd);
1494        }
1495    }
1496    // Move content from the unplaced slice at `sliceDepth` to the
1497    // frontier node at `frontierDepth`. Close that frontier node when
1498    // applicable.
1499    placeNodes({ sliceDepth, frontierDepth, parent, inject, wrap }) {
1500        while (this.depth > frontierDepth)
1501            this.closeFrontierNode();
1502        if (wrap)
1503            for (let i = 0; i < wrap.length; i++)
1504                this.openFrontierNode(wrap[i]);
1505        let slice = this.unplaced, fragment = parent ? parent.content : slice.content;
1506        let openStart = slice.openStart - sliceDepth;
1507        let taken = 0, add = [];
1508        let { match, type } = this.frontier[frontierDepth];
1509        if (inject) {
1510            for (let i = 0; i < inject.childCount; i++)
1511                add.push(inject.child(i));
1512            match = match.matchFragment(inject);
1513        }
1514        // Computes the amount of (end) open nodes at the end of the
1515        // fragment. When 0, the parent is open, but no more. When
1516        // negative, nothing is open.
1517        let openEndCount = (fragment.size + sliceDepth) - (slice.content.size - slice.openEnd);
1518        // Scan over the fragment, fitting as many child nodes as
1519        // possible.
1520        while (taken < fragment.childCount) {
1521            let next = fragment.child(taken), matches = match.matchType(next.type);
1522            if (!matches)
1523                break;
1524            taken++;
1525            if (taken > 1 || openStart == 0 || next.content.size) { // Drop empty open nodes
1526                match = matches;
1527                add.push(closeNodeStart(next.mark(type.allowedMarks(next.marks)), taken == 1 ? openStart : 0, taken == fragment.childCount ? openEndCount : -1));
1528            }
1529        }
1530        let toEnd = taken == fragment.childCount;
1531        if (!toEnd)
1532            openEndCount = -1;
1533        this.placed = addToFragment(this.placed, frontierDepth, Fragment.from(add));
1534        this.frontier[frontierDepth].match = match;
1535        // If the parent types match, and the entire node was moved, and
1536        // it's not open, close this frontier node right away.
1537        if (toEnd && openEndCount < 0 && parent && parent.type == this.frontier[this.depth].type && this.frontier.length > 1)
1538            this.closeFrontierNode();
1539        // Add new frontier nodes for any open nodes at the end.
1540        for (let i = 0, cur = fragment; i < openEndCount; i++) {
1541            let node = cur.lastChild;
1542            this.frontier.push({ type: node.type, match: node.contentMatchAt(node.childCount) });
1543            cur = node.content;
1544        }
1545        // Update `this.unplaced`. Drop the entire node from which we
1546        // placed it we got to its end, otherwise just drop the placed
1547        // nodes.
1548        this.unplaced = !toEnd ? new Slice(dropFromFragment(slice.content, sliceDepth, taken), slice.openStart, slice.openEnd)
1549            : sliceDepth == 0 ? Slice.empty
1550                : new Slice(dropFromFragment(slice.content, sliceDepth - 1, 1), sliceDepth - 1, openEndCount < 0 ? slice.openEnd : sliceDepth - 1);
1551    }
1552    mustMoveInline() {
1553        if (!this.$to.parent.isTextblock)
1554            return -1;
1555        let top = this.frontier[this.depth], level;
1556        if (!top.type.isTextblock || !contentAfterFits(this.$to, this.$to.depth, top.type, top.match, false) ||
1557            (this.$to.depth == this.depth && (level = this.findCloseLevel(this.$to)) && level.depth == this.depth))
1558            return -1;
1559        let { depth } = this.$to, after = this.$to.after(depth);
1560        while (depth > 1 && after == this.$to.end(--depth))
1561            ++after;
1562        return after;
1563    }
1564    findCloseLevel($to) {
1565        scan: for (let i = Math.min(this.depth, $to.depth); i >= 0; i--) {
1566            let { match, type }
vendor: 3,377 bytes, lines 1566-1642
1566 = this.frontier[i];
1567            let dropInner = i < $to.depth && $to.end(i + 1) == $to.pos + ($to.depth - (i + 1));
1568            let fit = contentAfterFits($to, i, type, match, dropInner);
1569            if (!fit)
1570                continue;
1571            for (let d = i - 1; d >= 0; d--) {
1572                let { match, type } = this.frontier[d];
1573                let matches = contentAfterFits($to, d, type, match, true);
1574                if (!matches || matches.childCount)
1575                    continue scan;
1576            }
1577            return { depth: i, fit, move: dropInner ? $to.doc.resolve($to.after(i + 1)) : $to };
1578        }
1579    }
1580    close($to) {
1581        let close = this.findCloseLevel($to);
1582        if (!close)
1583            return null;
1584        while (this.depth > close.depth)
1585            this.closeFrontierNode();
1586        if (close.fit.childCount)
1587            this.placed = addToFragment(this.placed, close.depth, close.fit);
1588        $to = close.move;
1589        for (let d = close.depth + 1; d <= $to.depth; d++) {
1590            let node = $to.node(d), add = node.type.contentMatch.fillBefore(node.content, true, $to.index(d));
1591            this.openFrontierNode(node.type, node.attrs, add);
1592        }
1593        return $to;
1594    }
1595    openFrontierNode(type, attrs = null, content) {
1596        let top = this.frontier[this.depth];
1597        top.match = top.match.matchType(type);
1598        this.placed = addToFragment(this.placed, this.depth, Fragment.from(type.create(attrs, content)));
1599        this.frontier.push({ type, match: type.contentMatch });
1600    }
1601    closeFrontierNode() {
1602        let open = this.frontier.pop();
1603        let add = open.match.fillBefore(Fragment.empty, true);
1604        if (add.childCount)
1605            this.placed = addToFragment(this.placed, this.frontier.length, add);
1606    }
1607}
1608function dropFromFragment(fragment, depth, count) {
1609    if (depth == 0)
1610        return fragment.cutByIndex(count, fragment.childCount);
1611    return fragment.replaceChild(0, fragment.firstChild.copy(dropFromFragment(fragment.firstChild.content, depth - 1, count)));
1612}
1613function addToFragment(fragment, depth, content) {
1614    if (depth == 0)
1615        return fragment.append(content);
1616    return fragment.replaceChild(fragment.childCount - 1, fragment.lastChild.copy(addToFragment(fragment.lastChild.content, depth - 1, content)));
1617}
1618function contentAt(fragment, depth) {
1619    for (let i = 0; i < depth; i++)
1620        fragment = fragment.firstChild.content;
1621    return fragment;
1622}
1623function closeNodeStart(node, openStart, openEnd) {
1624    if (openStart <= 0)
1625        return node;
1626    let frag = node.content;
1627    if (openStart > 1)
1628        frag = frag.replaceChild(0, closeNodeStart(frag.firstChild, openStart - 1, frag.childCount == 1 ? openEnd - 1 : 0));
1629    if (openStart > 0) {
1630        frag = node.type.contentMatch.fillBefore(frag).append(frag);
1631        if (openEnd <= 0)
1632            frag = frag.append(node.type.contentMatch.matchFragment(frag).fillBefore(Fragment.empty, true));
1633    }
1634    return node.copy(frag);
1635}
1636function contentAfterFits($to, depth, type, match, open) {
1637    let node = $to.node(depth), index = open ? $to.indexAfter(depth) : $to.index(depth);
1638    if (index == node.childCount && !type.compatibleContent(node.type))
1639        return null;
1640    let fit = match.fillBefore(node.content, true, index);
1641    return fit && !invalidMarks(type, node.content, index) ? fit : null;
1642}
vendor: 4,135 bytes, lines 1643-1734
1643function invalidMarks(type, fragment, start) {
1644    for (let i = start; i < fragment.childCount; i++)
1645        if (!type.allowsMarks(fragment.child(i).marks))
1646            return true;
1647    return false;
1648}
1649function definesContent(type) {
1650    return type.spec.defining || type.spec.definingForContent;
1651}
1652function replaceRange(tr, from, to, slice) {
1653    if (!slice.size)
1654        return tr.deleteRange(from, to);
1655    let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
1656    if (fitsTrivially($from, $to, slice))
1657        return tr.step(new ReplaceStep(from, to, slice));
1658    let targetDepths = coveredDepths($from, $to);
1659    // Can't replace the whole document, so remove 0 if it's present
1660    if (targetDepths[targetDepths.length - 1] == 0)
1661        targetDepths.pop();
1662    // Negative numbers represent not expansion over the whole node at
1663    // that depth, but replacing from $from.before(-D) to $to.pos.
1664    let preferredTarget = -($from.depth + 1);
1665    targetDepths.unshift(preferredTarget);
1666    // This loop picks a preferred target depth, if one of the covering
1667    // depths is not outside of a defining node, and adds negative
1668    // depths for any depth that has $from at its start and does not
1669    // cross a defining node.
1670    for (let d = $from.depth, pos = $from.pos - 1; d > 0; d--, pos--) {
1671        let spec = $from.node(d).type.spec;
1672        if (spec.defining || spec.definingAsContext || spec.isolating)
1673            break;
1674        if (targetDepths.indexOf(d) > -1)
1675            preferredTarget = d;
1676        else if ($from.before(d) == pos)
1677            targetDepths.splice(1, 0, -d);
1678    }
1679    // Try to fit each possible depth of the slice into each possible
1680    // target depth, starting with the preferred depths.
1681    let preferredTargetIndex = targetDepths.indexOf(preferredTarget);
1682    let leftNodes = [], preferredDepth = slice.openStart;
1683    for (let content = slice.content, i = 0;; i++) {
1684        let node = content.firstChild;
1685        leftNodes.push(node);
1686        if (i == slice.openStart)
1687            break;
1688        content = node.content;
1689    }
1690    // Back up preferredDepth to cover defining textblocks directly
1691    // above it, possibly skipping a non-defining textblock.
1692    for (let d = preferredDepth - 1; d >= 0; d--) {
1693        let leftNode = leftNodes[d], def = definesContent(leftNode.type);
1694        if (def && !leftNode.sameMarkup($from.node(Math.abs(preferredTarget) - 1)))
1695            preferredDepth = d;
1696        else if (def || !leftNode.type.isTextblock)
1697            break;
1698    }
1699    for (let j = slice.openStart; j >= 0; j--) {
1700        let openDepth = (j + preferredDepth + 1) % (slice.openStart + 1);
1701        let insert = leftNodes[openDepth];
1702        if (!insert)
1703            continue;
1704        for (let i = 0; i < targetDepths.length; i++) {
1705            // Loop over possible expansion levels, starting with the
1706            // preferred one
1707            let targetDepth = targetDepths[(i + preferredTargetIndex) % targetDepths.length], expand = true;
1708            if (targetDepth < 0) {
1709                expand = false;
1710                targetDepth = -targetDepth;
1711            }
1712            let parent = $from.node(targetDepth - 1), index = $from.index(targetDepth - 1);
1713            if (parent.canReplaceWith(index, index, insert.type, insert.marks))
1714                return tr.replace($from.before(targetDepth), expand ? $to.after(targetDepth) : to, new Slice(closeFragment(slice.content, 0, slice.openStart, openDepth), openDepth, slice.openEnd));
1715        }
1716    }
1717    let startSteps = tr.steps.length;
1718    for (let i = targetDepths.length - 1; i >= 0; i--) {
1719        tr.replace(from, to, slice);
1720        if (tr.steps.length > startSteps)
1721            break;
1722        let depth = targetDepths[i];
1723        if (depth < 0)
1724            continue;
1725        from = $from.before(depth);
1726        to = $to.after(depth);
1727    }
1728}
1729function closeFragment(fragment, depth, oldOpen, newOpen, parent) {
1730    if (depth < oldOpen) {
1731        let first = fragment.firstChild;
1732        fragment = fragment.replaceChild(0, first.copy(closeFragment(first.content, depth + 1, oldOpen, newOpen, first)));
1733    }
1734    if (depth >
vendor: 16,649 bytes, lines 1734-2213
1734 newOpen) {
1735        let match = parent.contentMatchAt(0);
1736        let start = match.fillBefore(fragment).append(fragment);
1737        fragment = start.append(match.matchFragment(start).fillBefore(Fragment.empty, true));
1738    }
1739    return fragment;
1740}
1741function replaceRangeWith(tr, from, to, node) {
1742    if (!node.isInline && from == to && tr.doc.resolve(from).parent.content.size) {
1743        let point = insertPoint(tr.doc, from, node.type);
1744        if (point != null)
1745            from = to = point;
1746    }
1747    tr.replaceRange(from, to, new Slice(Fragment.from(node), 0, 0));
1748}
1749function deleteRange(tr, from, to) {
1750    let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
1751    // When the deleted range spans from the start of one textblock to
1752    // the start of another one, move out of the start of both blocks.
1753    if ($from.parent.isTextblock && $to.parent.isTextblock && $from.start() != $to.start() &&
1754        $from.parentOffset == 0 && $to.parentOffset == 0) {
1755        let shared = $from.sharedDepth(to), isolated = false;
1756        for (let d = $from.depth; d > shared; d--)
1757            if ($from.node(d).type.spec.isolating)
1758                isolated = true;
1759        for (let d = $to.depth; d > shared; d--)
1760            if ($to.node(d).type.spec.isolating)
1761                isolated = true;
1762        if (!isolated) {
1763            for (let d = $from.depth; d > 0 && from == $from.start(d); d--)
1764                from = $from.before(d);
1765            for (let d = $to.depth; d > 0 && to == $to.start(d); d--)
1766                to = $to.before(d);
1767            $from = tr.doc.resolve(from);
1768            $to = tr.doc.resolve(to);
1769        }
1770    }
1771    let covered = coveredDepths($from, $to);
1772    for (let i = 0; i < covered.length; i++) {
1773        let depth = covered[i], last = i == covered.length - 1;
1774        if ((last && depth == 0) || $from.node(depth).type.contentMatch.validEnd)
1775            return tr.delete($from.start(depth), $to.end(depth));
1776        if (depth > 0 && (last || $from.node(depth - 1).canReplace($from.index(depth - 1), $to.indexAfter(depth - 1))))
1777            return tr.delete($from.before(depth), $to.after(depth));
1778    }
1779    for (let d = 1; d <= $from.depth && d <= $to.depth; d++) {
1780        if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d &&
1781            $from.start(d - 1) == $to.start(d - 1) && $from.node(d - 1).canReplace($from.index(d - 1), $to.index(d - 1)))
1782            return tr.delete($from.before(d), to);
1783    }
1784    tr.delete(from, to);
1785}
1786// Returns an array of all depths for which $from - $to spans the
1787// whole content of the nodes at that depth.
1788function coveredDepths($from, $to) {
1789    let result = [], minDepth = Math.min($from.depth, $to.depth);
1790    for (let d = minDepth; d >= 0; d--) {
1791        let start = $from.start(d);
1792        if (start < $from.pos - ($from.depth - d) ||
1793            $to.end(d) > $to.pos + ($to.depth - d) ||
1794            $from.node(d).type.spec.isolating ||
1795            $to.node(d).type.spec.isolating)
1796            break;
1797        if (start == $to.start(d) ||
1798            (d == $from.depth && d == $to.depth && $from.parent.inlineContent && $to.parent.inlineContent &&
1799                d && $to.start(d - 1) == start - 1))
1800            result.push(d);
1801    }
1802    return result;
1803}
1804
1805/**
1806Update an attribute in a specific node.
1807*/
1808class AttrStep extends Step {
1809    /**
1810    Construct an attribute step.
1811    */
1812    constructor(
1813    /**
1814    The position of the target node.
1815    */
1816    pos, 
1817    /**
1818    The attribute to set.
1819    */
1820    attr, 
1821    // The attribute's new value.
1822    value) {
1823        super();
1824        this.pos = pos;
1825        this.attr = attr;
1826        this.value = value;
1827    }
1828    apply(doc) {
1829        let node = doc.nodeAt(this.pos);
1830        if (!node)
1831            return StepResult.fail("No node at attribute step's position");
1832        let attrs = Object.create(null);
1833        for (let name in node.attrs)
1834            attrs[name] = node.attrs[name];
1835        attrs[this.attr] = this.value;
1836        let updated = node.type.create(attrs, null, node.marks);
1837        return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
1838    }
1839    getMap() {
1840        return StepMap.empty;
1841    }
1842    invert(doc) {
1843        return new AttrStep(this.pos, this.attr, doc.nodeAt(this.pos).attrs[this.attr]);
1844    }
1845    map(mapping) {
1846        let pos = mapping.mapResult(this.pos, 1);
1847        return pos.deletedAfter ? null : new AttrStep(pos.pos, this.attr, this.value);
1848    }
1849    toJSON() {
1850        return { stepType: "attr", pos: this.pos, attr: this.attr, value: this.value };
1851    }
1852    static fromJSON(schema, json) {
1853        if (typeof json.pos != "number" || typeof json.attr != "string")
1854            throw new RangeError("Invalid input for AttrStep.fromJSON");
1855        return new AttrStep(json.pos, json.attr, json.value);
1856    }
1857}
1858Step.jsonID("attr", AttrStep);
1859/**
1860Update an attribute in the doc node.
1861*/
1862class DocAttrStep extends Step {
1863    /**
1864    Construct an attribute step.
1865    */
1866    constructor(
1867    /**
1868    The attribute to set.
1869    */
1870    attr, 
1871    // The attribute's new value.
1872    value) {
1873        super();
1874        this.attr = attr;
1875        this.value = value;
1876    }
1877    apply(doc) {
1878        let attrs = Object.create(null);
1879        for (let name in doc.attrs)
1880            attrs[name] = doc.attrs[name];
1881        attrs[this.attr] = this.value;
1882        let updated = doc.type.create(attrs, doc.content, doc.marks);
1883        return StepResult.ok(updated);
1884    }
1885    getMap() {
1886        return StepMap.empty;
1887    }
1888    invert(doc) {
1889        return new DocAttrStep(this.attr, doc.attrs[this.attr]);
1890    }
1891    map(mapping) {
1892        return this;
1893    }
1894    toJSON() {
1895        return { stepType: "docAttr", attr: this.attr, value: this.value };
1896    }
1897    static fromJSON(schema, json) {
1898        if (typeof json.attr != "string")
1899            throw new RangeError("Invalid input for DocAttrStep.fromJSON");
1900        return new DocAttrStep(json.attr, json.value);
1901    }
1902}
1903Step.jsonID("docAttr", DocAttrStep);
1904
1905/**
1906@internal
1907*/
1908let TransformError = class extends Error {
1909};
1910TransformError = function TransformError(message) {
1911    let err = Error.call(this, message);
1912    err.__proto__ = TransformError.prototype;
1913    return err;
1914};
1915TransformError.prototype = Object.create(Error.prototype);
1916TransformError.prototype.constructor = TransformError;
1917TransformError.prototype.name = "TransformError";
1918/**
1919Abstraction to build up and track an array of
1920[steps](https://prosemirror.net/docs/ref/#transform.Step) representing a document transformation.
1921
1922Most transforming methods return the `Transform` object itself, so
1923that they can be chained.
1924*/
1925class Transform {
1926    /**
1927    Create a transform that starts with the given document.
1928    */
1929    constructor(
1930    /**
1931    The current document (the result of applying the steps in the
1932    transform).
1933    */
1934    doc) {
1935        this.doc = doc;
1936        /**
1937        The steps in this transform.
1938        */
1939        this.steps = [];
1940        /**
1941        The documents before each of the steps.
1942        */
1943        this.docs = [];
1944        /**
1945        A mapping with the maps for each of the steps in this transform.
1946        */
1947        this.mapping = new Mapping;
1948    }
1949    /**
1950    The starting document.
1951    */
1952    get before() { return this.docs.length ? this.docs[0] : this.doc; }
1953    /**
1954    Apply a new step in this transform, saving the result. Throws an
1955    error when the step fails.
1956    */
1957    step(step) {
1958        let result = this.maybeStep(step);
1959        if (result.failed)
1960            throw new TransformError(result.failed);
1961        return this;
1962    }
1963    /**
1964    Try to apply a step in this transformation, ignoring it if it
1965    fails. Returns the step result.
1966    */
1967    maybeStep(step) {
1968        let result = step.apply(this.doc);
1969        if (!result.failed)
1970            this.addStep(step, result.doc);
1971        return result;
1972    }
1973    /**
1974    True when the document has been changed (when there are any
1975    steps).
1976    */
1977    get docChanged() {
1978        return this.steps.length > 0;
1979    }
1980    /**
1981    Return a single range, in post-transform document positions,
1982    that covers all content changed by this transform. Returns null
1983    if no replacements are made. Note that this will ignore changes
1984    that add/remove marks without replacing the underlying content.
1985    */
1986    changedRange() {
1987        let from = 1e9, to = -1e9;
1988        for (let i = 0; i < this.mapping.maps.length; i++) {
1989            let map = this.mapping.maps[i];
1990            if (i) {
1991                from = map.map(from, 1);
1992                to = map.map(to, -1);
1993            }
1994            map.forEach((_f, _t, fromB, toB) => {
1995                from = Math.min(from, fromB);
1996                to = Math.max(to, toB);
1997            });
1998        }
1999        return from == 1e9 ? null : { from, to };
2000    }
2001    /**
2002    @internal
2003    */
2004    addStep(step, doc) {
2005        this.docs.push(this.doc);
2006        this.steps.push(step);
2007        this.mapping.appendMap(step.getMap());
2008        this.doc = doc;
2009    }
2010    /**
2011    Replace the part of the document between `from` and `to` with the
2012    given `slice`.
2013    */
2014    replace(from, to = from, slice = Slice.empty) {
2015        let step = replaceStep(this.doc, from, to, slice);
2016        if (step)
2017            this.step(step);
2018        return this;
2019    }
2020    /**
2021    Replace the given range with the given content, which may be a
2022    fragment, node, or array of nodes.
2023    */
2024    replaceWith(from, to, content) {
2025        return this.replace(from, to, new Slice(Fragment.from(content), 0, 0));
2026    }
2027    /**
2028    Delete the content between the given positions.
2029    */
2030    delete(from, to) {
2031        return this.replace(from, to, Slice.empty);
2032    }
2033    /**
2034    Insert the given content at the given position.
2035    */
2036    insert(pos, content) {
2037        return this.replaceWith(pos, pos, content);
2038    }
2039    /**
2040    Replace a range of the document with a given slice, using
2041    `from`, `to`, and the slice's
2042    [`openStart`](https://prosemirror.net/docs/ref/#model.Slice.openStart) property as hints, rather
2043    than fixed start and end points. This method may grow the
2044    replaced area or close open nodes in the slice in order to get a
2045    fit that is more in line with WYSIWYG expectations, by dropping
2046    fully covered parent nodes of the replaced region when they are
2047    marked [non-defining as
2048    context](https://prosemirror.net/docs/ref/#model.NodeSpec.definingAsContext), or including an
2049    open parent node from the slice that _is_ marked as [defining
2050    its content](https://prosemirror.net/docs/ref/#model.NodeSpec.definingForContent).
2051    
2052    This is the method, for example, to handle paste. The similar
2053    [`replace`](https://prosemirror.net/docs/ref/#transform.Transform.replace) method is a more
2054    primitive tool which will _not_ move the start and end of its given
2055    range, and is useful in situations where you need more precise
2056    control over what happens.
2057    */
2058    replaceRange(from, to, slice) {
2059        replaceRange(this, from, to, slice);
2060        return this;
2061    }
2062    /**
2063    Replace the given range with a node, but use `from` and `to` as
2064    hints, rather than precise positions. When from and to are the same
2065    and are at the start or end of a parent node in which the given
2066    node doesn't fit, this method may _move_ them out towards a parent
2067    that does allow the given node to be placed. When the given range
2068    completely covers a parent node, this method may completely replace
2069    that parent node.
2070    */
2071    replaceRangeWith(from, to, node) {
2072        replaceRangeWith(this, from, to, node);
2073        return this;
2074    }
2075    /**
2076    Delete the given range, expanding it to cover fully covered
2077    parent nodes until a valid replace is found.
2078    */
2079    deleteRange(from, to) {
2080        deleteRange(this, from, to);
2081        return this;
2082    }
2083    /**
2084    Split the content in the given range off from its parent, if there
2085    is sibling content before or after it, and move it up the tree to
2086    the depth specified by `target`. You'll probably want to use
2087    [`liftTarget`](https://prosemirror.net/docs/ref/#transform.liftTarget) to compute `target`, to make
2088    sure the lift is valid.
2089    */
2090    lift(range, target) {
2091        lift(this, range, target);
2092        return this;
2093    }
2094    /**
2095    Join the blocks around the given position. If depth is 2, their
2096    last and first siblings are also joined, and so on.
2097    */
2098    join(pos, depth = 1) {
2099        join(this, pos, depth);
2100        return this;
2101    }
2102    /**
2103    Wrap the given [range](https://prosemirror.net/docs/ref/#model.NodeRange) in the given set of wrappers.
2104    The wrappers are assumed to be valid in this position, and should
2105    probably be computed with [`findWrapping`](https://prosemirror.net/docs/ref/#transform.findWrapping).
2106    */
2107    wrap(range, wrappers) {
2108        wrap(this, range, wrappers);
2109        return this;
2110    }
2111    /**
2112    Set the type of all textblocks (partly) between `from` and `to` to
2113    the given node type with the given attributes.
2114    */
2115    setBlockType(from, to = from, type, attrs = null) {
2116        setBlockType(this, from, to, type, attrs);
2117        return this;
2118    }
2119    /**
2120    Change the type, attributes, and/or marks of the node at `pos`.
2121    When `type` isn't given, the existing node type is preserved,
2122    */
2123    setNodeMarkup(pos, type, attrs = null, marks) {
2124        setNodeMarkup(this, pos, type, attrs, marks);
2125        return this;
2126    }
2127    /**
2128    Set a single attribute on a given node to a new value.
2129    The `pos` addresses the document content. Use `setDocAttribute`
2130    to set attributes on the document itself.
2131    */
2132    setNodeAttribute(pos, attr, value) {
2133        this.step(new AttrStep(pos, attr, value));
2134        return this;
2135    }
2136    /**
2137    Set a single attribute on the document to a new value.
2138    */
2139    setDocAttribute(attr, value) {
2140        this.step(new DocAttrStep(attr, value));
2141        return this;
2142    }
2143    /**
2144    Add a mark to the node at position `pos`.
2145    */
2146    addNodeMark(pos, mark) {
2147        this.step(new AddNodeMarkStep(pos, mark));
2148        return this;
2149    }
2150    /**
2151    Remove a mark (or all marks of the given type) from the node at
2152    position `pos`.
2153    */
2154    removeNodeMark(pos, mark) {
2155        let node = this.doc.nodeAt(pos);
2156        if (!node)
2157            throw new RangeError("No node at position " + pos);
2158        if (mark instanceof Mark) {
2159            if (mark.isInSet(node.marks))
2160                this.step(new RemoveNodeMarkStep(pos, mark));
2161        }
2162        else {
2163            let set = node.marks, found, steps = [];
2164            while (found = mark.isInSet(set)) {
2165                steps.push(new RemoveNodeMarkStep(pos, found));
2166                set = found.removeFromSet(set);
2167            }
2168            for (let i = steps.length - 1; i >= 0; i--)
2169                this.step(steps[i]);
2170        }
2171        return this;
2172    }
2173    /**
2174    Split the node at the given position, and optionally, if `depth` is
2175    greater than one, any number of nodes above that. By default, the
2176    parts split off will inherit the node type of the original node.
2177    This can be changed by passing an array of types and attributes to
2178    use after the split (with the outermost nodes coming first).
2179    */
2180    split(pos, depth = 1, typesAfter) {
2181        split(this, pos, depth, typesAfter);
2182        return this;
2183    }
2184    /**
2185    Add the given mark to the inline content between `from` and `to`.
2186    */
2187    addMark(from, to, mark) {
2188        addMark(this, from, to, mark);
2189        return this;
2190    }
2191    /**
2192    Remove marks from inline nodes between `from` and `to`. When
2193    `mark` is a single mark, remove precisely that mark. When it is
2194    a mark type, remove all marks of that type. When it is null,
2195    remove all marks of any type.
2196    */
2197    removeMark(from, to, mark) {
2198        removeMark(this, from, to, mark);
2199        return this;
2200    }
2201    /**
2202    Removes all marks and nodes from the content of the node at
2203    `pos` that don't match the given new parent node type. Accepts
2204    an optional starting [content match](https://prosemirror.net/docs/ref/#model.ContentMatch) as
2205    third argument.
2206    */
2207    clearIncompatible(pos, parentType, match) {
2208        clearIncompatible(this, pos, parentType, match);
2209        return this;
2210    }
2211}
2212
2213export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, TransformError, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.