UNPKG

73.6 kBJavaScriptView Raw
1import { Text } from '@codemirror/text';
2export { Text } from '@codemirror/text';
3
4const DefaultSplit = /\r\n?|\n/;
5/// Distinguishes different ways in which positions can be mapped.
6var MapMode;
7(function (MapMode) {
8 /// Map a position to a valid new position, even when its context
9 /// was deleted.
10 MapMode[MapMode["Simple"] = 0] = "Simple";
11 /// Return null if deletion happens across the position.
12 MapMode[MapMode["TrackDel"] = 1] = "TrackDel";
13 /// Return null if the character _before_ the position is deleted.
14 MapMode[MapMode["TrackBefore"] = 2] = "TrackBefore";
15 /// Return null if the character _after_ the position is deleted.
16 MapMode[MapMode["TrackAfter"] = 3] = "TrackAfter";
17})(MapMode || (MapMode = {}));
18/// A change description is a variant of [change set](#state.ChangeSet)
19/// that doesn't store the inserted text. As such, it can't be
20/// applied, but is cheaper to store and manipulate.
21class ChangeDesc {
22 // Sections are encoded as pairs of integers. The first is the
23 // length in the current document, and the second is -1 for
24 // unaffected sections, and the length of the replacement content
25 // otherwise. So an insertion would be (0, n>0), a deletion (n>0,
26 // 0), and a replacement two positive numbers.
27 /// @internal
28 constructor(
29 /// @internal
30 sections) {
31 this.sections = sections;
32 }
33 /// The length of the document before the change.
34 get length() {
35 let result = 0;
36 for (let i = 0; i < this.sections.length; i += 2)
37 result += this.sections[i];
38 return result;
39 }
40 /// The length of the document after the change.
41 get newLength() {
42 let result = 0;
43 for (let i = 0; i < this.sections.length; i += 2) {
44 let ins = this.sections[i + 1];
45 result += ins < 0 ? this.sections[i] : ins;
46 }
47 return result;
48 }
49 /// False when there are actual changes in this set.
50 get empty() { return this.sections.length == 0 || this.sections.length == 2 && this.sections[1] < 0; }
51 /// Iterate over the unchanged parts left by these changes.
52 iterGaps(f) {
53 for (let i = 0, posA = 0, posB = 0; i < this.sections.length;) {
54 let len = this.sections[i++], ins = this.sections[i++];
55 if (ins < 0) {
56 f(posA, posB, len);
57 posB += len;
58 }
59 else {
60 posB += ins;
61 }
62 posA += len;
63 }
64 }
65 /// Iterate over the ranges changed by these changes. (See
66 /// [`ChangeSet.iterChanges`](#state.ChangeSet.iterChanges) for a
67 /// variant that also provides you with the inserted text.)
68 ///
69 /// When `individual` is true, adjacent changes (which are kept
70 /// separate for [position mapping](#state.ChangeDesc.mapPos)) are
71 /// reported separately.
72 iterChangedRanges(f, individual = false) {
73 iterChanges(this, f, individual);
74 }
75 /// Get a description of the inverted form of these changes.
76 get invertedDesc() {
77 let sections = [];
78 for (let i = 0; i < this.sections.length;) {
79 let len = this.sections[i++], ins = this.sections[i++];
80 if (ins < 0)
81 sections.push(len, ins);
82 else
83 sections.push(ins, len);
84 }
85 return new ChangeDesc(sections);
86 }
87 /// Compute the combined effect of applying another set of changes
88 /// after this one. The length of the document after this set should
89 /// match the length before `other`.
90 composeDesc(other) { return this.empty ? other : other.empty ? this : composeSets(this, other); }
91 /// Map this description, which should start with the same document
92 /// as `other`, over another set of changes, so that it can be
93 /// applied after it. When `before` is true, map as if the changes
94 /// in `other` happened before the ones in `this`.
95 mapDesc(other, before = false) { return other.empty ? this : mapSet(this, other, before); }
96 mapPos(pos, assoc = -1, mode = MapMode.Simple) {
97 let posA = 0, posB = 0;
98 for (let i = 0; i < this.sections.length;) {
99 let len = this.sections[i++], ins = this.sections[i++], endA = posA + len;
100 if (ins < 0) {
101 if (endA > pos)
102 return posB + (pos - posA);
103 posB += len;
104 }
105 else {
106 if (mode != MapMode.Simple && endA >= pos &&
107 (mode == MapMode.TrackDel && posA < pos && endA > pos ||
108 mode == MapMode.TrackBefore && posA < pos ||
109 mode == MapMode.TrackAfter && endA > pos))
110 return null;
111 if (endA > pos || endA == pos && assoc < 0 && !len)
112 return pos == posA || assoc < 0 ? posB : posB + ins;
113 posB += ins;
114 }
115 posA = endA;
116 }
117 if (pos > posA)
118 throw new RangeError(`Position ${pos} is out of range for changeset of length ${posA}`);
119 return posB;
120 }
121 /// Check whether these changes touch a given range. When one of the
122 /// changes entirely covers the range, the string `"cover"` is
123 /// returned.
124 touchesRange(from, to = from) {
125 for (let i = 0, pos = 0; i < this.sections.length && pos <= to;) {
126 let len = this.sections[i++], ins = this.sections[i++], end = pos + len;
127 if (ins >= 0 && pos <= to && end >= from)
128 return pos < from && end > to ? "cover" : true;
129 pos = end;
130 }
131 return false;
132 }
133 /// @internal
134 toString() {
135 let result = "";
136 for (let i = 0; i < this.sections.length;) {
137 let len = this.sections[i++], ins = this.sections[i++];
138 result += (result ? " " : "") + len + (ins >= 0 ? ":" + ins : "");
139 }
140 return result;
141 }
142}
143/// A change set represents a group of modifications to a document. It
144/// stores the document length, and can only be applied to documents
145/// with exactly that length.
146class ChangeSet extends ChangeDesc {
147 /// @internal
148 constructor(sections,
149 /// @internal
150 inserted) {
151 super(sections);
152 this.inserted = inserted;
153 }
154 /// Apply the changes to a document, returning the modified
155 /// document.
156 apply(doc) {
157 if (this.length != doc.length)
158 throw new RangeError("Applying change set to a document with the wrong length");
159 iterChanges(this, (fromA, toA, fromB, _toB, text) => doc = doc.replace(fromB, fromB + (toA - fromA), text), false);
160 return doc;
161 }
162 mapDesc(other, before = false) { return mapSet(this, other, before, true); }
163 /// Given the document as it existed _before_ the changes, return a
164 /// change set that represents the inverse of this set, which could
165 /// be used to go from the document created by the changes back to
166 /// the document as it existed before the changes.
167 invert(doc) {
168 let sections = this.sections.slice(), inserted = [];
169 for (let i = 0, pos = 0; i < sections.length; i += 2) {
170 let len = sections[i], ins = sections[i + 1];
171 if (ins >= 0) {
172 sections[i] = ins;
173 sections[i + 1] = len;
174 let index = i >> 1;
175 while (inserted.length < index)
176 inserted.push(Text.empty);
177 inserted.push(len ? doc.slice(pos, pos + len) : Text.empty);
178 }
179 pos += len;
180 }
181 return new ChangeSet(sections, inserted);
182 }
183 /// Combine two subsequent change sets into a single set. `other`
184 /// must start in the document produced by `this`. If `this` goes
185 /// `docA` → `docB` and `other` represents `docB` → `docC`, the
186 /// returned value will represent the change `docA` → `docC`.
187 compose(other) { return this.empty ? other : other.empty ? this : composeSets(this, other, true); }
188 /// Given another change set starting in the same document, maps this
189 /// change set over the other, producing a new change set that can be
190 /// applied to the document produced by applying `other`. When
191 /// `before` is `true`, order changes as if `this` comes before
192 /// `other`, otherwise (the default) treat `other` as coming first.
193 ///
194 /// Given two changes `A` and `B`, `A.compose(B.map(A))` and
195 /// `B.compose(A.map(B, true))` will produce the same document. This
196 /// provides a basic form of [operational
197 /// transformation](https://en.wikipedia.org/wiki/Operational_transformation),
198 /// and can be used for collaborative editing.
199 map(other, before = false) { return other.empty ? this : mapSet(this, other, before, true); }
200 /// Iterate over the changed ranges in the document, calling `f` for
201 /// each.
202 ///
203 /// When `individual` is true, adjacent changes are reported
204 /// separately.
205 iterChanges(f, individual = false) {
206 iterChanges(this, f, individual);
207 }
208 /// Get a [change description](#state.ChangeDesc) for this change
209 /// set.
210 get desc() { return new ChangeDesc(this.sections); }
211 /// @internal
212 filter(ranges) {
213 let resultSections = [], resultInserted = [], filteredSections = [];
214 let iter = new SectionIter(this);
215 done: for (let i = 0, pos = 0;;) {
216 let next = i == ranges.length ? 1e9 : ranges[i++];
217 while (pos < next || pos == next && iter.len == 0) {
218 if (iter.done)
219 break done;
220 let len = Math.min(iter.len, next - pos);
221 addSection(filteredSections, len, -1);
222 let ins = iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0;
223 addSection(resultSections, len, ins);
224 if (ins > 0)
225 addInsert(resultInserted, resultSections, iter.text);
226 iter.forward(len);
227 pos += len;
228 }
229 let end = ranges[i++];
230 while (pos < end) {
231 if (iter.done)
232 break done;
233 let len = Math.min(iter.len, end - pos);
234 addSection(resultSections, len, -1);
235 addSection(filteredSections, len, iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0);
236 iter.forward(len);
237 pos += len;
238 }
239 }
240 return { changes: new ChangeSet(resultSections, resultInserted),
241 filtered: new ChangeDesc(filteredSections) };
242 }
243 /// Serialize this change set to a JSON-representable value.
244 toJSON() {
245 let parts = [];
246 for (let i = 0; i < this.sections.length; i += 2) {
247 let len = this.sections[i], ins = this.sections[i + 1];
248 if (ins < 0)
249 parts.push(len);
250 else if (ins == 0)
251 parts.push([len]);
252 else
253 parts.push([len].concat(this.inserted[i >> 1].toJSON()));
254 }
255 return parts;
256 }
257 /// Create a change set for the given changes, for a document of the
258 /// given length, using `lineSep` as line separator.
259 static of(changes, length, lineSep) {
260 let sections = [], inserted = [], pos = 0;
261 let total = null;
262 function flush(force = false) {
263 if (!force && !sections.length)
264 return;
265 if (pos < length)
266 addSection(sections, length - pos, -1);
267 let set = new ChangeSet(sections, inserted);
268 total = total ? total.compose(set.map(total)) : set;
269 sections = [];
270 inserted = [];
271 pos = 0;
272 }
273 function process(spec) {
274 if (Array.isArray(spec)) {
275 for (let sub of spec)
276 process(sub);
277 }
278 else if (spec instanceof ChangeSet) {
279 if (spec.length != length)
280 throw new RangeError(`Mismatched change set length (got ${spec.length}, expected ${length})`);
281 flush();
282 total = total ? total.compose(spec.map(total)) : spec;
283 }
284 else {
285 let { from, to = from, insert } = spec;
286 if (from > to || from < 0 || to > length)
287 throw new RangeError(`Invalid change range ${from} to ${to} (in doc of length ${length})`);
288 let insText = !insert ? Text.empty : typeof insert == "string" ? Text.of(insert.split(lineSep || DefaultSplit)) : insert;
289 let insLen = insText.length;
290 if (from == to && insLen == 0)
291 return;
292 if (from < pos)
293 flush();
294 if (from > pos)
295 addSection(sections, from - pos, -1);
296 addSection(sections, to - from, insLen);
297 addInsert(inserted, sections, insText);
298 pos = to;
299 }
300 }
301 process(changes);
302 flush(!total);
303 return total;
304 }
305 /// Create an empty changeset of the given length.
306 static empty(length) {
307 return new ChangeSet(length ? [length, -1] : [], []);
308 }
309 /// Create a changeset from its JSON representation (as produced by
310 /// [`toJSON`](#state.ChangeSet.toJSON).
311 static fromJSON(json) {
312 if (!Array.isArray(json))
313 throw new RangeError("Invalid JSON representation of ChangeSet");
314 let sections = [], inserted = [];
315 for (let i = 0; i < json.length; i++) {
316 let part = json[i];
317 if (typeof part == "number") {
318 sections.push(part, -1);
319 }
320 else if (!Array.isArray(part) || typeof part[0] != "number" || part.some((e, i) => i && typeof e != "string")) {
321 throw new RangeError("Invalid JSON representation of ChangeSet");
322 }
323 else if (part.length == 1) {
324 sections.push(part[0], 0);
325 }
326 else {
327 while (inserted.length < i)
328 inserted.push(Text.empty);
329 inserted[i] = Text.of(part.slice(1));
330 sections.push(part[0], inserted[i].length);
331 }
332 }
333 return new ChangeSet(sections, inserted);
334 }
335}
336function addSection(sections, len, ins, forceJoin = false) {
337 if (len == 0 && ins <= 0)
338 return;
339 let last = sections.length - 2;
340 if (last >= 0 && ins <= 0 && ins == sections[last + 1])
341 sections[last] += len;
342 else if (len == 0 && sections[last] == 0)
343 sections[last + 1] += ins;
344 else if (forceJoin) {
345 sections[last] += len;
346 sections[last + 1] += ins;
347 }
348 else
349 sections.push(len, ins);
350}
351function addInsert(values, sections, value) {
352 if (value.length == 0)
353 return;
354 let index = (sections.length - 2) >> 1;
355 if (index < values.length) {
356 values[values.length - 1] = values[values.length - 1].append(value);
357 }
358 else {
359 while (values.length < index)
360 values.push(Text.empty);
361 values.push(value);
362 }
363}
364function iterChanges(desc, f, individual) {
365 let inserted = desc.inserted;
366 for (let posA = 0, posB = 0, i = 0; i < desc.sections.length;) {
367 let len = desc.sections[i++], ins = desc.sections[i++];
368 if (ins < 0) {
369 posA += len;
370 posB += len;
371 }
372 else {
373 let endA = posA, endB = posB, text = Text.empty;
374 for (;;) {
375 endA += len;
376 endB += ins;
377 if (ins && inserted)
378 text = text.append(inserted[(i - 2) >> 1]);
379 if (individual || i == desc.sections.length || desc.sections[i + 1] < 0)
380 break;
381 len = desc.sections[i++];
382 ins = desc.sections[i++];
383 }
384 f(posA, endA, posB, endB, text);
385 posA = endA;
386 posB = endB;
387 }
388 }
389}
390function mapSet(setA, setB, before, mkSet = false) {
391 let sections = [], insert = mkSet ? [] : null;
392 let a = new SectionIter(setA), b = new SectionIter(setB);
393 for (let posA = 0, posB = 0;;) {
394 if (a.ins == -1) {
395 posA += a.len;
396 a.next();
397 }
398 else if (b.ins == -1 && posB < posA) {
399 let skip = Math.min(b.len, posA - posB);
400 b.forward(skip);
401 addSection(sections, skip, -1);
402 posB += skip;
403 }
404 else if (b.ins >= 0 && (a.done || posB < posA || posB == posA && (b.len < a.len || b.len == a.len && !before))) {
405 addSection(sections, b.ins, -1);
406 while (posA > posB && !a.done && posA + a.len < posB + b.len) {
407 posA += a.len;
408 a.next();
409 }
410 posB += b.len;
411 b.next();
412 }
413 else if (a.ins >= 0) {
414 let len = 0, end = posA + a.len;
415 for (;;) {
416 if (b.ins >= 0 && posB > posA && posB + b.len < end) {
417 len += b.ins;
418 posB += b.len;
419 b.next();
420 }
421 else if (b.ins == -1 && posB < end) {
422 let skip = Math.min(b.len, end - posB);
423 len += skip;
424 b.forward(skip);
425 posB += skip;
426 }
427 else {
428 break;
429 }
430 }
431 addSection(sections, len, a.ins);
432 if (insert)
433 addInsert(insert, sections, a.text);
434 posA = end;
435 a.next();
436 }
437 else if (a.done && b.done) {
438 return insert ? new ChangeSet(sections, insert) : new ChangeDesc(sections);
439 }
440 else {
441 throw new Error("Mismatched change set lengths");
442 }
443 }
444}
445function composeSets(setA, setB, mkSet = false) {
446 let sections = [];
447 let insert = mkSet ? [] : null;
448 let a = new SectionIter(setA), b = new SectionIter(setB);
449 for (let open = false;;) {
450 if (a.done && b.done) {
451 return insert ? new ChangeSet(sections, insert) : new ChangeDesc(sections);
452 }
453 else if (a.ins == 0) { // Deletion in A
454 addSection(sections, a.len, 0, open);
455 a.next();
456 }
457 else if (b.len == 0 && !b.done) { // Insertion in B
458 addSection(sections, 0, b.ins, open);
459 if (insert)
460 addInsert(insert, sections, b.text);
461 b.next();
462 }
463 else if (a.done || b.done) {
464 throw new Error("Mismatched change set lengths");
465 }
466 else {
467 let len = Math.min(a.len2, b.len), sectionLen = sections.length;
468 if (a.ins == -1) {
469 let insB = b.ins == -1 ? -1 : b.off ? 0 : b.ins;
470 addSection(sections, len, insB, open);
471 if (insert && insB)
472 addInsert(insert, sections, b.text);
473 }
474 else if (b.ins == -1) {
475 addSection(sections, a.off ? 0 : a.len, len, open);
476 if (insert)
477 addInsert(insert, sections, a.textBit(len));
478 }
479 else {
480 addSection(sections, a.off ? 0 : a.len, b.off ? 0 : b.ins, open);
481 if (insert && !b.off)
482 addInsert(insert, sections, b.text);
483 }
484 open = (a.ins > len || b.ins >= 0 && b.len > len) && (open || sections.length > sectionLen);
485 a.forward2(len);
486 b.forward(len);
487 }
488 }
489}
490class SectionIter {
491 constructor(set) {
492 this.set = set;
493 this.i = 0;
494 this.next();
495 }
496 next() {
497 let { sections } = this.set;
498 if (this.i < sections.length) {
499 this.len = sections[this.i++];
500 this.ins = sections[this.i++];
501 }
502 else {
503 this.len = 0;
504 this.ins = -2;
505 }
506 this.off = 0;
507 }
508 get done() { return this.ins == -2; }
509 get len2() { return this.ins < 0 ? this.len : this.ins; }
510 get text() {
511 let { inserted } = this.set, index = (this.i - 2) >> 1;
512 return index >= inserted.length ? Text.empty : inserted[index];
513 }
514 textBit(len) {
515 let { inserted } = this.set, index = (this.i - 2) >> 1;
516 return index >= inserted.length && !len ? Text.empty
517 : inserted[index].slice(this.off, len == null ? undefined : this.off + len);
518 }
519 forward(len) {
520 if (len == this.len)
521 this.next();
522 else {
523 this.len -= len;
524 this.off += len;
525 }
526 }
527 forward2(len) {
528 if (this.ins == -1)
529 this.forward(len);
530 else if (len == this.ins)
531 this.next();
532 else {
533 this.ins -= len;
534 this.off += len;
535 }
536 }
537}
538
539/// A single selection range. When
540/// [`allowMultipleSelections`](#state.EditorState^allowMultipleSelections)
541/// is enabled, a [selection](#state.EditorSelection) may hold
542/// multiple ranges. By default, selections hold exactly one range.
543class SelectionRange {
544 /// @internal
545 constructor(
546 /// The lower boundary of the range.
547 from,
548 /// The upper boundary of the range.
549 to, flags) {
550 this.from = from;
551 this.to = to;
552 this.flags = flags;
553 }
554 /// The anchor of the range—the side that doesn't move when you
555 /// extend it.
556 get anchor() { return this.flags & 16 /* Inverted */ ? this.to : this.from; }
557 /// The head of the range, which is moved when the range is
558 /// [extended](#state.SelectionRange.extend).
559 get head() { return this.flags & 16 /* Inverted */ ? this.from : this.to; }
560 /// True when `anchor` and `head` are at the same position.
561 get empty() { return this.from == this.to; }
562 /// If this is a cursor that is explicitly associated with the
563 /// character on one of its sides, this returns the side. -1 means
564 /// the character before its position, 1 the character after, and 0
565 /// means no association.
566 get assoc() { return this.flags & 4 /* AssocBefore */ ? -1 : this.flags & 8 /* AssocAfter */ ? 1 : 0; }
567 /// The bidirectional text level associated with this cursor, if
568 /// any.
569 get bidiLevel() {
570 let level = this.flags & 3 /* BidiLevelMask */;
571 return level == 3 ? null : level;
572 }
573 /// The goal column (stored vertical offset) associated with a
574 /// cursor. This is used to preserve the vertical position when
575 /// [moving](#view.EditorView.moveVertically) across
576 /// lines of different length.
577 get goalColumn() {
578 let value = this.flags >> 5 /* GoalColumnOffset */;
579 return value == 33554431 /* NoGoalColumn */ ? undefined : value;
580 }
581 /// Map this range through a change, producing a valid range in the
582 /// updated document.
583 map(change) {
584 let from = change.mapPos(this.from), to = change.mapPos(this.to);
585 return from == this.from && to == this.to ? this : new SelectionRange(from, to, this.flags);
586 }
587 /// Extend this range to cover at least `from` to `to`.
588 extend(from, to = from) {
589 if (from <= this.anchor && to >= this.anchor)
590 return EditorSelection.range(from, to);
591 let head = Math.abs(from - this.anchor) > Math.abs(to - this.anchor) ? from : to;
592 return EditorSelection.range(this.anchor, head);
593 }
594 /// Compare this range to another range.
595 eq(other) {
596 return this.anchor == other.anchor && this.head == other.head;
597 }
598 /// Return a JSON-serializable object representing the range.
599 toJSON() { return { anchor: this.anchor, head: this.head }; }
600 /// Convert a JSON representation of a range to a `SelectionRange`
601 /// instance.
602 static fromJSON(json) {
603 if (!json || typeof json.anchor != "number" || typeof json.head != "number")
604 throw new RangeError("Invalid JSON representation for SelectionRange");
605 return EditorSelection.range(json.anchor, json.head);
606 }
607}
608/// An editor selection holds one or more selection ranges.
609class EditorSelection {
610 /// @internal
611 constructor(
612 /// The ranges in the selection, sorted by position. Ranges cannot
613 /// overlap (but they may touch, if they aren't empty).
614 ranges,
615 /// The index of the _main_ range in the selection (which is
616 /// usually the range that was added last).
617 mainIndex = 0) {
618 this.ranges = ranges;
619 this.mainIndex = mainIndex;
620 }
621 /// Map a selection through a change. Used to adjust the selection
622 /// position for changes.
623 map(change) {
624 if (change.empty)
625 return this;
626 return EditorSelection.create(this.ranges.map(r => r.map(change)), this.mainIndex);
627 }
628 /// Compare this selection to another selection.
629 eq(other) {
630 if (this.ranges.length != other.ranges.length ||
631 this.mainIndex != other.mainIndex)
632 return false;
633 for (let i = 0; i < this.ranges.length; i++)
634 if (!this.ranges[i].eq(other.ranges[i]))
635 return false;
636 return true;
637 }
638 /// Get the primary selection range. Usually, you should make sure
639 /// your code applies to _all_ ranges, by using methods like
640 /// [`changeByRange`](#state.EditorState.changeByRange).
641 get main() { return this.ranges[this.mainIndex]; }
642 /// Make sure the selection only has one range. Returns a selection
643 /// holding only the main range from this selection.
644 asSingle() {
645 return this.ranges.length == 1 ? this : new EditorSelection([this.main]);
646 }
647 /// Extend this selection with an extra range.
648 addRange(range, main = true) {
649 return EditorSelection.create([range].concat(this.ranges), main ? 0 : this.mainIndex + 1);
650 }
651 /// Replace a given range with another range, and then normalize the
652 /// selection to merge and sort ranges if necessary.
653 replaceRange(range, which = this.mainIndex) {
654 let ranges = this.ranges.slice();
655 ranges[which] = range;
656 return EditorSelection.create(ranges, this.mainIndex);
657 }
658 /// Convert this selection to an object that can be serialized to
659 /// JSON.
660 toJSON() {
661 return { ranges: this.ranges.map(r => r.toJSON()), main: this.mainIndex };
662 }
663 /// Create a selection from a JSON representation.
664 static fromJSON(json) {
665 if (!json || !Array.isArray(json.ranges) || typeof json.main != "number" || json.main >= json.ranges.length)
666 throw new RangeError("Invalid JSON representation for EditorSelection");
667 return new EditorSelection(json.ranges.map((r) => SelectionRange.fromJSON(r)), json.main);
668 }
669 /// Create a selection holding a single range.
670 static single(anchor, head = anchor) {
671 return new EditorSelection([EditorSelection.range(anchor, head)], 0);
672 }
673 /// Sort and merge the given set of ranges, creating a valid
674 /// selection.
675 static create(ranges, mainIndex = 0) {
676 if (ranges.length == 0)
677 throw new RangeError("A selection needs at least one range");
678 for (let pos = 0, i = 0; i < ranges.length; i++) {
679 let range = ranges[i];
680 if (range.empty ? range.from <= pos : range.from < pos)
681 return normalized(ranges.slice(), mainIndex);
682 pos = range.to;
683 }
684 return new EditorSelection(ranges, mainIndex);
685 }
686 /// Create a cursor selection range at the given position. You can
687 /// safely ignore the optional arguments in most situations.
688 static cursor(pos, assoc = 0, bidiLevel, goalColumn) {
689 return new SelectionRange(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* AssocBefore */ : 8 /* AssocAfter */) |
690 (bidiLevel == null ? 3 : Math.min(2, bidiLevel)) |
691 ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */));
692 }
693 /// Create a selection range.
694 static range(anchor, head, goalColumn) {
695 let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
696 return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal) : new SelectionRange(anchor, head, goal);
697 }
698}
699function normalized(ranges, mainIndex = 0) {
700 let main = ranges[mainIndex];
701 ranges.sort((a, b) => a.from - b.from);
702 mainIndex = ranges.indexOf(main);
703 for (let i = 1; i < ranges.length; i++) {
704 let range = ranges[i], prev = ranges[i - 1];
705 if (range.empty ? range.from <= prev.to : range.from < prev.to) {
706 let from = prev.from, to = Math.max(range.to, prev.to);
707 if (i <= mainIndex)
708 mainIndex--;
709 ranges.splice(--i, 2, range.anchor > range.head ? EditorSelection.range(to, from) : EditorSelection.range(from, to));
710 }
711 }
712 return new EditorSelection(ranges, mainIndex);
713}
714function checkSelection(selection, docLength) {
715 for (let range of selection.ranges)
716 if (range.to > docLength)
717 throw new RangeError("Selection points outside of document");
718}
719
720let nextID = 0;
721/// A facet is a labeled value that is associated with an editor
722/// state. It takes inputs from any number of extensions, and combines
723/// those into a single output value.
724///
725/// Examples of facets are the [theme](#view.EditorView^theme) styles
726/// associated with an editor or the [tab
727/// size](#state.EditorState^tabSize) (which is reduced to a single
728/// value, using the input with the hightest precedence).
729class Facet {
730 constructor(
731 /// @internal
732 combine,
733 /// @internal
734 compareInput,
735 /// @internal
736 compare, isStatic,
737 /// @internal
738 extensions) {
739 this.combine = combine;
740 this.compareInput = compareInput;
741 this.compare = compare;
742 this.isStatic = isStatic;
743 this.extensions = extensions;
744 /// @internal
745 this.id = nextID++;
746 this.default = combine([]);
747 }
748 /// Define a new facet.
749 static define(config = {}) {
750 return new Facet(config.combine || ((a) => a), config.compareInput || ((a, b) => a === b), config.compare || (!config.combine ? sameArray : (a, b) => a === b), !!config.static, config.enables);
751 }
752 /// Returns an extension that adds the given value for this facet.
753 of(value) {
754 return new FacetProvider([], this, 0 /* Static */, value);
755 }
756 /// Create an extension that computes a value for the facet from a
757 /// state. You must take care to declare the parts of the state that
758 /// this value depends on, since your function is only called again
759 /// for a new state when one of those parts changed.
760 ///
761 /// In most cases, you'll want to use the
762 /// [`provide`](#state.StateField^define^config.provide) option when
763 /// defining a field instead.
764 compute(deps, get) {
765 if (this.isStatic)
766 throw new Error("Can't compute a static facet");
767 return new FacetProvider(deps, this, 1 /* Single */, get);
768 }
769 /// Create an extension that computes zero or more values for this
770 /// facet from a state.
771 computeN(deps, get) {
772 if (this.isStatic)
773 throw new Error("Can't compute a static facet");
774 return new FacetProvider(deps, this, 2 /* Multi */, get);
775 }
776 from(field, get) {
777 if (!get)
778 get = x => x;
779 return this.compute([field], state => get(state.field(field)));
780 }
781}
782function sameArray(a, b) {
783 return a == b || a.length == b.length && a.every((e, i) => e === b[i]);
784}
785class FacetProvider {
786 constructor(dependencies, facet, type, value) {
787 this.dependencies = dependencies;
788 this.facet = facet;
789 this.type = type;
790 this.value = value;
791 this.id = nextID++;
792 }
793 dynamicSlot(addresses) {
794 var _a;
795 let getter = this.value;
796 let compare = this.facet.compareInput;
797 let idx = addresses[this.id] >> 1, multi = this.type == 2 /* Multi */;
798 let depDoc = false, depSel = false, depAddrs = [];
799 for (let dep of this.dependencies) {
800 if (dep == "doc")
801 depDoc = true;
802 else if (dep == "selection")
803 depSel = true;
804 else if ((((_a = addresses[dep.id]) !== null && _a !== void 0 ? _a : 1) & 1) == 0)
805 depAddrs.push(addresses[dep.id]);
806 }
807 return (state, tr) => {
808 if (!tr || tr.reconfigure) {
809 state.values[idx] = getter(state);
810 return 1 /* Changed */;
811 }
812 else {
813 let depChanged = (depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) ||
814 depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0);
815 if (!depChanged)
816 return 0;
817 let newVal = getter(state), oldVal = tr.startState.values[idx];
818 if (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))
819 return 0;
820 state.values[idx] = newVal;
821 return 1 /* Changed */;
822 }
823 };
824 }
825}
826function compareArray(a, b, compare) {
827 if (a.length != b.length)
828 return false;
829 for (let i = 0; i < a.length; i++)
830 if (!compare(a[i], b[i]))
831 return false;
832 return true;
833}
834function dynamicFacetSlot(addresses, facet, providers) {
835 let providerAddrs = providers.map(p => addresses[p.id]);
836 let providerTypes = providers.map(p => p.type);
837 let dynamic = providerAddrs.filter(p => !(p & 1));
838 let idx = addresses[facet.id] >> 1;
839 return (state, tr) => {
840 let oldAddr = !tr ? null : tr.reconfigure ? tr.startState.config.address[facet.id] : idx << 1;
841 let changed = oldAddr == null;
842 for (let dynAddr of dynamic) {
843 if (ensureAddr(state, dynAddr) & 1 /* Changed */)
844 changed = true;
845 }
846 if (!changed)
847 return 0;
848 let values = [];
849 for (let i = 0; i < providerAddrs.length; i++) {
850 let value = getAddr(state, providerAddrs[i]);
851 if (providerTypes[i] == 2 /* Multi */)
852 for (let val of value)
853 values.push(val);
854 else
855 values.push(value);
856 }
857 let newVal = facet.combine(values);
858 if (oldAddr != null && facet.compare(newVal, getAddr(tr.startState, oldAddr)))
859 return 0;
860 state.values[idx] = newVal;
861 return 1 /* Changed */;
862 };
863}
864function maybeIndex(state, id) {
865 let found = state.config.address[id];
866 return found == null ? null : found >> 1;
867}
868const initField = Facet.define({ static: true });
869/// Fields can store additional information in an editor state, and
870/// keep it in sync with the rest of the state.
871class StateField {
872 constructor(
873 /// @internal
874 id, createF, updateF, compareF,
875 /// @internal
876 spec) {
877 this.id = id;
878 this.createF = createF;
879 this.updateF = updateF;
880 this.compareF = compareF;
881 this.spec = spec;
882 /// @internal
883 this.provides = undefined;
884 }
885 /// Define a state field.
886 static define(config) {
887 let field = new StateField(nextID++, config.create, config.update, config.compare || ((a, b) => a === b), config);
888 if (config.provide)
889 field.provides = config.provide(field);
890 return field;
891 }
892 create(state) {
893 let init = state.facet(initField).find(i => i.field == this);
894 return ((init === null || init === void 0 ? void 0 : init.create) || this.createF)(state);
895 }
896 /// @internal
897 slot(addresses) {
898 let idx = addresses[this.id] >> 1;
899 return (state, tr) => {
900 if (!tr) {
901 state.values[idx] = this.create(state);
902 return 1 /* Changed */;
903 }
904 let oldVal, changed = 0;
905 if (tr.reconfigure) {
906 let oldIdx = maybeIndex(tr.startState, this.id);
907 oldVal = oldIdx == null ? this.create(tr.startState) : tr.startState.values[oldIdx];
908 changed = 1 /* Changed */;
909 }
910 else {
911 oldVal = tr.startState.values[idx];
912 }
913 let value = this.updateF(oldVal, tr);
914 if (!changed && !this.compareF(oldVal, value))
915 changed = 1 /* Changed */;
916 if (changed)
917 state.values[idx] = value;
918 return changed;
919 };
920 }
921 /// Returns an extension that enables this field and overrides the
922 /// way it is initialized. Can be useful when you need to provide a
923 /// non-default starting value for the field.
924 init(create) {
925 return [this, initField.of({ field: this, create })];
926 }
927}
928const Prec_ = { fallback: 3, default: 2, extend: 1, override: 0 };
929function prec(value) {
930 return (ext) => new PrecExtension(ext, value);
931}
932/// By default extensions are registered in the order they are found
933/// in the flattened form of nested array that was provided.
934/// Individual extension values can be assigned a precedence to
935/// override this. Extensions that do not have a precedence set get
936/// the precedence of the nearest parent with a precedence, or
937/// [`default`](#state.Prec.default) if there is no such parent. The
938/// final ordering of extensions is determined by first sorting by
939/// precedence and then by order within each precedence.
940const Prec = {
941 /// A precedence below the default precedence, which will cause
942 /// default-precedence extensions to override it even if they are
943 /// specified later in the extension ordering.
944 fallback: prec(Prec_.fallback),
945 /// The regular default precedence.
946 default: prec(Prec_.default),
947 /// A higher-than-default precedence.
948 extend: prec(Prec_.extend),
949 /// Precedence above the `default` and `extend` precedences.
950 override: prec(Prec_.override)
951};
952class PrecExtension {
953 constructor(inner, prec) {
954 this.inner = inner;
955 this.prec = prec;
956 }
957}
958class TaggedExtension {
959 constructor(tag, inner) {
960 this.tag = tag;
961 this.inner = inner;
962 }
963}
964/// Tagged extensions can be used to make a configuration dynamic.
965/// Tagging an extension allows you to later
966/// [replace](#state.TransactionSpec.reconfigure) it with
967/// another extension. A given tag may only occur once within a given
968/// configuration.
969function tagExtension(tag, extension) {
970 return new TaggedExtension(tag, extension);
971}
972class Configuration {
973 constructor(source, replacements, dynamicSlots, address, staticValues) {
974 this.source = source;
975 this.replacements = replacements;
976 this.dynamicSlots = dynamicSlots;
977 this.address = address;
978 this.staticValues = staticValues;
979 this.statusTemplate = [];
980 while (this.statusTemplate.length < dynamicSlots.length)
981 this.statusTemplate.push(0 /* Uninitialized */);
982 }
983 staticFacet(facet) {
984 let addr = this.address[facet.id];
985 return addr == null ? facet.default : this.staticValues[addr >> 1];
986 }
987 static resolve(extension, replacements = Object.create(null), oldState) {
988 let fields = [];
989 let facets = Object.create(null);
990 for (let ext of flatten(extension, replacements)) {
991 if (ext instanceof StateField)
992 fields.push(ext);
993 else
994 (facets[ext.facet.id] || (facets[ext.facet.id] = [])).push(ext);
995 }
996 let address = Object.create(null);
997 let staticValues = [];
998 let dynamicSlots = [];
999 for (let field of fields) {
1000 address[field.id] = dynamicSlots.length << 1;
1001 dynamicSlots.push(a => field.slot(a));
1002 }
1003 for (let id in facets) {
1004 let providers = facets[id], facet = providers[0].facet;
1005 if (providers.every(p => p.type == 0 /* Static */)) {
1006 address[facet.id] = (staticValues.length << 1) | 1;
1007 let value = facet.combine(providers.map(p => p.value));
1008 let oldAddr = oldState ? oldState.config.address[facet.id] : null;
1009 if (oldAddr != null) {
1010 let oldVal = getAddr(oldState, oldAddr);
1011 if (facet.compare(value, oldVal))
1012 value = oldVal;
1013 }
1014 staticValues.push(value);
1015 }
1016 else {
1017 for (let p of providers) {
1018 if (p.type == 0 /* Static */) {
1019 address[p.id] = (staticValues.length << 1) | 1;
1020 staticValues.push(p.value);
1021 }
1022 else {
1023 address[p.id] = dynamicSlots.length << 1;
1024 dynamicSlots.push(a => p.dynamicSlot(a));
1025 }
1026 }
1027 address[facet.id] = dynamicSlots.length << 1;
1028 dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers));
1029 }
1030 }
1031 return new Configuration(extension, replacements, dynamicSlots.map(f => f(address)), address, staticValues);
1032 }
1033}
1034function allKeys(obj) {
1035 return (Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(obj) : []).concat(Object.keys(obj));
1036}
1037function flatten(extension, replacements) {
1038 let result = [[], [], [], []];
1039 let seen = new Map();
1040 let tagsSeen = Object.create(null);
1041 function inner(ext, prec) {
1042 let known = seen.get(ext);
1043 if (known != null) {
1044 if (known >= prec)
1045 return;
1046 let found = result[known].indexOf(ext);
1047 if (found > -1)
1048 result[known].splice(found, 1);
1049 }
1050 seen.set(ext, prec);
1051 if (Array.isArray(ext)) {
1052 for (let e of ext)
1053 inner(e, prec);
1054 }
1055 else if (ext instanceof TaggedExtension) {
1056 if (ext.tag in tagsSeen)
1057 throw new RangeError(`Duplicate use of tag '${String(ext.tag)}' in extensions`);
1058 tagsSeen[ext.tag] = true;
1059 inner(replacements[ext.tag] || ext.inner, prec);
1060 }
1061 else if (ext instanceof PrecExtension) {
1062 inner(ext.inner, ext.prec);
1063 }
1064 else if (ext instanceof StateField) {
1065 result[prec].push(ext);
1066 if (ext.provides)
1067 inner(ext.provides, prec);
1068 }
1069 else if (ext instanceof FacetProvider) {
1070 result[prec].push(ext);
1071 if (ext.facet.extensions)
1072 inner(ext.facet.extensions, prec);
1073 }
1074 else {
1075 inner(ext.extension, prec);
1076 }
1077 }
1078 inner(extension, Prec_.default);
1079 for (let key of allKeys(replacements))
1080 if (!(key in tagsSeen) && key != "full" && replacements[key]) {
1081 tagsSeen[key] = true;
1082 inner(replacements[key], Prec_.default);
1083 }
1084 return result.reduce((a, b) => a.concat(b));
1085}
1086function ensureAddr(state, addr) {
1087 if (addr & 1)
1088 return 2 /* Computed */;
1089 let idx = addr >> 1;
1090 let status = state.status[idx];
1091 if (status == 4 /* Computing */)
1092 throw new Error("Cyclic dependency between fields and/or facets");
1093 if (status & 2 /* Computed */)
1094 return status;
1095 state.status[idx] = 4 /* Computing */;
1096 let changed = state.config.dynamicSlots[idx](state, state.applying);
1097 return state.status[idx] = 2 /* Computed */ | changed;
1098}
1099function getAddr(state, addr) {
1100 return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1];
1101}
1102
1103const languageData = Facet.define();
1104const allowMultipleSelections = Facet.define({
1105 combine: values => values.some(v => v),
1106 static: true
1107});
1108const lineSeparator = Facet.define({
1109 combine: values => values.length ? values[0] : undefined,
1110 static: true
1111});
1112const changeFilter = Facet.define();
1113const transactionFilter = Facet.define();
1114const transactionExtender = Facet.define();
1115
1116/// Annotations are tagged values that are used to add metadata to
1117/// transactions in an extensible way. They should be used to model
1118/// things that effect the entire transaction (such as its [time
1119/// stamp](#state.Transaction^time) or information about its
1120/// [origin](#state.Transaction^userEvent)). For effects that happen
1121/// _alongside_ the other changes made by the transaction, [state
1122/// effects](#state.StateEffect) are more appropriate.
1123class Annotation {
1124 /// @internal
1125 constructor(
1126 /// The annotation type.
1127 type,
1128 /// The value of this annotation.
1129 value) {
1130 this.type = type;
1131 this.value = value;
1132 }
1133 /// Define a new type of annotation.
1134 static define() { return new AnnotationType(); }
1135}
1136/// Marker that identifies a type of [annotation](#state.Annotation).
1137class AnnotationType {
1138 /// Create an instance of this annotation.
1139 of(value) { return new Annotation(this, value); }
1140}
1141/// State effects can be used to represent additional effects
1142/// associated with a [transaction](#state.Transaction.effects). They
1143/// are often useful to model changes to custom [state
1144/// fields](#state.StateField), when those changes aren't implicit in
1145/// document or selection changes.
1146class StateEffect {
1147 /// @internal
1148 constructor(
1149 /// @internal
1150 type,
1151 /// The value of this effect.
1152 value) {
1153 this.type = type;
1154 this.value = value;
1155 }
1156 /// Map this effect through a position mapping. Will return
1157 /// `undefined` when that ends up deleting the effect.
1158 map(mapping) {
1159 let mapped = this.type.map(this.value, mapping);
1160 return mapped === undefined ? undefined : mapped == this.value ? this : new StateEffect(this.type, mapped);
1161 }
1162 /// Tells you whether this effect object is of a given
1163 /// [type](#state.StateEffectType).
1164 is(type) { return this.type == type; }
1165 /// Define a new effect type. The type parameter indicates the type
1166 /// of values that his effect holds.
1167 static define(spec = {}) {
1168 return new StateEffectType(spec.map || (v => v));
1169 }
1170 /// Map an array of effects through a change set.
1171 static mapEffects(effects, mapping) {
1172 if (!effects.length)
1173 return effects;
1174 let result = [];
1175 for (let effect of effects) {
1176 let mapped = effect.map(mapping);
1177 if (mapped)
1178 result.push(mapped);
1179 }
1180 return result;
1181 }
1182}
1183/// Representation of a type of state effect. Defined with
1184/// [`StateEffect.define`](#state.StateEffect^define).
1185class StateEffectType {
1186 /// @internal
1187 constructor(
1188 // The `any` types in these function types are there to work
1189 // around TypeScript issue #37631, where the type guard on
1190 // `StateEffect.is` mysteriously stops working when these properly
1191 // have type `Value`.
1192 /// @internal
1193 map) {
1194 this.map = map;
1195 }
1196 /// Create a [state effect](#state.StateEffect) instance of this
1197 /// type.
1198 of(value) { return new StateEffect(this, value); }
1199}
1200/// Changes to the editor state are grouped into transactions.
1201/// Typically, a user action creates a single transaction, which may
1202/// contain any number of document changes, may change the selection,
1203/// or have other effects. Create a transaction by calling
1204/// [`EditorState.update`](#state.EditorState.update).
1205class Transaction {
1206 /// @internal
1207 constructor(
1208 /// The state from which the transaction starts.
1209 startState,
1210 /// The document changes made by this transaction.
1211 changes,
1212 /// The selection set by this transaction, or undefined if it
1213 /// doesn't explicitly set a selection.
1214 selection,
1215 /// The effects added to the transaction.
1216 effects,
1217 /// @internal
1218 annotations,
1219 /// Holds an object when this transaction
1220 /// [reconfigures](#state.ReconfigurationSpec) the state.
1221 reconfigure,
1222 /// Whether the selection should be scrolled into view after this
1223 /// transaction is dispatched.
1224 scrollIntoView) {
1225 this.startState = startState;
1226 this.changes = changes;
1227 this.selection = selection;
1228 this.effects = effects;
1229 this.annotations = annotations;
1230 this.reconfigure = reconfigure;
1231 this.scrollIntoView = scrollIntoView;
1232 /// @internal
1233 this._doc = null;
1234 /// @internal
1235 this._state = null;
1236 if (selection)
1237 checkSelection(selection, changes.newLength);
1238 if (!annotations.some((a) => a.type == Transaction.time))
1239 this.annotations = annotations.concat(Transaction.time.of(Date.now()));
1240 }
1241 /// The new document produced by the transaction. Contrary to
1242 /// [`.state`](#state.Transaction.state)`.doc`, accessing this won't
1243 /// force the entire new state to be computed right away, so it is
1244 /// recommended that [transaction
1245 /// filters](#state.EditorState^transactionFilter) use this getter
1246 /// when they need to look at the new document.
1247 get newDoc() {
1248 return this._doc || (this._doc = this.changes.apply(this.startState.doc));
1249 }
1250 /// The new selection produced by the transaction. If
1251 /// [`this.selection`](#state.Transaction.selection) is undefined,
1252 /// this will [map](#state.EditorSelection.map) the start state's
1253 /// current selection through the changes made by the transaction.
1254 get newSelection() {
1255 return this.selection || this.startState.selection.map(this.changes);
1256 }
1257 /// The new state created by the transaction. Computed on demand
1258 /// (but retained for subsequent access), so itis recommended not to
1259 /// access it in [transaction
1260 /// filters](#state.EditorState^transactionFilter) when possible.
1261 get state() {
1262 if (!this._state)
1263 this.startState.applyTransaction(this);
1264 return this._state;
1265 }
1266 /// Get the value of the given annotation type, if any.
1267 annotation(type) {
1268 for (let ann of this.annotations)
1269 if (ann.type == type)
1270 return ann.value;
1271 return undefined;
1272 }
1273 /// Indicates whether the transaction changed the document.
1274 get docChanged() { return !this.changes.empty; }
1275}
1276/// Annotation used to store transaction timestamps.
1277Transaction.time = Annotation.define();
1278/// Annotation used to associate a transaction with a user interface
1279/// event. The view will set this to...
1280///
1281/// - `"input"` when the user types text
1282/// - `"delete"` when the user deletes the selection or text near the selection
1283/// - `"keyboardselection"` when moving the selection via the keyboard
1284/// - `"pointerselection"` when moving the selection through the pointing device
1285/// - `"paste"` when pasting content
1286/// - `"cut"` when cutting
1287/// - `"drop"` when content is inserted via drag-and-drop
1288Transaction.userEvent = Annotation.define();
1289/// Annotation indicating whether a transaction should be added to
1290/// the undo history or not.
1291Transaction.addToHistory = Annotation.define();
1292function joinRanges(a, b) {
1293 let result = [];
1294 for (let iA = 0, iB = 0;;) {
1295 let from, to;
1296 if (iA < a.length && (iB == b.length || b[iB] >= a[iA])) {
1297 from = a[iA++];
1298 to = a[iA++];
1299 }
1300 else if (iB < b.length) {
1301 from = b[iB++];
1302 to = b[iB++];
1303 }
1304 else
1305 return result;
1306 if (!result.length || result[result.length - 1] < from)
1307 result.push(from, to);
1308 else if (result[result.length - 1] < to)
1309 result[result.length - 1] = to;
1310 }
1311}
1312function mergeTransaction(a, b, sequential) {
1313 var _a;
1314 let mapForA, mapForB, changes;
1315 if (sequential) {
1316 mapForA = b.changes;
1317 mapForB = ChangeSet.empty(b.changes.length);
1318 changes = a.changes.compose(b.changes);
1319 }
1320 else {
1321 mapForA = b.changes.map(a.changes);
1322 mapForB = a.changes.mapDesc(b.changes, true);
1323 changes = a.changes.compose(mapForA);
1324 }
1325 return {
1326 changes,
1327 selection: b.selection ? b.selection.map(mapForB) : (_a = a.selection) === null || _a === void 0 ? void 0 : _a.map(mapForA),
1328 effects: StateEffect.mapEffects(a.effects, mapForA).concat(StateEffect.mapEffects(b.effects, mapForB)),
1329 annotations: a.annotations.length ? a.annotations.concat(b.annotations) : b.annotations,
1330 scrollIntoView: a.scrollIntoView || b.scrollIntoView,
1331 reconfigure: !b.reconfigure ? a.reconfigure : b.reconfigure.full || !a.reconfigure ? b.reconfigure
1332 : Object.assign({}, a.reconfigure, b.reconfigure)
1333 };
1334}
1335function resolveTransactionInner(state, spec, docSize) {
1336 let reconf = spec.reconfigure;
1337 if (reconf && reconf.append) {
1338 reconf = Object.assign({}, reconf);
1339 let tag = typeof Symbol == "undefined" ? "__append" + Math.floor(Math.random() * 0xffffffff) : Symbol("appendConf");
1340 reconf[tag] = reconf.append;
1341 reconf.append = undefined;
1342 }
1343 let sel = spec.selection;
1344 return {
1345 changes: spec.changes instanceof ChangeSet ? spec.changes
1346 : ChangeSet.of(spec.changes || [], docSize, state.facet(lineSeparator)),
1347 selection: sel && (sel instanceof EditorSelection ? sel : EditorSelection.single(sel.anchor, sel.head)),
1348 effects: asArray(spec.effects),
1349 annotations: asArray(spec.annotations),
1350 scrollIntoView: !!spec.scrollIntoView,
1351 reconfigure: reconf
1352 };
1353}
1354function resolveTransaction(state, specs, filter) {
1355 let s = resolveTransactionInner(state, specs.length ? specs[0] : {}, state.doc.length);
1356 if (specs.length && specs[0].filter === false)
1357 filter = false;
1358 for (let i = 1; i < specs.length; i++) {
1359 if (specs[i].filter === false)
1360 filter = false;
1361 let seq = !!specs[i].sequential;
1362 s = mergeTransaction(s, resolveTransactionInner(state, specs[i], seq ? s.changes.newLength : state.doc.length), seq);
1363 }
1364 let tr = new Transaction(state, s.changes, s.selection, s.effects, s.annotations, s.reconfigure, s.scrollIntoView);
1365 return extendTransaction(filter ? filterTransaction(tr) : tr);
1366}
1367// Finish a transaction by applying filters if necessary.
1368function filterTransaction(tr) {
1369 let state = tr.startState;
1370 // Change filters
1371 let result = true;
1372 for (let filter of state.facet(changeFilter)) {
1373 let value = filter(tr);
1374 if (value === false) {
1375 result = false;
1376 break;
1377 }
1378 if (Array.isArray(value))
1379 result = result === true ? value : joinRanges(result, value);
1380 }
1381 if (result !== true) {
1382 let changes, back;
1383 if (result === false) {
1384 back = tr.changes.invertedDesc;
1385 changes = ChangeSet.empty(state.doc.length);
1386 }
1387 else {
1388 let filtered = tr.changes.filter(result);
1389 changes = filtered.changes;
1390 back = filtered.filtered.invertedDesc;
1391 }
1392 tr = new Transaction(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.reconfigure, tr.scrollIntoView);
1393 }
1394 // Transaction filters
1395 let filters = state.facet(transactionFilter);
1396 for (let i = filters.length - 1; i >= 0; i--) {
1397 let filtered = filters[i](tr);
1398 if (filtered instanceof Transaction)
1399 tr = filtered;
1400 else if (Array.isArray(filtered) && filtered.length == 1 && filtered[0] instanceof Transaction)
1401 tr = filtered[0];
1402 else
1403 tr = resolveTransaction(state, asArray(filtered), false);
1404 }
1405 return tr;
1406}
1407function extendTransaction(tr) {
1408 let state = tr.startState, extenders = state.facet(transactionExtender), spec = tr;
1409 for (let i = extenders.length - 1; i >= 0; i--) {
1410 let extension = extenders[i](tr);
1411 if (extension && Object.keys(extension).length)
1412 spec = mergeTransaction(tr, resolveTransactionInner(state, extension, tr.changes.newLength), true);
1413 }
1414 return spec == tr ? tr : new Transaction(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.reconfigure, spec.scrollIntoView);
1415}
1416const none = [];
1417function asArray(value) {
1418 return value == null ? none : Array.isArray(value) ? value : [value];
1419}
1420
1421/// The categories produced by a [character
1422/// categorizer](#state.EditorState.charCategorizer). These are used
1423/// do things like selecting by word.
1424var CharCategory;
1425(function (CharCategory) {
1426 /// Word characters.
1427 CharCategory[CharCategory["Word"] = 0] = "Word";
1428 /// Whitespace.
1429 CharCategory[CharCategory["Space"] = 1] = "Space";
1430 /// Anything else.
1431 CharCategory[CharCategory["Other"] = 2] = "Other";
1432})(CharCategory || (CharCategory = {}));
1433const nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
1434let wordChar;
1435try {
1436 wordChar = new RegExp("[\\p{Alphabetic}\\p{Number}_]", "u");
1437}
1438catch (_) { }
1439function hasWordChar(str) {
1440 if (wordChar)
1441 return wordChar.test(str);
1442 for (let i = 0; i < str.length; i++) {
1443 let ch = str[i];
1444 if (/\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)))
1445 return true;
1446 }
1447 return false;
1448}
1449function makeCategorizer(wordChars) {
1450 return (char) => {
1451 if (!/\S/.test(char))
1452 return CharCategory.Space;
1453 if (hasWordChar(char))
1454 return CharCategory.Word;
1455 for (let i = 0; i < wordChars.length; i++)
1456 if (char.indexOf(wordChars[i]) > -1)
1457 return CharCategory.Word;
1458 return CharCategory.Other;
1459 };
1460}
1461
1462/// The editor state class is a persistent (immutable) data structure.
1463/// To update a state, you [create](#state.EditorState.update) a
1464/// [transaction](#state.Transaction), which produces a _new_ state
1465/// instance, without modifying the original object.
1466///
1467/// As such, _never_ mutate properties of a state directly. That'll
1468/// just break things.
1469class EditorState {
1470 /// @internal
1471 constructor(
1472 /// @internal
1473 config,
1474 /// The current document.
1475 doc,
1476 /// The current selection.
1477 selection, tr = null) {
1478 this.config = config;
1479 this.doc = doc;
1480 this.selection = selection;
1481 /// @internal
1482 this.applying = null;
1483 this.status = config.statusTemplate.slice();
1484 if (tr && !tr.reconfigure) {
1485 this.values = tr.startState.values.slice();
1486 }
1487 else {
1488 this.values = config.dynamicSlots.map(_ => null);
1489 // Copy over old values for shared facets/fields if this is a reconfigure
1490 if (tr)
1491 for (let id in config.address) {
1492 let cur = config.address[id], prev = tr.startState.config.address[id];
1493 if (prev != null && (cur & 1) == 0)
1494 this.values[cur >> 1] = getAddr(tr.startState, prev);
1495 }
1496 }
1497 this.applying = tr;
1498 // Fill in the computed state immediately, so that further queries
1499 // for it made during the update return this state
1500 if (tr)
1501 tr._state = this;
1502 for (let i = 0; i < this.config.dynamicSlots.length; i++)
1503 ensureAddr(this, i << 1);
1504 this.applying = null;
1505 }
1506 field(field, require = true) {
1507 let addr = this.config.address[field.id];
1508 if (addr == null) {
1509 if (require)
1510 throw new RangeError("Field is not present in this state");
1511 return undefined;
1512 }
1513 ensureAddr(this, addr);
1514 return getAddr(this, addr);
1515 }
1516 /// Create a [transaction](#state.Transaction) that updates this
1517 /// state. Any number of [transaction specs](#state.TransactionSpec)
1518 /// can be passed. Unless
1519 /// [`sequential`](#state.TransactionSpec.sequential) is set, the
1520 /// [changes](#state.TransactionSpec.changes) (if any) of each spec
1521 /// are assumed to start in the _current_ document (not the document
1522 /// produced by previous specs), and its
1523 /// [selection](#state.TransactionSpec.selection) and
1524 /// [effects](#state.TransactionSpec.effects) are assumed to refer
1525 /// to the document created by its _own_ changes. The resulting
1526 /// transaction contains the combined effect of all the different
1527 /// specs. For things like
1528 /// [selection](#state.TransactionSpec.selection) or
1529 /// [reconfiguration](#state.TransactionSpec.reconfigure), later
1530 /// specs take precedence over earlier ones.
1531 update(...specs) {
1532 return resolveTransaction(this, specs, true);
1533 }
1534 /// @internal
1535 applyTransaction(tr) {
1536 let conf = this.config;
1537 if (tr.reconfigure)
1538 conf = Configuration.resolve(tr.reconfigure.full || conf.source, Object.assign(conf.replacements, tr.reconfigure, { full: undefined }), this);
1539 new EditorState(conf, tr.newDoc, tr.newSelection, tr);
1540 }
1541 /// Create a [transaction spec](#state.TransactionSpec) that
1542 /// replaces every selection range with the given content.
1543 replaceSelection(text) {
1544 if (typeof text == "string")
1545 text = this.toText(text);
1546 return this.changeByRange(range => ({ changes: { from: range.from, to: range.to, insert: text },
1547 range: EditorSelection.cursor(range.from + text.length) }));
1548 }
1549 /// Create a set of changes and a new selection by running the given
1550 /// function for each range in the active selection. The function
1551 /// can return an optional set of changes (in the coordinate space
1552 /// of the start document), plus an updated range (in the coordinate
1553 /// space of the document produced by the call's own changes). This
1554 /// method will merge all the changes and ranges into a single
1555 /// changeset and selection, and return it as a [transaction
1556 /// spec](#state.TransactionSpec), which can be passed to
1557 /// [`update`](#state.EditorState.update).
1558 changeByRange(f) {
1559 let sel = this.selection;
1560 let result1 = f(sel.ranges[0]);
1561 let changes = this.changes(result1.changes), ranges = [result1.range];
1562 let effects = asArray(result1.effects);
1563 for (let i = 1; i < sel.ranges.length; i++) {
1564 let result = f(sel.ranges[i]);
1565 let newChanges = this.changes(result.changes), newMapped = newChanges.map(changes);
1566 for (let j = 0; j < i; j++)
1567 ranges[j] = ranges[j].map(newMapped);
1568 let mapBy = changes.mapDesc(newChanges, true);
1569 ranges.push(result.range.map(mapBy));
1570 changes = changes.compose(newMapped);
1571 effects = StateEffect.mapEffects(effects, newMapped).concat(StateEffect.mapEffects(asArray(result.effects), mapBy));
1572 }
1573 return {
1574 changes,
1575 selection: EditorSelection.create(ranges, sel.mainIndex),
1576 effects
1577 };
1578 }
1579 /// Create a [change set](#state.ChangeSet) from the given change
1580 /// description, taking the state's document length and line
1581 /// separator into account.
1582 changes(spec = []) {
1583 if (spec instanceof ChangeSet)
1584 return spec;
1585 return ChangeSet.of(spec, this.doc.length, this.facet(EditorState.lineSeparator));
1586 }
1587 /// Using the state's [line
1588 /// separator](#state.EditorState^lineSeparator), create a
1589 /// [`Text`](#text.Text) instance from the given string.
1590 toText(string) {
1591 return Text.of(string.split(this.facet(EditorState.lineSeparator) || DefaultSplit));
1592 }
1593 /// Return the given range of the document as a string.
1594 sliceDoc(from = 0, to = this.doc.length) {
1595 return this.doc.sliceString(from, to, this.lineBreak);
1596 }
1597 /// Get the value of a state [facet](#state.Facet).
1598 facet(facet) {
1599 let addr = this.config.address[facet.id];
1600 if (addr == null)
1601 return facet.default;
1602 ensureAddr(this, addr);
1603 return getAddr(this, addr);
1604 }
1605 /// Convert this state to a JSON-serializable object. When custom
1606 /// fields should be serialized, you can pass them in as an object
1607 /// mapping property names (in the resulting object, which should
1608 /// not use `doc` or `selection`) to fields.
1609 toJSON(fields) {
1610 let result = {
1611 doc: this.sliceDoc(),
1612 selection: this.selection.toJSON()
1613 };
1614 if (fields)
1615 for (let prop in fields)
1616 result[prop] = fields[prop].spec.toJSON(this.field(fields[prop]), this);
1617 return result;
1618 }
1619 /// Deserialize a state from its JSON representation. When custom
1620 /// fields should be deserialized, pass the same object you passed
1621 /// to [`toJSON`](#state.EditorState.toJSON) when serializing as
1622 /// third argument.
1623 static fromJSON(json, config = {}, fields) {
1624 if (!json || typeof json.doc != "string")
1625 throw new RangeError("Invalid JSON representation for EditorState");
1626 let fieldInit = [];
1627 if (fields)
1628 for (let prop in fields) {
1629 let field = fields[prop], value = json[prop];
1630 fieldInit.push(field.init(state => field.spec.fromJSON(value, state)));
1631 }
1632 return EditorState.create({
1633 doc: json.doc,
1634 selection: EditorSelection.fromJSON(json.selection),
1635 extensions: config.extensions ? fieldInit.concat([config.extensions]) : fieldInit
1636 });
1637 }
1638 /// Create a new state. You'll usually only need this when
1639 /// initializing an editor—updated states are created by applying
1640 /// transactions.
1641 static create(config = {}) {
1642 let configuration = Configuration.resolve(config.extensions || []);
1643 let doc = config.doc instanceof Text ? config.doc
1644 : Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit));
1645 let selection = !config.selection ? EditorSelection.single(0)
1646 : config.selection instanceof EditorSelection ? config.selection
1647 : EditorSelection.single(config.selection.anchor, config.selection.head);
1648 checkSelection(selection, doc.length);
1649 if (!configuration.staticFacet(allowMultipleSelections))
1650 selection = selection.asSingle();
1651 return new EditorState(configuration, doc, selection);
1652 }
1653 /// The size (in columns) of a tab in the document, determined by
1654 /// the [`tabSize`](#state.EditorState^tabSize) facet.
1655 get tabSize() { return this.facet(EditorState.tabSize); }
1656 /// Get the proper [line-break](#state.EditorState^lineSeparator)
1657 /// string for this state.
1658 get lineBreak() { return this.facet(EditorState.lineSeparator) || "\n"; }
1659 /// Look up a translation for the given phrase (via the
1660 /// [`phrases`](#state.EditorState^phrases) facet), or return the
1661 /// original string if no translation is found.
1662 phrase(phrase) {
1663 for (let map of this.facet(EditorState.phrases))
1664 if (Object.prototype.hasOwnProperty.call(map, phrase))
1665 return map[phrase];
1666 return phrase;
1667 }
1668 /// Find the values for a given language data field, provided by the
1669 /// the [`languageData`](#state.EditorState^languageData) facet.
1670 languageDataAt(name, pos) {
1671 let values = [];
1672 for (let provider of this.facet(languageData)) {
1673 for (let result of provider(this, pos)) {
1674 if (Object.prototype.hasOwnProperty.call(result, name))
1675 values.push(result[name]);
1676 }
1677 }
1678 return values;
1679 }
1680 /// Return a function that can categorize strings (expected to
1681 /// represent a single [grapheme cluster](#text.findClusterBreak))
1682 /// into one of:
1683 ///
1684 /// - Word (contains an alphanumeric character or a character
1685 /// explicitly listed in the local language's `"wordChars"`
1686 /// language data, which should be a string)
1687 /// - Space (contains only whitespace)
1688 /// - Other (anything else)
1689 charCategorizer(at) {
1690 return makeCategorizer(this.languageDataAt("wordChars", at).join(""));
1691 }
1692}
1693/// A facet that, when enabled, causes the editor to allow multiple
1694/// ranges to be selected. Be careful though, because by default the
1695/// editor relies on the native DOM selection, which cannot handle
1696/// multiple selections. An extension like
1697/// [`drawSelection`](#view.drawSelection) can be used to make
1698/// secondary selections visible to the user.
1699EditorState.allowMultipleSelections = allowMultipleSelections;
1700/// Configures the tab size to use in this state. The first
1701/// (highest-precedence) value of the facet is used. If no value is
1702/// given, this defaults to 4.
1703EditorState.tabSize = Facet.define({
1704 combine: values => values.length ? values[0] : 4
1705});
1706/// The line separator to use. By default, any of `"\n"`, `"\r\n"`
1707/// and `"\r"` is treated as a separator when splitting lines, and
1708/// lines are joined with `"\n"`.
1709///
1710/// When you configure a value here, only that precise separator
1711/// will be used, allowing you to round-trip documents through the
1712/// editor without normalizing line separators.
1713EditorState.lineSeparator = lineSeparator;
1714/// Registers translation phrases. The
1715/// [`phrase`](#state.EditorState.phrase) method will look through
1716/// all objects registered with this facet to find translations for
1717/// its argument.
1718EditorState.phrases = Facet.define();
1719/// A facet used to register [language
1720/// data](#state.EditorState.languageDataAt) providers.
1721EditorState.languageData = languageData;
1722/// Facet used to register change filters, which are called for each
1723/// transaction (unless explicitly
1724/// [disabled](#state.TransactionSpec.filter)), and can suppress
1725/// part of the transaction's changes.
1726///
1727/// Such a function can return `true` to indicate that it doesn't
1728/// want to do anything, `false` to completely stop the changes in
1729/// the transaction, or a set of ranges in which changes should be
1730/// suppressed. Such ranges are represented as an array of numbers,
1731/// with each pair of two number indicating the start and end of a
1732/// range. So for example `[10, 20, 100, 110]` suppresses changes
1733/// between 10 and 20, and between 100 and 110.
1734EditorState.changeFilter = changeFilter;
1735/// Facet used to register a hook that gets a chance to update or
1736/// replace transaction specs before they are applied. This will
1737/// only be applied for transactions that don't have
1738/// [`filter`](#state.TransactionSpec.filter) set to `false`. You
1739/// can either return a single (possibly the input transaction), or
1740/// an array of specs (which will be combined in the same way as the
1741/// arguments to [`EditorState.update`](#state.EditorState.update)).
1742///
1743/// When possible, it is recommended to avoid accessing
1744/// [`Transaction.state`](#state.Transaction.state) in a filter,
1745/// since it will force creation of a state that will then be
1746/// discarded again, if the transaction is actually filtered.
1747///
1748/// (This functionality should be used with care. Indiscriminately
1749/// modifying transaction is likely to break something or degrade
1750/// the user experience.)
1751EditorState.transactionFilter = transactionFilter;
1752/// This is a more limited form of
1753/// [`transactionFilter`](#state.EditorState^transactionFilter),
1754/// which can only add
1755/// [annotations](#state.TransactionSpec.annotations),
1756/// [effects](#state.TransactionSpec.effects), and
1757/// [configuration](#state.TransactionSpec.reconfigure) info. _But_,
1758/// this type of filter runs even the transaction has disabled
1759/// regular [filtering](#state.TransactionSpec.filter), making it
1760/// suitable for effects that don't need to touch the changes or
1761/// selection, but do want to process every transaction.
1762///
1763/// Extenders run _after_ filters, when both are applied.
1764EditorState.transactionExtender = transactionExtender;
1765
1766/// Utility function for combining behaviors to fill in a config
1767/// object from an array of provided configs. Will, by default, error
1768/// when a field gets two values that aren't `===`-equal, but you can
1769/// provide combine functions per field to do something else.
1770function combineConfig(configs, defaults, // Should hold only the optional properties of Config, but I haven't managed to express that
1771combine = {}) {
1772 let result = {};
1773 for (let config of configs)
1774 for (let key of Object.keys(config)) {
1775 let value = config[key], current = result[key];
1776 if (current === undefined)
1777 result[key] = value;
1778 else if (current === value || value === undefined) ; // No conflict
1779 else if (Object.hasOwnProperty.call(combine, key))
1780 result[key] = combine[key](current, value);
1781 else
1782 throw new Error("Config merge conflict for field " + key);
1783 }
1784 for (let key in defaults)
1785 if (result[key] === undefined)
1786 result[key] = defaults[key];
1787 return result;
1788}
1789
1790export { Annotation, AnnotationType, ChangeDesc, ChangeSet, CharCategory, EditorSelection, EditorState, Facet, MapMode, Prec, SelectionRange, StateEffect, StateEffectType, StateField, Transaction, combineConfig, tagExtension };