prosemirror-transform 1.4.0 → 1.5.0-beta.1

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