@codemirror/state 0.19.9 → 0.20.0
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/CHANGELOG.md +20 -0
- package/dist/index.cjs +1611 -74
- package/dist/index.d.ts +509 -64
- package/dist/index.js +1581 -53
- package/package.json +1 -4
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,658 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
The data structure for documents. @nonabstract
|
|
7
|
+
*/
|
|
8
|
+
class Text {
|
|
9
|
+
/**
|
|
10
|
+
@internal
|
|
11
|
+
*/
|
|
12
|
+
constructor() { }
|
|
13
|
+
/**
|
|
14
|
+
Get the line description around the given position.
|
|
15
|
+
*/
|
|
16
|
+
lineAt(pos) {
|
|
17
|
+
if (pos < 0 || pos > this.length)
|
|
18
|
+
throw new RangeError(`Invalid position ${pos} in document of length ${this.length}`);
|
|
19
|
+
return this.lineInner(pos, false, 1, 0);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
Get the description for the given (1-based) line number.
|
|
23
|
+
*/
|
|
24
|
+
line(n) {
|
|
25
|
+
if (n < 1 || n > this.lines)
|
|
26
|
+
throw new RangeError(`Invalid line number ${n} in ${this.lines}-line document`);
|
|
27
|
+
return this.lineInner(n, true, 1, 0);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
Replace a range of the text with the given content.
|
|
31
|
+
*/
|
|
32
|
+
replace(from, to, text) {
|
|
33
|
+
let parts = [];
|
|
34
|
+
this.decompose(0, from, parts, 2 /* To */);
|
|
35
|
+
if (text.length)
|
|
36
|
+
text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */);
|
|
37
|
+
this.decompose(to, this.length, parts, 1 /* From */);
|
|
38
|
+
return TextNode.from(parts, this.length - (to - from) + text.length);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
Append another document to this one.
|
|
42
|
+
*/
|
|
43
|
+
append(other) {
|
|
44
|
+
return this.replace(this.length, this.length, other);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
Retrieve the text between the given points.
|
|
48
|
+
*/
|
|
49
|
+
slice(from, to = this.length) {
|
|
50
|
+
let parts = [];
|
|
51
|
+
this.decompose(from, to, parts, 0);
|
|
52
|
+
return TextNode.from(parts, to - from);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
Test whether this text is equal to another instance.
|
|
56
|
+
*/
|
|
57
|
+
eq(other) {
|
|
58
|
+
if (other == this)
|
|
59
|
+
return true;
|
|
60
|
+
if (other.length != this.length || other.lines != this.lines)
|
|
61
|
+
return false;
|
|
62
|
+
let start = this.scanIdentical(other, 1), end = this.length - this.scanIdentical(other, -1);
|
|
63
|
+
let a = new RawTextCursor(this), b = new RawTextCursor(other);
|
|
64
|
+
for (let skip = start, pos = start;;) {
|
|
65
|
+
a.next(skip);
|
|
66
|
+
b.next(skip);
|
|
67
|
+
skip = 0;
|
|
68
|
+
if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value)
|
|
69
|
+
return false;
|
|
70
|
+
pos += a.value.length;
|
|
71
|
+
if (a.done || pos >= end)
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
Iterate over the text. When `dir` is `-1`, iteration happens
|
|
77
|
+
from end to start. This will return lines and the breaks between
|
|
78
|
+
them as separate strings.
|
|
79
|
+
*/
|
|
80
|
+
iter(dir = 1) { return new RawTextCursor(this, dir); }
|
|
81
|
+
/**
|
|
82
|
+
Iterate over a range of the text. When `from` > `to`, the
|
|
83
|
+
iterator will run in reverse.
|
|
84
|
+
*/
|
|
85
|
+
iterRange(from, to = this.length) { return new PartialTextCursor(this, from, to); }
|
|
86
|
+
/**
|
|
87
|
+
Return a cursor that iterates over the given range of lines,
|
|
88
|
+
_without_ returning the line breaks between, and yielding empty
|
|
89
|
+
strings for empty lines.
|
|
90
|
+
|
|
91
|
+
When `from` and `to` are given, they should be 1-based line numbers.
|
|
92
|
+
*/
|
|
93
|
+
iterLines(from, to) {
|
|
94
|
+
let inner;
|
|
95
|
+
if (from == null) {
|
|
96
|
+
inner = this.iter();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
if (to == null)
|
|
100
|
+
to = this.lines + 1;
|
|
101
|
+
let start = this.line(from).from;
|
|
102
|
+
inner = this.iterRange(start, Math.max(start, to == this.lines + 1 ? this.length : to <= 1 ? 0 : this.line(to - 1).to));
|
|
103
|
+
}
|
|
104
|
+
return new LineCursor(inner);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
@internal
|
|
108
|
+
*/
|
|
109
|
+
toString() { return this.sliceString(0); }
|
|
110
|
+
/**
|
|
111
|
+
Convert the document to an array of lines (which can be
|
|
112
|
+
deserialized again via [`Text.of`](https://codemirror.net/6/docs/ref/#state.Text^of)).
|
|
113
|
+
*/
|
|
114
|
+
toJSON() {
|
|
115
|
+
let lines = [];
|
|
116
|
+
this.flatten(lines);
|
|
117
|
+
return lines;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
Create a `Text` instance for the given array of lines.
|
|
121
|
+
*/
|
|
122
|
+
static of(text) {
|
|
123
|
+
if (text.length == 0)
|
|
124
|
+
throw new RangeError("A document must have at least one line");
|
|
125
|
+
if (text.length == 1 && !text[0])
|
|
126
|
+
return Text.empty;
|
|
127
|
+
return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Leaves store an array of line strings. There are always line breaks
|
|
131
|
+
// between these strings. Leaves are limited in size and have to be
|
|
132
|
+
// contained in TextNode instances for bigger documents.
|
|
133
|
+
class TextLeaf extends Text {
|
|
134
|
+
constructor(text, length = textLength(text)) {
|
|
135
|
+
super();
|
|
136
|
+
this.text = text;
|
|
137
|
+
this.length = length;
|
|
138
|
+
}
|
|
139
|
+
get lines() { return this.text.length; }
|
|
140
|
+
get children() { return null; }
|
|
141
|
+
lineInner(target, isLine, line, offset) {
|
|
142
|
+
for (let i = 0;; i++) {
|
|
143
|
+
let string = this.text[i], end = offset + string.length;
|
|
144
|
+
if ((isLine ? line : end) >= target)
|
|
145
|
+
return new Line(offset, end, line, string);
|
|
146
|
+
offset = end + 1;
|
|
147
|
+
line++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
decompose(from, to, target, open) {
|
|
151
|
+
let text = from <= 0 && to >= this.length ? this
|
|
152
|
+
: new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from));
|
|
153
|
+
if (open & 1 /* From */) {
|
|
154
|
+
let prev = target.pop();
|
|
155
|
+
let joined = appendText(text.text, prev.text.slice(), 0, text.length);
|
|
156
|
+
if (joined.length <= 32 /* Branch */) {
|
|
157
|
+
target.push(new TextLeaf(joined, prev.length + text.length));
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
let mid = joined.length >> 1;
|
|
161
|
+
target.push(new TextLeaf(joined.slice(0, mid)), new TextLeaf(joined.slice(mid)));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
target.push(text);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
replace(from, to, text) {
|
|
169
|
+
if (!(text instanceof TextLeaf))
|
|
170
|
+
return super.replace(from, to, text);
|
|
171
|
+
let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to);
|
|
172
|
+
let newLen = this.length + text.length - (to - from);
|
|
173
|
+
if (lines.length <= 32 /* Branch */)
|
|
174
|
+
return new TextLeaf(lines, newLen);
|
|
175
|
+
return TextNode.from(TextLeaf.split(lines, []), newLen);
|
|
176
|
+
}
|
|
177
|
+
sliceString(from, to = this.length, lineSep = "\n") {
|
|
178
|
+
let result = "";
|
|
179
|
+
for (let pos = 0, i = 0; pos <= to && i < this.text.length; i++) {
|
|
180
|
+
let line = this.text[i], end = pos + line.length;
|
|
181
|
+
if (pos > from && i)
|
|
182
|
+
result += lineSep;
|
|
183
|
+
if (from < end && to > pos)
|
|
184
|
+
result += line.slice(Math.max(0, from - pos), to - pos);
|
|
185
|
+
pos = end + 1;
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
flatten(target) {
|
|
190
|
+
for (let line of this.text)
|
|
191
|
+
target.push(line);
|
|
192
|
+
}
|
|
193
|
+
scanIdentical() { return 0; }
|
|
194
|
+
static split(text, target) {
|
|
195
|
+
let part = [], len = -1;
|
|
196
|
+
for (let line of text) {
|
|
197
|
+
part.push(line);
|
|
198
|
+
len += line.length + 1;
|
|
199
|
+
if (part.length == 32 /* Branch */) {
|
|
200
|
+
target.push(new TextLeaf(part, len));
|
|
201
|
+
part = [];
|
|
202
|
+
len = -1;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (len > -1)
|
|
206
|
+
target.push(new TextLeaf(part, len));
|
|
207
|
+
return target;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Nodes provide the tree structure of the `Text` type. They store a
|
|
211
|
+
// number of other nodes or leaves, taking care to balance themselves
|
|
212
|
+
// on changes. There are implied line breaks _between_ the children of
|
|
213
|
+
// a node (but not before the first or after the last child).
|
|
214
|
+
class TextNode extends Text {
|
|
215
|
+
constructor(children, length) {
|
|
216
|
+
super();
|
|
217
|
+
this.children = children;
|
|
218
|
+
this.length = length;
|
|
219
|
+
this.lines = 0;
|
|
220
|
+
for (let child of children)
|
|
221
|
+
this.lines += child.lines;
|
|
222
|
+
}
|
|
223
|
+
lineInner(target, isLine, line, offset) {
|
|
224
|
+
for (let i = 0;; i++) {
|
|
225
|
+
let child = this.children[i], end = offset + child.length, endLine = line + child.lines - 1;
|
|
226
|
+
if ((isLine ? endLine : end) >= target)
|
|
227
|
+
return child.lineInner(target, isLine, line, offset);
|
|
228
|
+
offset = end + 1;
|
|
229
|
+
line = endLine + 1;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
decompose(from, to, target, open) {
|
|
233
|
+
for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) {
|
|
234
|
+
let child = this.children[i], end = pos + child.length;
|
|
235
|
+
if (from <= end && to >= pos) {
|
|
236
|
+
let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0));
|
|
237
|
+
if (pos >= from && end <= to && !childOpen)
|
|
238
|
+
target.push(child);
|
|
239
|
+
else
|
|
240
|
+
child.decompose(from - pos, to - pos, target, childOpen);
|
|
241
|
+
}
|
|
242
|
+
pos = end + 1;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
replace(from, to, text) {
|
|
246
|
+
if (text.lines < this.lines)
|
|
247
|
+
for (let i = 0, pos = 0; i < this.children.length; i++) {
|
|
248
|
+
let child = this.children[i], end = pos + child.length;
|
|
249
|
+
// Fast path: if the change only affects one child and the
|
|
250
|
+
// child's size remains in the acceptable range, only update
|
|
251
|
+
// that child
|
|
252
|
+
if (from >= pos && to <= end) {
|
|
253
|
+
let updated = child.replace(from - pos, to - pos, text);
|
|
254
|
+
let totalLines = this.lines - child.lines + updated.lines;
|
|
255
|
+
if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) &&
|
|
256
|
+
updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) {
|
|
257
|
+
let copy = this.children.slice();
|
|
258
|
+
copy[i] = updated;
|
|
259
|
+
return new TextNode(copy, this.length - (to - from) + text.length);
|
|
260
|
+
}
|
|
261
|
+
return super.replace(pos, end, updated);
|
|
262
|
+
}
|
|
263
|
+
pos = end + 1;
|
|
264
|
+
}
|
|
265
|
+
return super.replace(from, to, text);
|
|
266
|
+
}
|
|
267
|
+
sliceString(from, to = this.length, lineSep = "\n") {
|
|
268
|
+
let result = "";
|
|
269
|
+
for (let i = 0, pos = 0; i < this.children.length && pos <= to; i++) {
|
|
270
|
+
let child = this.children[i], end = pos + child.length;
|
|
271
|
+
if (pos > from && i)
|
|
272
|
+
result += lineSep;
|
|
273
|
+
if (from < end && to > pos)
|
|
274
|
+
result += child.sliceString(from - pos, to - pos, lineSep);
|
|
275
|
+
pos = end + 1;
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
flatten(target) {
|
|
280
|
+
for (let child of this.children)
|
|
281
|
+
child.flatten(target);
|
|
282
|
+
}
|
|
283
|
+
scanIdentical(other, dir) {
|
|
284
|
+
if (!(other instanceof TextNode))
|
|
285
|
+
return 0;
|
|
286
|
+
let length = 0;
|
|
287
|
+
let [iA, iB, eA, eB] = dir > 0 ? [0, 0, this.children.length, other.children.length]
|
|
288
|
+
: [this.children.length - 1, other.children.length - 1, -1, -1];
|
|
289
|
+
for (;; iA += dir, iB += dir) {
|
|
290
|
+
if (iA == eA || iB == eB)
|
|
291
|
+
return length;
|
|
292
|
+
let chA = this.children[iA], chB = other.children[iB];
|
|
293
|
+
if (chA != chB)
|
|
294
|
+
return length + chA.scanIdentical(chB, dir);
|
|
295
|
+
length += chA.length + 1;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
static from(children, length = children.reduce((l, ch) => l + ch.length + 1, -1)) {
|
|
299
|
+
let lines = 0;
|
|
300
|
+
for (let ch of children)
|
|
301
|
+
lines += ch.lines;
|
|
302
|
+
if (lines < 32 /* Branch */) {
|
|
303
|
+
let flat = [];
|
|
304
|
+
for (let ch of children)
|
|
305
|
+
ch.flatten(flat);
|
|
306
|
+
return new TextLeaf(flat, length);
|
|
307
|
+
}
|
|
308
|
+
let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
|
309
|
+
let chunked = [], currentLines = 0, currentLen = -1, currentChunk = [];
|
|
310
|
+
function add(child) {
|
|
311
|
+
let last;
|
|
312
|
+
if (child.lines > maxChunk && child instanceof TextNode) {
|
|
313
|
+
for (let node of child.children)
|
|
314
|
+
add(node);
|
|
315
|
+
}
|
|
316
|
+
else if (child.lines > minChunk && (currentLines > minChunk || !currentLines)) {
|
|
317
|
+
flush();
|
|
318
|
+
chunked.push(child);
|
|
319
|
+
}
|
|
320
|
+
else if (child instanceof TextLeaf && currentLines &&
|
|
321
|
+
(last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf &&
|
|
322
|
+
child.lines + last.lines <= 32 /* Branch */) {
|
|
323
|
+
currentLines += child.lines;
|
|
324
|
+
currentLen += child.length + 1;
|
|
325
|
+
currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
if (currentLines + child.lines > chunk)
|
|
329
|
+
flush();
|
|
330
|
+
currentLines += child.lines;
|
|
331
|
+
currentLen += child.length + 1;
|
|
332
|
+
currentChunk.push(child);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function flush() {
|
|
336
|
+
if (currentLines == 0)
|
|
337
|
+
return;
|
|
338
|
+
chunked.push(currentChunk.length == 1 ? currentChunk[0] : TextNode.from(currentChunk, currentLen));
|
|
339
|
+
currentLen = -1;
|
|
340
|
+
currentLines = currentChunk.length = 0;
|
|
341
|
+
}
|
|
342
|
+
for (let child of children)
|
|
343
|
+
add(child);
|
|
344
|
+
flush();
|
|
345
|
+
return chunked.length == 1 ? chunked[0] : new TextNode(chunked, length);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
Text.empty = new TextLeaf([""], 0);
|
|
349
|
+
function textLength(text) {
|
|
350
|
+
let length = -1;
|
|
351
|
+
for (let line of text)
|
|
352
|
+
length += line.length + 1;
|
|
353
|
+
return length;
|
|
354
|
+
}
|
|
355
|
+
function appendText(text, target, from = 0, to = 1e9) {
|
|
356
|
+
for (let pos = 0, i = 0, first = true; i < text.length && pos <= to; i++) {
|
|
357
|
+
let line = text[i], end = pos + line.length;
|
|
358
|
+
if (end >= from) {
|
|
359
|
+
if (end > to)
|
|
360
|
+
line = line.slice(0, to - pos);
|
|
361
|
+
if (pos < from)
|
|
362
|
+
line = line.slice(from - pos);
|
|
363
|
+
if (first) {
|
|
364
|
+
target[target.length - 1] += line;
|
|
365
|
+
first = false;
|
|
366
|
+
}
|
|
367
|
+
else
|
|
368
|
+
target.push(line);
|
|
369
|
+
}
|
|
370
|
+
pos = end + 1;
|
|
371
|
+
}
|
|
372
|
+
return target;
|
|
373
|
+
}
|
|
374
|
+
function sliceText(text, from, to) {
|
|
375
|
+
return appendText(text, [""], from, to);
|
|
376
|
+
}
|
|
377
|
+
class RawTextCursor {
|
|
378
|
+
constructor(text, dir = 1) {
|
|
379
|
+
this.dir = dir;
|
|
380
|
+
this.done = false;
|
|
381
|
+
this.lineBreak = false;
|
|
382
|
+
this.value = "";
|
|
383
|
+
this.nodes = [text];
|
|
384
|
+
this.offsets = [dir > 0 ? 1 : (text instanceof TextLeaf ? text.text.length : text.children.length) << 1];
|
|
385
|
+
}
|
|
386
|
+
nextInner(skip, dir) {
|
|
387
|
+
this.done = this.lineBreak = false;
|
|
388
|
+
for (;;) {
|
|
389
|
+
let last = this.nodes.length - 1;
|
|
390
|
+
let top = this.nodes[last], offsetValue = this.offsets[last], offset = offsetValue >> 1;
|
|
391
|
+
let size = top instanceof TextLeaf ? top.text.length : top.children.length;
|
|
392
|
+
if (offset == (dir > 0 ? size : 0)) {
|
|
393
|
+
if (last == 0) {
|
|
394
|
+
this.done = true;
|
|
395
|
+
this.value = "";
|
|
396
|
+
return this;
|
|
397
|
+
}
|
|
398
|
+
if (dir > 0)
|
|
399
|
+
this.offsets[last - 1]++;
|
|
400
|
+
this.nodes.pop();
|
|
401
|
+
this.offsets.pop();
|
|
402
|
+
}
|
|
403
|
+
else if ((offsetValue & 1) == (dir > 0 ? 0 : 1)) {
|
|
404
|
+
this.offsets[last] += dir;
|
|
405
|
+
if (skip == 0) {
|
|
406
|
+
this.lineBreak = true;
|
|
407
|
+
this.value = "\n";
|
|
408
|
+
return this;
|
|
409
|
+
}
|
|
410
|
+
skip--;
|
|
411
|
+
}
|
|
412
|
+
else if (top instanceof TextLeaf) {
|
|
413
|
+
// Move to the next string
|
|
414
|
+
let next = top.text[offset + (dir < 0 ? -1 : 0)];
|
|
415
|
+
this.offsets[last] += dir;
|
|
416
|
+
if (next.length > Math.max(0, skip)) {
|
|
417
|
+
this.value = skip == 0 ? next : dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip);
|
|
418
|
+
return this;
|
|
419
|
+
}
|
|
420
|
+
skip -= next.length;
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
let next = top.children[offset + (dir < 0 ? -1 : 0)];
|
|
424
|
+
if (skip > next.length) {
|
|
425
|
+
skip -= next.length;
|
|
426
|
+
this.offsets[last] += dir;
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
if (dir < 0)
|
|
430
|
+
this.offsets[last]--;
|
|
431
|
+
this.nodes.push(next);
|
|
432
|
+
this.offsets.push(dir > 0 ? 1 : (next instanceof TextLeaf ? next.text.length : next.children.length) << 1);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
next(skip = 0) {
|
|
438
|
+
if (skip < 0) {
|
|
439
|
+
this.nextInner(-skip, (-this.dir));
|
|
440
|
+
skip = this.value.length;
|
|
441
|
+
}
|
|
442
|
+
return this.nextInner(skip, this.dir);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
class PartialTextCursor {
|
|
446
|
+
constructor(text, start, end) {
|
|
447
|
+
this.value = "";
|
|
448
|
+
this.done = false;
|
|
449
|
+
this.cursor = new RawTextCursor(text, start > end ? -1 : 1);
|
|
450
|
+
this.pos = start > end ? text.length : 0;
|
|
451
|
+
this.from = Math.min(start, end);
|
|
452
|
+
this.to = Math.max(start, end);
|
|
453
|
+
}
|
|
454
|
+
nextInner(skip, dir) {
|
|
455
|
+
if (dir < 0 ? this.pos <= this.from : this.pos >= this.to) {
|
|
456
|
+
this.value = "";
|
|
457
|
+
this.done = true;
|
|
458
|
+
return this;
|
|
459
|
+
}
|
|
460
|
+
skip += Math.max(0, dir < 0 ? this.pos - this.to : this.from - this.pos);
|
|
461
|
+
let limit = dir < 0 ? this.pos - this.from : this.to - this.pos;
|
|
462
|
+
if (skip > limit)
|
|
463
|
+
skip = limit;
|
|
464
|
+
limit -= skip;
|
|
465
|
+
let { value } = this.cursor.next(skip);
|
|
466
|
+
this.pos += (value.length + skip) * dir;
|
|
467
|
+
this.value = value.length <= limit ? value : dir < 0 ? value.slice(value.length - limit) : value.slice(0, limit);
|
|
468
|
+
this.done = !this.value;
|
|
469
|
+
return this;
|
|
470
|
+
}
|
|
471
|
+
next(skip = 0) {
|
|
472
|
+
if (skip < 0)
|
|
473
|
+
skip = Math.max(skip, this.from - this.pos);
|
|
474
|
+
else if (skip > 0)
|
|
475
|
+
skip = Math.min(skip, this.to - this.pos);
|
|
476
|
+
return this.nextInner(skip, this.cursor.dir);
|
|
477
|
+
}
|
|
478
|
+
get lineBreak() { return this.cursor.lineBreak && this.value != ""; }
|
|
479
|
+
}
|
|
480
|
+
class LineCursor {
|
|
481
|
+
constructor(inner) {
|
|
482
|
+
this.inner = inner;
|
|
483
|
+
this.afterBreak = true;
|
|
484
|
+
this.value = "";
|
|
485
|
+
this.done = false;
|
|
486
|
+
}
|
|
487
|
+
next(skip = 0) {
|
|
488
|
+
let { done, lineBreak, value } = this.inner.next(skip);
|
|
489
|
+
if (done) {
|
|
490
|
+
this.done = true;
|
|
491
|
+
this.value = "";
|
|
492
|
+
}
|
|
493
|
+
else if (lineBreak) {
|
|
494
|
+
if (this.afterBreak) {
|
|
495
|
+
this.value = "";
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
this.afterBreak = true;
|
|
499
|
+
this.next();
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
this.value = value;
|
|
504
|
+
this.afterBreak = false;
|
|
505
|
+
}
|
|
506
|
+
return this;
|
|
507
|
+
}
|
|
508
|
+
get lineBreak() { return false; }
|
|
509
|
+
}
|
|
510
|
+
if (typeof Symbol != "undefined") {
|
|
511
|
+
Text.prototype[Symbol.iterator] = function () { return this.iter(); };
|
|
512
|
+
RawTextCursor.prototype[Symbol.iterator] = PartialTextCursor.prototype[Symbol.iterator] =
|
|
513
|
+
LineCursor.prototype[Symbol.iterator] = function () { return this; };
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
This type describes a line in the document. It is created
|
|
517
|
+
on-demand when lines are [queried](https://codemirror.net/6/docs/ref/#state.Text.lineAt).
|
|
518
|
+
*/
|
|
519
|
+
class Line {
|
|
520
|
+
/**
|
|
521
|
+
@internal
|
|
522
|
+
*/
|
|
523
|
+
constructor(
|
|
524
|
+
/**
|
|
525
|
+
The position of the start of the line.
|
|
526
|
+
*/
|
|
527
|
+
from,
|
|
528
|
+
/**
|
|
529
|
+
The position at the end of the line (_before_ the line break,
|
|
530
|
+
or at the end of document for the last line).
|
|
531
|
+
*/
|
|
532
|
+
to,
|
|
533
|
+
/**
|
|
534
|
+
This line's line number (1-based).
|
|
535
|
+
*/
|
|
536
|
+
number,
|
|
537
|
+
/**
|
|
538
|
+
The line's content.
|
|
539
|
+
*/
|
|
540
|
+
text) {
|
|
541
|
+
this.from = from;
|
|
542
|
+
this.to = to;
|
|
543
|
+
this.number = number;
|
|
544
|
+
this.text = text;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
The length of the line (not including any line break after it).
|
|
548
|
+
*/
|
|
549
|
+
get length() { return this.to - this.from; }
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Compressed representation of the Grapheme_Cluster_Break=Extend
|
|
553
|
+
// information from
|
|
554
|
+
// http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt.
|
|
555
|
+
// Each pair of elements represents a range, as an offet from the
|
|
556
|
+
// previous range and a length. Numbers are in base-36, with the empty
|
|
557
|
+
// string being a shorthand for 1.
|
|
558
|
+
let extend = "lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map(s => s ? parseInt(s, 36) : 1);
|
|
559
|
+
// Convert offsets into absolute values
|
|
560
|
+
for (let i = 1; i < extend.length; i++)
|
|
561
|
+
extend[i] += extend[i - 1];
|
|
562
|
+
function isExtendingChar(code) {
|
|
563
|
+
for (let i = 1; i < extend.length; i += 2)
|
|
564
|
+
if (extend[i] > code)
|
|
565
|
+
return extend[i - 1] <= code;
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
function isRegionalIndicator(code) {
|
|
569
|
+
return code >= 0x1F1E6 && code <= 0x1F1FF;
|
|
570
|
+
}
|
|
571
|
+
const ZWJ = 0x200d;
|
|
572
|
+
/**
|
|
573
|
+
Returns a next grapheme cluster break _after_ (not equal to)
|
|
574
|
+
`pos`, if `forward` is true, or before otherwise. Returns `pos`
|
|
575
|
+
itself if no further cluster break is available in the string.
|
|
576
|
+
Moves across surrogate pairs, extending characters (when
|
|
577
|
+
`includeExtending` is true), characters joined with zero-width
|
|
578
|
+
joiners, and flag emoji.
|
|
579
|
+
*/
|
|
580
|
+
function findClusterBreak(str, pos, forward = true, includeExtending = true) {
|
|
581
|
+
return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending);
|
|
582
|
+
}
|
|
583
|
+
function nextClusterBreak(str, pos, includeExtending) {
|
|
584
|
+
if (pos == str.length)
|
|
585
|
+
return pos;
|
|
586
|
+
// If pos is in the middle of a surrogate pair, move to its start
|
|
587
|
+
if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1)))
|
|
588
|
+
pos--;
|
|
589
|
+
let prev = codePointAt(str, pos);
|
|
590
|
+
pos += codePointSize(prev);
|
|
591
|
+
while (pos < str.length) {
|
|
592
|
+
let next = codePointAt(str, pos);
|
|
593
|
+
if (prev == ZWJ || next == ZWJ || includeExtending && isExtendingChar(next)) {
|
|
594
|
+
pos += codePointSize(next);
|
|
595
|
+
prev = next;
|
|
596
|
+
}
|
|
597
|
+
else if (isRegionalIndicator(next)) {
|
|
598
|
+
let countBefore = 0, i = pos - 2;
|
|
599
|
+
while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) {
|
|
600
|
+
countBefore++;
|
|
601
|
+
i -= 2;
|
|
602
|
+
}
|
|
603
|
+
if (countBefore % 2 == 0)
|
|
604
|
+
break;
|
|
605
|
+
else
|
|
606
|
+
pos += 2;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return pos;
|
|
613
|
+
}
|
|
614
|
+
function prevClusterBreak(str, pos, includeExtending) {
|
|
615
|
+
while (pos > 0) {
|
|
616
|
+
let found = nextClusterBreak(str, pos - 2, includeExtending);
|
|
617
|
+
if (found < pos)
|
|
618
|
+
return found;
|
|
619
|
+
pos--;
|
|
620
|
+
}
|
|
621
|
+
return 0;
|
|
622
|
+
}
|
|
623
|
+
function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
|
|
624
|
+
function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
|
|
625
|
+
/**
|
|
626
|
+
Find the code point at the given position in a string (like the
|
|
627
|
+
[`codePointAt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt)
|
|
628
|
+
string method).
|
|
629
|
+
*/
|
|
630
|
+
function codePointAt(str, pos) {
|
|
631
|
+
let code0 = str.charCodeAt(pos);
|
|
632
|
+
if (!surrogateHigh(code0) || pos + 1 == str.length)
|
|
633
|
+
return code0;
|
|
634
|
+
let code1 = str.charCodeAt(pos + 1);
|
|
635
|
+
if (!surrogateLow(code1))
|
|
636
|
+
return code0;
|
|
637
|
+
return ((code0 - 0xd800) << 10) + (code1 - 0xdc00) + 0x10000;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
Given a Unicode codepoint, return the JavaScript string that
|
|
641
|
+
respresents it (like
|
|
642
|
+
[`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)).
|
|
643
|
+
*/
|
|
644
|
+
function fromCodePoint(code) {
|
|
645
|
+
if (code <= 0xffff)
|
|
646
|
+
return String.fromCharCode(code);
|
|
647
|
+
code -= 0x10000;
|
|
648
|
+
return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
The first character that takes up two positions in a JavaScript
|
|
652
|
+
string. It is often useful to compare with this after calling
|
|
653
|
+
`codePointAt`, to figure out whether your character takes up 1 or
|
|
654
|
+
2 index positions.
|
|
655
|
+
*/
|
|
656
|
+
function codePointSize(code) { return code < 0x10000 ? 1 : 2; }
|
|
6
657
|
|
|
7
658
|
const DefaultSplit = /\r\n?|\n/;
|
|
8
659
|
/**
|
|
@@ -74,7 +725,9 @@ class ChangeDesc {
|
|
|
74
725
|
*/
|
|
75
726
|
get empty() { return this.sections.length == 0 || this.sections.length == 2 && this.sections[1] < 0; }
|
|
76
727
|
/**
|
|
77
|
-
Iterate over the unchanged parts left by these changes.
|
|
728
|
+
Iterate over the unchanged parts left by these changes. `posA`
|
|
729
|
+
provides the position of the range in the old document, `posB`
|
|
730
|
+
the new position in the changed document.
|
|
78
731
|
*/
|
|
79
732
|
iterGaps(f) {
|
|
80
733
|
for (let i = 0, posA = 0, posB = 0; i < this.sections.length;) {
|
|
@@ -93,6 +746,9 @@ class ChangeDesc {
|
|
|
93
746
|
Iterate over the ranges changed by these changes. (See
|
|
94
747
|
[`ChangeSet.iterChanges`](https://codemirror.net/6/docs/ref/#state.ChangeSet.iterChanges) for a
|
|
95
748
|
variant that also provides you with the inserted text.)
|
|
749
|
+
`fromA`/`toA` provides the extent of the change in the starting
|
|
750
|
+
document, `fromB`/`toB` the extent of the replacement in the
|
|
751
|
+
changed document.
|
|
96
752
|
|
|
97
753
|
When `individual` is true, adjacent changes (which are kept
|
|
98
754
|
separate for [position mapping](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) are
|
|
@@ -235,8 +891,8 @@ class ChangeSet extends ChangeDesc {
|
|
|
235
891
|
sections[i + 1] = len;
|
|
236
892
|
let index = i >> 1;
|
|
237
893
|
while (inserted.length < index)
|
|
238
|
-
inserted.push(
|
|
239
|
-
inserted.push(len ? doc.slice(pos, pos + len) :
|
|
894
|
+
inserted.push(Text.empty);
|
|
895
|
+
inserted.push(len ? doc.slice(pos, pos + len) : Text.empty);
|
|
240
896
|
}
|
|
241
897
|
pos += len;
|
|
242
898
|
}
|
|
@@ -363,7 +1019,7 @@ class ChangeSet extends ChangeDesc {
|
|
|
363
1019
|
let { from, to = from, insert } = spec;
|
|
364
1020
|
if (from > to || from < 0 || to > length)
|
|
365
1021
|
throw new RangeError(`Invalid change range ${from} to ${to} (in doc of length ${length})`);
|
|
366
|
-
let insText = !insert ?
|
|
1022
|
+
let insText = !insert ? Text.empty : typeof insert == "string" ? Text.of(insert.split(lineSep || DefaultSplit)) : insert;
|
|
367
1023
|
let insLen = insText.length;
|
|
368
1024
|
if (from == to && insLen == 0)
|
|
369
1025
|
return;
|
|
@@ -407,8 +1063,8 @@ class ChangeSet extends ChangeDesc {
|
|
|
407
1063
|
}
|
|
408
1064
|
else {
|
|
409
1065
|
while (inserted.length < i)
|
|
410
|
-
inserted.push(
|
|
411
|
-
inserted[i] =
|
|
1066
|
+
inserted.push(Text.empty);
|
|
1067
|
+
inserted[i] = Text.of(part.slice(1));
|
|
412
1068
|
sections.push(part[0], inserted[i].length);
|
|
413
1069
|
}
|
|
414
1070
|
}
|
|
@@ -439,7 +1095,7 @@ function addInsert(values, sections, value) {
|
|
|
439
1095
|
}
|
|
440
1096
|
else {
|
|
441
1097
|
while (values.length < index)
|
|
442
|
-
values.push(
|
|
1098
|
+
values.push(Text.empty);
|
|
443
1099
|
values.push(value);
|
|
444
1100
|
}
|
|
445
1101
|
}
|
|
@@ -452,18 +1108,18 @@ function iterChanges(desc, f, individual) {
|
|
|
452
1108
|
posB += len;
|
|
453
1109
|
}
|
|
454
1110
|
else {
|
|
455
|
-
let endA = posA, endB = posB, text
|
|
1111
|
+
let endA = posA, endB = posB, text = Text.empty;
|
|
456
1112
|
for (;;) {
|
|
457
1113
|
endA += len;
|
|
458
1114
|
endB += ins;
|
|
459
1115
|
if (ins && inserted)
|
|
460
|
-
text
|
|
1116
|
+
text = text.append(inserted[(i - 2) >> 1]);
|
|
461
1117
|
if (individual || i == desc.sections.length || desc.sections[i + 1] < 0)
|
|
462
1118
|
break;
|
|
463
1119
|
len = desc.sections[i++];
|
|
464
1120
|
ins = desc.sections[i++];
|
|
465
1121
|
}
|
|
466
|
-
f(posA, endA, posB, endB, text
|
|
1122
|
+
f(posA, endA, posB, endB, text);
|
|
467
1123
|
posA = endA;
|
|
468
1124
|
posB = endB;
|
|
469
1125
|
}
|
|
@@ -591,11 +1247,11 @@ class SectionIter {
|
|
|
591
1247
|
get len2() { return this.ins < 0 ? this.len : this.ins; }
|
|
592
1248
|
get text() {
|
|
593
1249
|
let { inserted } = this.set, index = (this.i - 2) >> 1;
|
|
594
|
-
return index >= inserted.length ?
|
|
1250
|
+
return index >= inserted.length ? Text.empty : inserted[index];
|
|
595
1251
|
}
|
|
596
1252
|
textBit(len) {
|
|
597
1253
|
let { inserted } = this.set, index = (this.i - 2) >> 1;
|
|
598
|
-
return index >= inserted.length && !len ?
|
|
1254
|
+
return index >= inserted.length && !len ? Text.empty
|
|
599
1255
|
: inserted[index].slice(this.off, len == null ? undefined : this.off + len);
|
|
600
1256
|
}
|
|
601
1257
|
forward(len) {
|
|
@@ -875,10 +1531,10 @@ A facet is a labeled value that is associated with an editor
|
|
|
875
1531
|
state. It takes inputs from any number of extensions, and combines
|
|
876
1532
|
those into a single output value.
|
|
877
1533
|
|
|
878
|
-
Examples of facets are the [
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1534
|
+
Examples of uses of facets are the [tab
|
|
1535
|
+
size](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize), [editor
|
|
1536
|
+
attributes](https://codemirror.net/6/docs/ref/#view.EditorView^editorAttributes), and [update
|
|
1537
|
+
listeners](https://codemirror.net/6/docs/ref/#view.EditorView^updateListener).
|
|
882
1538
|
*/
|
|
883
1539
|
class Facet {
|
|
884
1540
|
constructor(
|
|
@@ -916,7 +1572,7 @@ class Facet {
|
|
|
916
1572
|
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);
|
|
917
1573
|
}
|
|
918
1574
|
/**
|
|
919
|
-
Returns an extension that adds the given value
|
|
1575
|
+
Returns an extension that adds the given value to this facet.
|
|
920
1576
|
*/
|
|
921
1577
|
of(value) {
|
|
922
1578
|
return new FacetProvider([], this, 0 /* Static */, value);
|
|
@@ -927,9 +1583,8 @@ class Facet {
|
|
|
927
1583
|
this value depends on, since your function is only called again
|
|
928
1584
|
for a new state when one of those parts changed.
|
|
929
1585
|
|
|
930
|
-
In
|
|
931
|
-
[`
|
|
932
|
-
defining a field instead.
|
|
1586
|
+
In cases where your value depends only on a single field, you'll
|
|
1587
|
+
want to use the [`from`](https://codemirror.net/6/docs/ref/#state.Facet.from) method instead.
|
|
933
1588
|
*/
|
|
934
1589
|
compute(deps, get) {
|
|
935
1590
|
if (this.isStatic)
|
|
@@ -982,8 +1637,7 @@ class FacetProvider {
|
|
|
982
1637
|
return 1 /* Changed */;
|
|
983
1638
|
},
|
|
984
1639
|
update(state, tr) {
|
|
985
|
-
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) ||
|
|
986
|
-
depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0)) {
|
|
1640
|
+
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) {
|
|
987
1641
|
let newVal = getter(state);
|
|
988
1642
|
if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) {
|
|
989
1643
|
state.values[idx] = newVal;
|
|
@@ -992,12 +1646,15 @@ class FacetProvider {
|
|
|
992
1646
|
}
|
|
993
1647
|
return 0;
|
|
994
1648
|
},
|
|
995
|
-
reconfigure(state, oldState) {
|
|
1649
|
+
reconfigure: (state, oldState) => {
|
|
996
1650
|
let newVal = getter(state);
|
|
997
1651
|
let oldAddr = oldState.config.address[id];
|
|
998
1652
|
if (oldAddr != null) {
|
|
999
1653
|
let oldVal = getAddr(oldState, oldAddr);
|
|
1000
|
-
if (
|
|
1654
|
+
if (this.dependencies.every(dep => {
|
|
1655
|
+
return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) :
|
|
1656
|
+
dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true;
|
|
1657
|
+
}) || (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))) {
|
|
1001
1658
|
state.values[idx] = oldVal;
|
|
1002
1659
|
return 0;
|
|
1003
1660
|
}
|
|
@@ -1016,6 +1673,13 @@ function compareArray(a, b, compare) {
|
|
|
1016
1673
|
return false;
|
|
1017
1674
|
return true;
|
|
1018
1675
|
}
|
|
1676
|
+
function ensureAll(state, addrs) {
|
|
1677
|
+
let changed = false;
|
|
1678
|
+
for (let addr of addrs)
|
|
1679
|
+
if (ensureAddr(state, addr) & 1 /* Changed */)
|
|
1680
|
+
changed = true;
|
|
1681
|
+
return changed;
|
|
1682
|
+
}
|
|
1019
1683
|
function dynamicFacetSlot(addresses, facet, providers) {
|
|
1020
1684
|
let providerAddrs = providers.map(p => addresses[p.id]);
|
|
1021
1685
|
let providerTypes = providers.map(p => p.type);
|
|
@@ -1041,7 +1705,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|
|
1041
1705
|
return 1 /* Changed */;
|
|
1042
1706
|
},
|
|
1043
1707
|
update(state, tr) {
|
|
1044
|
-
if (!
|
|
1708
|
+
if (!ensureAll(state, dynamic))
|
|
1045
1709
|
return 0;
|
|
1046
1710
|
let value = get(state);
|
|
1047
1711
|
if (facet.compare(value, state.values[idx]))
|
|
@@ -1050,7 +1714,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|
|
1050
1714
|
return 1 /* Changed */;
|
|
1051
1715
|
},
|
|
1052
1716
|
reconfigure(state, oldState) {
|
|
1053
|
-
let depChanged =
|
|
1717
|
+
let depChanged = ensureAll(state, providerAddrs);
|
|
1054
1718
|
let oldProviders = oldState.config.facets[facet.id], oldValue = oldState.facet(facet);
|
|
1055
1719
|
if (oldProviders && !depChanged && sameArray(providers, oldProviders)) {
|
|
1056
1720
|
state.values[idx] = oldValue;
|
|
@@ -1163,42 +1827,29 @@ precedence and then by order within each precedence.
|
|
|
1163
1827
|
*/
|
|
1164
1828
|
const Prec = {
|
|
1165
1829
|
/**
|
|
1166
|
-
The
|
|
1167
|
-
near the
|
|
1168
|
-
*/
|
|
1169
|
-
lowest: prec(Prec_.lowest),
|
|
1170
|
-
/**
|
|
1171
|
-
A lower-than-default precedence, for extensions.
|
|
1172
|
-
*/
|
|
1173
|
-
low: prec(Prec_.low),
|
|
1174
|
-
/**
|
|
1175
|
-
The default precedence, which is also used for extensions
|
|
1176
|
-
without an explicit precedence.
|
|
1830
|
+
The highest precedence level, for extensions that should end up
|
|
1831
|
+
near the start of the precedence ordering.
|
|
1177
1832
|
*/
|
|
1178
|
-
|
|
1833
|
+
highest: prec(Prec_.highest),
|
|
1179
1834
|
/**
|
|
1180
1835
|
A higher-than-default precedence, for extensions that should
|
|
1181
1836
|
come before those with default precedence.
|
|
1182
1837
|
*/
|
|
1183
1838
|
high: prec(Prec_.high),
|
|
1184
1839
|
/**
|
|
1185
|
-
The
|
|
1186
|
-
|
|
1187
|
-
*/
|
|
1188
|
-
highest: prec(Prec_.highest),
|
|
1189
|
-
// FIXME Drop these in some future breaking version
|
|
1190
|
-
/**
|
|
1191
|
-
Backwards-compatible synonym for `Prec.lowest`.
|
|
1840
|
+
The default precedence, which is also used for extensions
|
|
1841
|
+
without an explicit precedence.
|
|
1192
1842
|
*/
|
|
1193
|
-
|
|
1843
|
+
default: prec(Prec_.default),
|
|
1194
1844
|
/**
|
|
1195
|
-
|
|
1845
|
+
A lower-than-default precedence.
|
|
1196
1846
|
*/
|
|
1197
|
-
|
|
1847
|
+
low: prec(Prec_.low),
|
|
1198
1848
|
/**
|
|
1199
|
-
|
|
1849
|
+
The lowest precedence level. Meant for things that should end up
|
|
1850
|
+
near the end of the extension order.
|
|
1200
1851
|
*/
|
|
1201
|
-
|
|
1852
|
+
lowest: prec(Prec_.lowest)
|
|
1202
1853
|
};
|
|
1203
1854
|
class PrecExtension {
|
|
1204
1855
|
constructor(inner, prec) {
|
|
@@ -1312,7 +1963,7 @@ function flatten(extension, compartments, newCompartments) {
|
|
|
1312
1963
|
function inner(ext, prec) {
|
|
1313
1964
|
let known = seen.get(ext);
|
|
1314
1965
|
if (known != null) {
|
|
1315
|
-
if (known
|
|
1966
|
+
if (known <= prec)
|
|
1316
1967
|
return;
|
|
1317
1968
|
let found = result[known].indexOf(ext);
|
|
1318
1969
|
if (found > -1)
|
|
@@ -1527,7 +2178,9 @@ Changes to the editor state are grouped into transactions.
|
|
|
1527
2178
|
Typically, a user action creates a single transaction, which may
|
|
1528
2179
|
contain any number of document changes, may change the selection,
|
|
1529
2180
|
or have other effects. Create a transaction by calling
|
|
1530
|
-
[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update)
|
|
2181
|
+
[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update), or immediately
|
|
2182
|
+
dispatch one by calling
|
|
2183
|
+
[`EditorView.dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch).
|
|
1531
2184
|
*/
|
|
1532
2185
|
class Transaction {
|
|
1533
2186
|
/**
|
|
@@ -1601,7 +2254,7 @@ class Transaction {
|
|
|
1601
2254
|
}
|
|
1602
2255
|
/**
|
|
1603
2256
|
The new state created by the transaction. Computed on demand
|
|
1604
|
-
(but retained for subsequent access), so
|
|
2257
|
+
(but retained for subsequent access), so it is recommended not to
|
|
1605
2258
|
access it in [transaction
|
|
1606
2259
|
filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) when possible.
|
|
1607
2260
|
*/
|
|
@@ -1643,7 +2296,8 @@ class Transaction {
|
|
|
1643
2296
|
}
|
|
1644
2297
|
}
|
|
1645
2298
|
/**
|
|
1646
|
-
Annotation used to store transaction timestamps.
|
|
2299
|
+
Annotation used to store transaction timestamps. Automatically
|
|
2300
|
+
added to every transaction, holding `Date.now()`.
|
|
1647
2301
|
*/
|
|
1648
2302
|
Transaction.time = Annotation.define();
|
|
1649
2303
|
/**
|
|
@@ -2016,10 +2670,10 @@ class EditorState {
|
|
|
2016
2670
|
/**
|
|
2017
2671
|
Using the state's [line
|
|
2018
2672
|
separator](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator), create a
|
|
2019
|
-
[`Text`](https://codemirror.net/6/docs/ref/#
|
|
2673
|
+
[`Text`](https://codemirror.net/6/docs/ref/#state.Text) instance from the given string.
|
|
2020
2674
|
*/
|
|
2021
2675
|
toText(string) {
|
|
2022
|
-
return
|
|
2676
|
+
return Text.of(string.split(this.facet(EditorState.lineSeparator) || DefaultSplit));
|
|
2023
2677
|
}
|
|
2024
2678
|
/**
|
|
2025
2679
|
Return the given range of the document as a string.
|
|
@@ -2084,8 +2738,8 @@ class EditorState {
|
|
|
2084
2738
|
*/
|
|
2085
2739
|
static create(config = {}) {
|
|
2086
2740
|
let configuration = Configuration.resolve(config.extensions || [], new Map);
|
|
2087
|
-
let doc = config.doc instanceof
|
|
2088
|
-
:
|
|
2741
|
+
let doc = config.doc instanceof Text ? config.doc
|
|
2742
|
+
: Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit));
|
|
2089
2743
|
let selection = !config.selection ? EditorSelection.single(0)
|
|
2090
2744
|
: config.selection instanceof EditorSelection ? config.selection
|
|
2091
2745
|
: EditorSelection.single(config.selection.anchor, config.selection.head);
|
|
@@ -2136,7 +2790,7 @@ class EditorState {
|
|
|
2136
2790
|
}
|
|
2137
2791
|
/**
|
|
2138
2792
|
Return a function that can categorize strings (expected to
|
|
2139
|
-
represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#
|
|
2793
|
+
represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#state.findClusterBreak))
|
|
2140
2794
|
into one of:
|
|
2141
2795
|
|
|
2142
2796
|
- Word (contains an alphanumeric character or a character
|
|
@@ -2155,18 +2809,18 @@ class EditorState {
|
|
|
2155
2809
|
this returns null.
|
|
2156
2810
|
*/
|
|
2157
2811
|
wordAt(pos) {
|
|
2158
|
-
let { text
|
|
2812
|
+
let { text, from, length } = this.doc.lineAt(pos);
|
|
2159
2813
|
let cat = this.charCategorizer(pos);
|
|
2160
2814
|
let start = pos - from, end = pos - from;
|
|
2161
2815
|
while (start > 0) {
|
|
2162
|
-
let prev =
|
|
2163
|
-
if (cat(text
|
|
2816
|
+
let prev = findClusterBreak(text, start, false);
|
|
2817
|
+
if (cat(text.slice(prev, start)) != exports.CharCategory.Word)
|
|
2164
2818
|
break;
|
|
2165
2819
|
start = prev;
|
|
2166
2820
|
}
|
|
2167
2821
|
while (end < length) {
|
|
2168
|
-
let next =
|
|
2169
|
-
if (cat(text
|
|
2822
|
+
let next = findClusterBreak(text, end);
|
|
2823
|
+
if (cat(text.slice(end, next)) != exports.CharCategory.Word)
|
|
2170
2824
|
break;
|
|
2171
2825
|
end = next;
|
|
2172
2826
|
}
|
|
@@ -2220,7 +2874,12 @@ Registers translation phrases. The
|
|
|
2220
2874
|
all objects registered with this facet to find translations for
|
|
2221
2875
|
its argument.
|
|
2222
2876
|
*/
|
|
2223
|
-
EditorState.phrases = Facet.define(
|
|
2877
|
+
EditorState.phrases = Facet.define({
|
|
2878
|
+
compare(a, b) {
|
|
2879
|
+
let kA = Object.keys(a), kB = Object.keys(b);
|
|
2880
|
+
return kA.length == kB.length && kA.every(k => a[k] == b[k]);
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2224
2883
|
/**
|
|
2225
2884
|
A facet used to register [language
|
|
2226
2885
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) providers.
|
|
@@ -2236,7 +2895,7 @@ Such a function can return `true` to indicate that it doesn't
|
|
|
2236
2895
|
want to do anything, `false` to completely stop the changes in
|
|
2237
2896
|
the transaction, or a set of ranges in which changes should be
|
|
2238
2897
|
suppressed. Such ranges are represented as an array of numbers,
|
|
2239
|
-
with each pair of two
|
|
2898
|
+
with each pair of two numbers indicating the start and end of a
|
|
2240
2899
|
range. So for example `[10, 20, 100, 110]` suppresses changes
|
|
2241
2900
|
between 10 and 20, and between 100 and 110.
|
|
2242
2901
|
*/
|
|
@@ -2267,19 +2926,22 @@ This is a more limited form of
|
|
|
2267
2926
|
which can only add
|
|
2268
2927
|
[annotations](https://codemirror.net/6/docs/ref/#state.TransactionSpec.annotations) and
|
|
2269
2928
|
[effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects). _But_, this type
|
|
2270
|
-
of filter runs even the transaction has disabled regular
|
|
2929
|
+
of filter runs even if the transaction has disabled regular
|
|
2271
2930
|
[filtering](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter), making it suitable
|
|
2272
2931
|
for effects that don't need to touch the changes or selection,
|
|
2273
2932
|
but do want to process every transaction.
|
|
2274
2933
|
|
|
2275
|
-
Extenders run _after_ filters, when both are
|
|
2934
|
+
Extenders run _after_ filters, when both are present.
|
|
2276
2935
|
*/
|
|
2277
2936
|
EditorState.transactionExtender = transactionExtender;
|
|
2278
2937
|
Compartment.reconfigure = StateEffect.define();
|
|
2279
2938
|
|
|
2280
2939
|
/**
|
|
2281
2940
|
Utility function for combining behaviors to fill in a config
|
|
2282
|
-
object from an array of provided configs.
|
|
2941
|
+
object from an array of provided configs. `defaults` should hold
|
|
2942
|
+
default values for all optional fields in `Config`.
|
|
2943
|
+
|
|
2944
|
+
The function will, by default, error
|
|
2283
2945
|
when a field gets two values that aren't `===`-equal, but you can
|
|
2284
2946
|
provide combine functions per field to do something else.
|
|
2285
2947
|
*/
|
|
@@ -2303,10 +2965,873 @@ combine = {}) {
|
|
|
2303
2965
|
return result;
|
|
2304
2966
|
}
|
|
2305
2967
|
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2968
|
+
/**
|
|
2969
|
+
Each range is associated with a value, which must inherit from
|
|
2970
|
+
this class.
|
|
2971
|
+
*/
|
|
2972
|
+
class RangeValue {
|
|
2973
|
+
/**
|
|
2974
|
+
Compare this value with another value. Used when comparing
|
|
2975
|
+
rangesets. The default implementation compares by identity.
|
|
2976
|
+
Unless you are only creating a fixed number of unique instances
|
|
2977
|
+
of your value type, it is a good idea to implement this
|
|
2978
|
+
properly.
|
|
2979
|
+
*/
|
|
2980
|
+
eq(other) { return this == other; }
|
|
2981
|
+
/**
|
|
2982
|
+
Create a [range](https://codemirror.net/6/docs/ref/#state.Range) with this value.
|
|
2983
|
+
*/
|
|
2984
|
+
range(from, to = from) { return new Range(from, to, this); }
|
|
2985
|
+
}
|
|
2986
|
+
RangeValue.prototype.startSide = RangeValue.prototype.endSide = 0;
|
|
2987
|
+
RangeValue.prototype.point = false;
|
|
2988
|
+
RangeValue.prototype.mapMode = exports.MapMode.TrackDel;
|
|
2989
|
+
/**
|
|
2990
|
+
A range associates a value with a range of positions.
|
|
2991
|
+
*/
|
|
2992
|
+
class Range {
|
|
2993
|
+
/**
|
|
2994
|
+
@internal
|
|
2995
|
+
*/
|
|
2996
|
+
constructor(
|
|
2997
|
+
/**
|
|
2998
|
+
The range's start position.
|
|
2999
|
+
*/
|
|
3000
|
+
from,
|
|
3001
|
+
/**
|
|
3002
|
+
Its end position.
|
|
3003
|
+
*/
|
|
3004
|
+
to,
|
|
3005
|
+
/**
|
|
3006
|
+
The value associated with this range.
|
|
3007
|
+
*/
|
|
3008
|
+
value) {
|
|
3009
|
+
this.from = from;
|
|
3010
|
+
this.to = to;
|
|
3011
|
+
this.value = value;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
function cmpRange(a, b) {
|
|
3015
|
+
return a.from - b.from || a.value.startSide - b.value.startSide;
|
|
3016
|
+
}
|
|
3017
|
+
class Chunk {
|
|
3018
|
+
constructor(from, to, value,
|
|
3019
|
+
// Chunks are marked with the largest point that occurs
|
|
3020
|
+
// in them (or -1 for no points), so that scans that are
|
|
3021
|
+
// only interested in points (such as the
|
|
3022
|
+
// heightmap-related logic) can skip range-only chunks.
|
|
3023
|
+
maxPoint) {
|
|
3024
|
+
this.from = from;
|
|
3025
|
+
this.to = to;
|
|
3026
|
+
this.value = value;
|
|
3027
|
+
this.maxPoint = maxPoint;
|
|
3028
|
+
}
|
|
3029
|
+
get length() { return this.to[this.to.length - 1]; }
|
|
3030
|
+
// Find the index of the given position and side. Use the ranges'
|
|
3031
|
+
// `from` pos when `end == false`, `to` when `end == true`.
|
|
3032
|
+
findIndex(pos, side, end, startAt = 0) {
|
|
3033
|
+
let arr = end ? this.to : this.from;
|
|
3034
|
+
for (let lo = startAt, hi = arr.length;;) {
|
|
3035
|
+
if (lo == hi)
|
|
3036
|
+
return lo;
|
|
3037
|
+
let mid = (lo + hi) >> 1;
|
|
3038
|
+
let diff = arr[mid] - pos || (end ? this.value[mid].endSide : this.value[mid].startSide) - side;
|
|
3039
|
+
if (mid == lo)
|
|
3040
|
+
return diff >= 0 ? lo : hi;
|
|
3041
|
+
if (diff >= 0)
|
|
3042
|
+
hi = mid;
|
|
3043
|
+
else
|
|
3044
|
+
lo = mid + 1;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
between(offset, from, to, f) {
|
|
3048
|
+
for (let i = this.findIndex(from, -1000000000 /* Far */, true), e = this.findIndex(to, 1000000000 /* Far */, false, i); i < e; i++)
|
|
3049
|
+
if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false)
|
|
3050
|
+
return false;
|
|
3051
|
+
}
|
|
3052
|
+
map(offset, changes) {
|
|
3053
|
+
let value = [], from = [], to = [], newPos = -1, maxPoint = -1;
|
|
3054
|
+
for (let i = 0; i < this.value.length; i++) {
|
|
3055
|
+
let val = this.value[i], curFrom = this.from[i] + offset, curTo = this.to[i] + offset, newFrom, newTo;
|
|
3056
|
+
if (curFrom == curTo) {
|
|
3057
|
+
let mapped = changes.mapPos(curFrom, val.startSide, val.mapMode);
|
|
3058
|
+
if (mapped == null)
|
|
3059
|
+
continue;
|
|
3060
|
+
newFrom = newTo = mapped;
|
|
3061
|
+
if (val.startSide != val.endSide) {
|
|
3062
|
+
newTo = changes.mapPos(curFrom, val.endSide);
|
|
3063
|
+
if (newTo < newFrom)
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
else {
|
|
3068
|
+
newFrom = changes.mapPos(curFrom, val.startSide);
|
|
3069
|
+
newTo = changes.mapPos(curTo, val.endSide);
|
|
3070
|
+
if (newFrom > newTo || newFrom == newTo && val.startSide > 0 && val.endSide <= 0)
|
|
3071
|
+
continue;
|
|
3072
|
+
}
|
|
3073
|
+
if ((newTo - newFrom || val.endSide - val.startSide) < 0)
|
|
3074
|
+
continue;
|
|
3075
|
+
if (newPos < 0)
|
|
3076
|
+
newPos = newFrom;
|
|
3077
|
+
if (val.point)
|
|
3078
|
+
maxPoint = Math.max(maxPoint, newTo - newFrom);
|
|
3079
|
+
value.push(val);
|
|
3080
|
+
from.push(newFrom - newPos);
|
|
3081
|
+
to.push(newTo - newPos);
|
|
3082
|
+
}
|
|
3083
|
+
return { mapped: value.length ? new Chunk(from, to, value, maxPoint) : null, pos: newPos };
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#state.Range) in a
|
|
3088
|
+
way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#state.RangeSet.map) and
|
|
3089
|
+
[update](https://codemirror.net/6/docs/ref/#state.RangeSet.update). This is an immutable data
|
|
3090
|
+
structure.
|
|
3091
|
+
*/
|
|
3092
|
+
class RangeSet {
|
|
3093
|
+
/**
|
|
3094
|
+
@internal
|
|
3095
|
+
*/
|
|
3096
|
+
constructor(
|
|
3097
|
+
/**
|
|
3098
|
+
@internal
|
|
3099
|
+
*/
|
|
3100
|
+
chunkPos,
|
|
3101
|
+
/**
|
|
3102
|
+
@internal
|
|
3103
|
+
*/
|
|
3104
|
+
chunk,
|
|
3105
|
+
/**
|
|
3106
|
+
@internal
|
|
3107
|
+
*/
|
|
3108
|
+
nextLayer = RangeSet.empty,
|
|
3109
|
+
/**
|
|
3110
|
+
@internal
|
|
3111
|
+
*/
|
|
3112
|
+
maxPoint) {
|
|
3113
|
+
this.chunkPos = chunkPos;
|
|
3114
|
+
this.chunk = chunk;
|
|
3115
|
+
this.nextLayer = nextLayer;
|
|
3116
|
+
this.maxPoint = maxPoint;
|
|
3117
|
+
}
|
|
3118
|
+
/**
|
|
3119
|
+
@internal
|
|
3120
|
+
*/
|
|
3121
|
+
get length() {
|
|
3122
|
+
let last = this.chunk.length - 1;
|
|
3123
|
+
return last < 0 ? 0 : Math.max(this.chunkEnd(last), this.nextLayer.length);
|
|
3124
|
+
}
|
|
3125
|
+
/**
|
|
3126
|
+
The number of ranges in the set.
|
|
3127
|
+
*/
|
|
3128
|
+
get size() {
|
|
3129
|
+
if (this.isEmpty)
|
|
3130
|
+
return 0;
|
|
3131
|
+
let size = this.nextLayer.size;
|
|
3132
|
+
for (let chunk of this.chunk)
|
|
3133
|
+
size += chunk.value.length;
|
|
3134
|
+
return size;
|
|
3135
|
+
}
|
|
3136
|
+
/**
|
|
3137
|
+
@internal
|
|
3138
|
+
*/
|
|
3139
|
+
chunkEnd(index) {
|
|
3140
|
+
return this.chunkPos[index] + this.chunk[index].length;
|
|
3141
|
+
}
|
|
3142
|
+
/**
|
|
3143
|
+
Update the range set, optionally adding new ranges or filtering
|
|
3144
|
+
out existing ones.
|
|
3145
|
+
|
|
3146
|
+
(Note: The type parameter is just there as a kludge to work
|
|
3147
|
+
around TypeScript variance issues that prevented `RangeSet<X>`
|
|
3148
|
+
from being a subtype of `RangeSet<Y>` when `X` is a subtype of
|
|
3149
|
+
`Y`.)
|
|
3150
|
+
*/
|
|
3151
|
+
update(updateSpec) {
|
|
3152
|
+
let { add = [], sort = false, filterFrom = 0, filterTo = this.length } = updateSpec;
|
|
3153
|
+
let filter = updateSpec.filter;
|
|
3154
|
+
if (add.length == 0 && !filter)
|
|
3155
|
+
return this;
|
|
3156
|
+
if (sort)
|
|
3157
|
+
add = add.slice().sort(cmpRange);
|
|
3158
|
+
if (this.isEmpty)
|
|
3159
|
+
return add.length ? RangeSet.of(add) : this;
|
|
3160
|
+
let cur = new LayerCursor(this, null, -1).goto(0), i = 0, spill = [];
|
|
3161
|
+
let builder = new RangeSetBuilder();
|
|
3162
|
+
while (cur.value || i < add.length) {
|
|
3163
|
+
if (i < add.length && (cur.from - add[i].from || cur.startSide - add[i].value.startSide) >= 0) {
|
|
3164
|
+
let range = add[i++];
|
|
3165
|
+
if (!builder.addInner(range.from, range.to, range.value))
|
|
3166
|
+
spill.push(range);
|
|
3167
|
+
}
|
|
3168
|
+
else if (cur.rangeIndex == 1 && cur.chunkIndex < this.chunk.length &&
|
|
3169
|
+
(i == add.length || this.chunkEnd(cur.chunkIndex) < add[i].from) &&
|
|
3170
|
+
(!filter || filterFrom > this.chunkEnd(cur.chunkIndex) || filterTo < this.chunkPos[cur.chunkIndex]) &&
|
|
3171
|
+
builder.addChunk(this.chunkPos[cur.chunkIndex], this.chunk[cur.chunkIndex])) {
|
|
3172
|
+
cur.nextChunk();
|
|
3173
|
+
}
|
|
3174
|
+
else {
|
|
3175
|
+
if (!filter || filterFrom > cur.to || filterTo < cur.from || filter(cur.from, cur.to, cur.value)) {
|
|
3176
|
+
if (!builder.addInner(cur.from, cur.to, cur.value))
|
|
3177
|
+
spill.push(new Range(cur.from, cur.to, cur.value));
|
|
3178
|
+
}
|
|
3179
|
+
cur.next();
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
return builder.finishInner(this.nextLayer.isEmpty && !spill.length ? RangeSet.empty
|
|
3183
|
+
: this.nextLayer.update({ add: spill, filter, filterFrom, filterTo }));
|
|
3184
|
+
}
|
|
3185
|
+
/**
|
|
3186
|
+
Map this range set through a set of changes, return the new set.
|
|
3187
|
+
*/
|
|
3188
|
+
map(changes) {
|
|
3189
|
+
if (changes.empty || this.isEmpty)
|
|
3190
|
+
return this;
|
|
3191
|
+
let chunks = [], chunkPos = [], maxPoint = -1;
|
|
3192
|
+
for (let i = 0; i < this.chunk.length; i++) {
|
|
3193
|
+
let start = this.chunkPos[i], chunk = this.chunk[i];
|
|
3194
|
+
let touch = changes.touchesRange(start, start + chunk.length);
|
|
3195
|
+
if (touch === false) {
|
|
3196
|
+
maxPoint = Math.max(maxPoint, chunk.maxPoint);
|
|
3197
|
+
chunks.push(chunk);
|
|
3198
|
+
chunkPos.push(changes.mapPos(start));
|
|
3199
|
+
}
|
|
3200
|
+
else if (touch === true) {
|
|
3201
|
+
let { mapped, pos } = chunk.map(start, changes);
|
|
3202
|
+
if (mapped) {
|
|
3203
|
+
maxPoint = Math.max(maxPoint, mapped.maxPoint);
|
|
3204
|
+
chunks.push(mapped);
|
|
3205
|
+
chunkPos.push(pos);
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
let next = this.nextLayer.map(changes);
|
|
3210
|
+
return chunks.length == 0 ? next : new RangeSet(chunkPos, chunks, next, maxPoint);
|
|
3211
|
+
}
|
|
3212
|
+
/**
|
|
3213
|
+
Iterate over the ranges that touch the region `from` to `to`,
|
|
3214
|
+
calling `f` for each. There is no guarantee that the ranges will
|
|
3215
|
+
be reported in any specific order. When the callback returns
|
|
3216
|
+
`false`, iteration stops.
|
|
3217
|
+
*/
|
|
3218
|
+
between(from, to, f) {
|
|
3219
|
+
if (this.isEmpty)
|
|
3220
|
+
return;
|
|
3221
|
+
for (let i = 0; i < this.chunk.length; i++) {
|
|
3222
|
+
let start = this.chunkPos[i], chunk = this.chunk[i];
|
|
3223
|
+
if (to >= start && from <= start + chunk.length &&
|
|
3224
|
+
chunk.between(start, from - start, to - start, f) === false)
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3227
|
+
this.nextLayer.between(from, to, f);
|
|
3228
|
+
}
|
|
3229
|
+
/**
|
|
3230
|
+
Iterate over the ranges in this set, in order, including all
|
|
3231
|
+
ranges that end at or after `from`.
|
|
3232
|
+
*/
|
|
3233
|
+
iter(from = 0) {
|
|
3234
|
+
return HeapCursor.from([this]).goto(from);
|
|
3235
|
+
}
|
|
3236
|
+
/**
|
|
3237
|
+
@internal
|
|
3238
|
+
*/
|
|
3239
|
+
get isEmpty() { return this.nextLayer == this; }
|
|
3240
|
+
/**
|
|
3241
|
+
Iterate over the ranges in a collection of sets, in order,
|
|
3242
|
+
starting from `from`.
|
|
3243
|
+
*/
|
|
3244
|
+
static iter(sets, from = 0) {
|
|
3245
|
+
return HeapCursor.from(sets).goto(from);
|
|
3246
|
+
}
|
|
3247
|
+
/**
|
|
3248
|
+
Iterate over two groups of sets, calling methods on `comparator`
|
|
3249
|
+
to notify it of possible differences.
|
|
3250
|
+
*/
|
|
3251
|
+
static compare(oldSets, newSets,
|
|
3252
|
+
/**
|
|
3253
|
+
This indicates how the underlying data changed between these
|
|
3254
|
+
ranges, and is needed to synchronize the iteration. `from` and
|
|
3255
|
+
`to` are coordinates in the _new_ space, after these changes.
|
|
3256
|
+
*/
|
|
3257
|
+
textDiff, comparator,
|
|
3258
|
+
/**
|
|
3259
|
+
Can be used to ignore all non-point ranges, and points below
|
|
3260
|
+
the given size. When -1, all ranges are compared.
|
|
3261
|
+
*/
|
|
3262
|
+
minPointSize = -1) {
|
|
3263
|
+
let a = oldSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize);
|
|
3264
|
+
let b = newSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize);
|
|
3265
|
+
let sharedChunks = findSharedChunks(a, b, textDiff);
|
|
3266
|
+
let sideA = new SpanCursor(a, sharedChunks, minPointSize);
|
|
3267
|
+
let sideB = new SpanCursor(b, sharedChunks, minPointSize);
|
|
3268
|
+
textDiff.iterGaps((fromA, fromB, length) => compare(sideA, fromA, sideB, fromB, length, comparator));
|
|
3269
|
+
if (textDiff.empty && textDiff.length == 0)
|
|
3270
|
+
compare(sideA, 0, sideB, 0, 0, comparator);
|
|
3271
|
+
}
|
|
3272
|
+
/**
|
|
3273
|
+
Compare the contents of two groups of range sets, returning true
|
|
3274
|
+
if they are equivalent in the given range.
|
|
3275
|
+
*/
|
|
3276
|
+
static eq(oldSets, newSets, from = 0, to) {
|
|
3277
|
+
if (to == null)
|
|
3278
|
+
to = 1000000000 /* Far */;
|
|
3279
|
+
let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0);
|
|
3280
|
+
let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0);
|
|
3281
|
+
if (a.length != b.length)
|
|
3282
|
+
return false;
|
|
3283
|
+
if (!a.length)
|
|
3284
|
+
return true;
|
|
3285
|
+
let sharedChunks = findSharedChunks(a, b);
|
|
3286
|
+
let sideA = new SpanCursor(a, sharedChunks, 0).goto(from), sideB = new SpanCursor(b, sharedChunks, 0).goto(from);
|
|
3287
|
+
for (;;) {
|
|
3288
|
+
if (sideA.to != sideB.to ||
|
|
3289
|
+
!sameValues(sideA.active, sideB.active) ||
|
|
3290
|
+
sideA.point && (!sideB.point || !sideA.point.eq(sideB.point)))
|
|
3291
|
+
return false;
|
|
3292
|
+
if (sideA.to > to)
|
|
3293
|
+
return true;
|
|
3294
|
+
sideA.next();
|
|
3295
|
+
sideB.next();
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
/**
|
|
3299
|
+
Iterate over a group of range sets at the same time, notifying
|
|
3300
|
+
the iterator about the ranges covering every given piece of
|
|
3301
|
+
content. Returns the open count (see
|
|
3302
|
+
[`SpanIterator.span`](https://codemirror.net/6/docs/ref/#state.SpanIterator.span)) at the end
|
|
3303
|
+
of the iteration.
|
|
3304
|
+
*/
|
|
3305
|
+
static spans(sets, from, to, iterator,
|
|
3306
|
+
/**
|
|
3307
|
+
When given and greater than -1, only points of at least this
|
|
3308
|
+
size are taken into account.
|
|
3309
|
+
*/
|
|
3310
|
+
minPointSize = -1) {
|
|
3311
|
+
let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from;
|
|
3312
|
+
let open = cursor.openStart;
|
|
3313
|
+
for (;;) {
|
|
3314
|
+
let curTo = Math.min(cursor.to, to);
|
|
3315
|
+
if (cursor.point) {
|
|
3316
|
+
iterator.point(pos, curTo, cursor.point, cursor.activeForPoint(cursor.to), open, cursor.pointRank);
|
|
3317
|
+
open = cursor.openEnd(curTo) + (cursor.to > curTo ? 1 : 0);
|
|
3318
|
+
}
|
|
3319
|
+
else if (curTo > pos) {
|
|
3320
|
+
iterator.span(pos, curTo, cursor.active, open);
|
|
3321
|
+
open = cursor.openEnd(curTo);
|
|
3322
|
+
}
|
|
3323
|
+
if (cursor.to > to)
|
|
3324
|
+
break;
|
|
3325
|
+
pos = cursor.to;
|
|
3326
|
+
cursor.next();
|
|
3327
|
+
}
|
|
3328
|
+
return open;
|
|
3329
|
+
}
|
|
3330
|
+
/**
|
|
3331
|
+
Create a range set for the given range or array of ranges. By
|
|
3332
|
+
default, this expects the ranges to be _sorted_ (by start
|
|
3333
|
+
position and, if two start at the same position,
|
|
3334
|
+
`value.startSide`). You can pass `true` as second argument to
|
|
3335
|
+
cause the method to sort them.
|
|
3336
|
+
*/
|
|
3337
|
+
static of(ranges, sort = false) {
|
|
3338
|
+
let build = new RangeSetBuilder();
|
|
3339
|
+
for (let range of ranges instanceof Range ? [ranges] : sort ? lazySort(ranges) : ranges)
|
|
3340
|
+
build.add(range.from, range.to, range.value);
|
|
3341
|
+
return build.finish();
|
|
3342
|
+
}
|
|
3343
|
+
}
|
|
3344
|
+
/**
|
|
3345
|
+
The empty set of ranges.
|
|
3346
|
+
*/
|
|
3347
|
+
RangeSet.empty = new RangeSet([], [], null, -1);
|
|
3348
|
+
function lazySort(ranges) {
|
|
3349
|
+
if (ranges.length > 1)
|
|
3350
|
+
for (let prev = ranges[0], i = 1; i < ranges.length; i++) {
|
|
3351
|
+
let cur = ranges[i];
|
|
3352
|
+
if (cmpRange(prev, cur) > 0)
|
|
3353
|
+
return ranges.slice().sort(cmpRange);
|
|
3354
|
+
prev = cur;
|
|
3355
|
+
}
|
|
3356
|
+
return ranges;
|
|
3357
|
+
}
|
|
3358
|
+
RangeSet.empty.nextLayer = RangeSet.empty;
|
|
3359
|
+
/**
|
|
3360
|
+
A range set builder is a data structure that helps build up a
|
|
3361
|
+
[range set](https://codemirror.net/6/docs/ref/#state.RangeSet) directly, without first allocating
|
|
3362
|
+
an array of [`Range`](https://codemirror.net/6/docs/ref/#state.Range) objects.
|
|
3363
|
+
*/
|
|
3364
|
+
class RangeSetBuilder {
|
|
3365
|
+
/**
|
|
3366
|
+
Create an empty builder.
|
|
3367
|
+
*/
|
|
3368
|
+
constructor() {
|
|
3369
|
+
this.chunks = [];
|
|
3370
|
+
this.chunkPos = [];
|
|
3371
|
+
this.chunkStart = -1;
|
|
3372
|
+
this.last = null;
|
|
3373
|
+
this.lastFrom = -1000000000 /* Far */;
|
|
3374
|
+
this.lastTo = -1000000000 /* Far */;
|
|
3375
|
+
this.from = [];
|
|
3376
|
+
this.to = [];
|
|
3377
|
+
this.value = [];
|
|
3378
|
+
this.maxPoint = -1;
|
|
3379
|
+
this.setMaxPoint = -1;
|
|
3380
|
+
this.nextLayer = null;
|
|
3381
|
+
}
|
|
3382
|
+
finishChunk(newArrays) {
|
|
3383
|
+
this.chunks.push(new Chunk(this.from, this.to, this.value, this.maxPoint));
|
|
3384
|
+
this.chunkPos.push(this.chunkStart);
|
|
3385
|
+
this.chunkStart = -1;
|
|
3386
|
+
this.setMaxPoint = Math.max(this.setMaxPoint, this.maxPoint);
|
|
3387
|
+
this.maxPoint = -1;
|
|
3388
|
+
if (newArrays) {
|
|
3389
|
+
this.from = [];
|
|
3390
|
+
this.to = [];
|
|
3391
|
+
this.value = [];
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
/**
|
|
3395
|
+
Add a range. Ranges should be added in sorted (by `from` and
|
|
3396
|
+
`value.startSide`) order.
|
|
3397
|
+
*/
|
|
3398
|
+
add(from, to, value) {
|
|
3399
|
+
if (!this.addInner(from, to, value))
|
|
3400
|
+
(this.nextLayer || (this.nextLayer = new RangeSetBuilder)).add(from, to, value);
|
|
3401
|
+
}
|
|
3402
|
+
/**
|
|
3403
|
+
@internal
|
|
3404
|
+
*/
|
|
3405
|
+
addInner(from, to, value) {
|
|
3406
|
+
let diff = from - this.lastTo || value.startSide - this.last.endSide;
|
|
3407
|
+
if (diff <= 0 && (from - this.lastFrom || value.startSide - this.last.startSide) < 0)
|
|
3408
|
+
throw new Error("Ranges must be added sorted by `from` position and `startSide`");
|
|
3409
|
+
if (diff < 0)
|
|
3410
|
+
return false;
|
|
3411
|
+
if (this.from.length == 250 /* ChunkSize */)
|
|
3412
|
+
this.finishChunk(true);
|
|
3413
|
+
if (this.chunkStart < 0)
|
|
3414
|
+
this.chunkStart = from;
|
|
3415
|
+
this.from.push(from - this.chunkStart);
|
|
3416
|
+
this.to.push(to - this.chunkStart);
|
|
3417
|
+
this.last = value;
|
|
3418
|
+
this.lastFrom = from;
|
|
3419
|
+
this.lastTo = to;
|
|
3420
|
+
this.value.push(value);
|
|
3421
|
+
if (value.point)
|
|
3422
|
+
this.maxPoint = Math.max(this.maxPoint, to - from);
|
|
3423
|
+
return true;
|
|
3424
|
+
}
|
|
3425
|
+
/**
|
|
3426
|
+
@internal
|
|
3427
|
+
*/
|
|
3428
|
+
addChunk(from, chunk) {
|
|
3429
|
+
if ((from - this.lastTo || chunk.value[0].startSide - this.last.endSide) < 0)
|
|
3430
|
+
return false;
|
|
3431
|
+
if (this.from.length)
|
|
3432
|
+
this.finishChunk(true);
|
|
3433
|
+
this.setMaxPoint = Math.max(this.setMaxPoint, chunk.maxPoint);
|
|
3434
|
+
this.chunks.push(chunk);
|
|
3435
|
+
this.chunkPos.push(from);
|
|
3436
|
+
let last = chunk.value.length - 1;
|
|
3437
|
+
this.last = chunk.value[last];
|
|
3438
|
+
this.lastFrom = chunk.from[last] + from;
|
|
3439
|
+
this.lastTo = chunk.to[last] + from;
|
|
3440
|
+
return true;
|
|
3441
|
+
}
|
|
3442
|
+
/**
|
|
3443
|
+
Finish the range set. Returns the new set. The builder can't be
|
|
3444
|
+
used anymore after this has been called.
|
|
3445
|
+
*/
|
|
3446
|
+
finish() { return this.finishInner(RangeSet.empty); }
|
|
3447
|
+
/**
|
|
3448
|
+
@internal
|
|
3449
|
+
*/
|
|
3450
|
+
finishInner(next) {
|
|
3451
|
+
if (this.from.length)
|
|
3452
|
+
this.finishChunk(false);
|
|
3453
|
+
if (this.chunks.length == 0)
|
|
3454
|
+
return next;
|
|
3455
|
+
let result = new RangeSet(this.chunkPos, this.chunks, this.nextLayer ? this.nextLayer.finishInner(next) : next, this.setMaxPoint);
|
|
3456
|
+
this.from = null; // Make sure further `add` calls produce errors
|
|
3457
|
+
return result;
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
function findSharedChunks(a, b, textDiff) {
|
|
3461
|
+
let inA = new Map();
|
|
3462
|
+
for (let set of a)
|
|
3463
|
+
for (let i = 0; i < set.chunk.length; i++)
|
|
3464
|
+
if (set.chunk[i].maxPoint <= 0)
|
|
3465
|
+
inA.set(set.chunk[i], set.chunkPos[i]);
|
|
3466
|
+
let shared = new Set();
|
|
3467
|
+
for (let set of b)
|
|
3468
|
+
for (let i = 0; i < set.chunk.length; i++) {
|
|
3469
|
+
let known = inA.get(set.chunk[i]);
|
|
3470
|
+
if (known != null && (textDiff ? textDiff.mapPos(known) : known) == set.chunkPos[i] &&
|
|
3471
|
+
!(textDiff === null || textDiff === void 0 ? void 0 : textDiff.touchesRange(known, known + set.chunk[i].length)))
|
|
3472
|
+
shared.add(set.chunk[i]);
|
|
3473
|
+
}
|
|
3474
|
+
return shared;
|
|
3475
|
+
}
|
|
3476
|
+
class LayerCursor {
|
|
3477
|
+
constructor(layer, skip, minPoint, rank = 0) {
|
|
3478
|
+
this.layer = layer;
|
|
3479
|
+
this.skip = skip;
|
|
3480
|
+
this.minPoint = minPoint;
|
|
3481
|
+
this.rank = rank;
|
|
3482
|
+
}
|
|
3483
|
+
get startSide() { return this.value ? this.value.startSide : 0; }
|
|
3484
|
+
get endSide() { return this.value ? this.value.endSide : 0; }
|
|
3485
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3486
|
+
this.chunkIndex = this.rangeIndex = 0;
|
|
3487
|
+
this.gotoInner(pos, side, false);
|
|
3488
|
+
return this;
|
|
3489
|
+
}
|
|
3490
|
+
gotoInner(pos, side, forward) {
|
|
3491
|
+
while (this.chunkIndex < this.layer.chunk.length) {
|
|
3492
|
+
let next = this.layer.chunk[this.chunkIndex];
|
|
3493
|
+
if (!(this.skip && this.skip.has(next) ||
|
|
3494
|
+
this.layer.chunkEnd(this.chunkIndex) < pos ||
|
|
3495
|
+
next.maxPoint < this.minPoint))
|
|
3496
|
+
break;
|
|
3497
|
+
this.chunkIndex++;
|
|
3498
|
+
forward = false;
|
|
3499
|
+
}
|
|
3500
|
+
if (this.chunkIndex < this.layer.chunk.length) {
|
|
3501
|
+
let rangeIndex = this.layer.chunk[this.chunkIndex].findIndex(pos - this.layer.chunkPos[this.chunkIndex], side, true);
|
|
3502
|
+
if (!forward || this.rangeIndex < rangeIndex)
|
|
3503
|
+
this.setRangeIndex(rangeIndex);
|
|
3504
|
+
}
|
|
3505
|
+
this.next();
|
|
3506
|
+
}
|
|
3507
|
+
forward(pos, side) {
|
|
3508
|
+
if ((this.to - pos || this.endSide - side) < 0)
|
|
3509
|
+
this.gotoInner(pos, side, true);
|
|
3510
|
+
}
|
|
3511
|
+
next() {
|
|
3512
|
+
for (;;) {
|
|
3513
|
+
if (this.chunkIndex == this.layer.chunk.length) {
|
|
3514
|
+
this.from = this.to = 1000000000 /* Far */;
|
|
3515
|
+
this.value = null;
|
|
3516
|
+
break;
|
|
3517
|
+
}
|
|
3518
|
+
else {
|
|
3519
|
+
let chunkPos = this.layer.chunkPos[this.chunkIndex], chunk = this.layer.chunk[this.chunkIndex];
|
|
3520
|
+
let from = chunkPos + chunk.from[this.rangeIndex];
|
|
3521
|
+
this.from = from;
|
|
3522
|
+
this.to = chunkPos + chunk.to[this.rangeIndex];
|
|
3523
|
+
this.value = chunk.value[this.rangeIndex];
|
|
3524
|
+
this.setRangeIndex(this.rangeIndex + 1);
|
|
3525
|
+
if (this.minPoint < 0 || this.value.point && this.to - this.from >= this.minPoint)
|
|
3526
|
+
break;
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
setRangeIndex(index) {
|
|
3531
|
+
if (index == this.layer.chunk[this.chunkIndex].value.length) {
|
|
3532
|
+
this.chunkIndex++;
|
|
3533
|
+
if (this.skip) {
|
|
3534
|
+
while (this.chunkIndex < this.layer.chunk.length && this.skip.has(this.layer.chunk[this.chunkIndex]))
|
|
3535
|
+
this.chunkIndex++;
|
|
3536
|
+
}
|
|
3537
|
+
this.rangeIndex = 0;
|
|
3538
|
+
}
|
|
3539
|
+
else {
|
|
3540
|
+
this.rangeIndex = index;
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
nextChunk() {
|
|
3544
|
+
this.chunkIndex++;
|
|
3545
|
+
this.rangeIndex = 0;
|
|
3546
|
+
this.next();
|
|
3547
|
+
}
|
|
3548
|
+
compare(other) {
|
|
3549
|
+
return this.from - other.from || this.startSide - other.startSide || this.rank - other.rank ||
|
|
3550
|
+
this.to - other.to || this.endSide - other.endSide;
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
class HeapCursor {
|
|
3554
|
+
constructor(heap) {
|
|
3555
|
+
this.heap = heap;
|
|
3556
|
+
}
|
|
3557
|
+
static from(sets, skip = null, minPoint = -1) {
|
|
3558
|
+
let heap = [];
|
|
3559
|
+
for (let i = 0; i < sets.length; i++) {
|
|
3560
|
+
for (let cur = sets[i]; !cur.isEmpty; cur = cur.nextLayer) {
|
|
3561
|
+
if (cur.maxPoint >= minPoint)
|
|
3562
|
+
heap.push(new LayerCursor(cur, skip, minPoint, i));
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
return heap.length == 1 ? heap[0] : new HeapCursor(heap);
|
|
3566
|
+
}
|
|
3567
|
+
get startSide() { return this.value ? this.value.startSide : 0; }
|
|
3568
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3569
|
+
for (let cur of this.heap)
|
|
3570
|
+
cur.goto(pos, side);
|
|
3571
|
+
for (let i = this.heap.length >> 1; i >= 0; i--)
|
|
3572
|
+
heapBubble(this.heap, i);
|
|
3573
|
+
this.next();
|
|
3574
|
+
return this;
|
|
3575
|
+
}
|
|
3576
|
+
forward(pos, side) {
|
|
3577
|
+
for (let cur of this.heap)
|
|
3578
|
+
cur.forward(pos, side);
|
|
3579
|
+
for (let i = this.heap.length >> 1; i >= 0; i--)
|
|
3580
|
+
heapBubble(this.heap, i);
|
|
3581
|
+
if ((this.to - pos || this.value.endSide - side) < 0)
|
|
3582
|
+
this.next();
|
|
3583
|
+
}
|
|
3584
|
+
next() {
|
|
3585
|
+
if (this.heap.length == 0) {
|
|
3586
|
+
this.from = this.to = 1000000000 /* Far */;
|
|
3587
|
+
this.value = null;
|
|
3588
|
+
this.rank = -1;
|
|
3589
|
+
}
|
|
3590
|
+
else {
|
|
3591
|
+
let top = this.heap[0];
|
|
3592
|
+
this.from = top.from;
|
|
3593
|
+
this.to = top.to;
|
|
3594
|
+
this.value = top.value;
|
|
3595
|
+
this.rank = top.rank;
|
|
3596
|
+
if (top.value)
|
|
3597
|
+
top.next();
|
|
3598
|
+
heapBubble(this.heap, 0);
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
function heapBubble(heap, index) {
|
|
3603
|
+
for (let cur = heap[index];;) {
|
|
3604
|
+
let childIndex = (index << 1) + 1;
|
|
3605
|
+
if (childIndex >= heap.length)
|
|
3606
|
+
break;
|
|
3607
|
+
let child = heap[childIndex];
|
|
3608
|
+
if (childIndex + 1 < heap.length && child.compare(heap[childIndex + 1]) >= 0) {
|
|
3609
|
+
child = heap[childIndex + 1];
|
|
3610
|
+
childIndex++;
|
|
3611
|
+
}
|
|
3612
|
+
if (cur.compare(child) < 0)
|
|
3613
|
+
break;
|
|
3614
|
+
heap[childIndex] = cur;
|
|
3615
|
+
heap[index] = child;
|
|
3616
|
+
index = childIndex;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
class SpanCursor {
|
|
3620
|
+
constructor(sets, skip, minPoint) {
|
|
3621
|
+
this.minPoint = minPoint;
|
|
3622
|
+
this.active = [];
|
|
3623
|
+
this.activeTo = [];
|
|
3624
|
+
this.activeRank = [];
|
|
3625
|
+
this.minActive = -1;
|
|
3626
|
+
// A currently active point range, if any
|
|
3627
|
+
this.point = null;
|
|
3628
|
+
this.pointFrom = 0;
|
|
3629
|
+
this.pointRank = 0;
|
|
3630
|
+
this.to = -1000000000 /* Far */;
|
|
3631
|
+
this.endSide = 0;
|
|
3632
|
+
this.openStart = -1;
|
|
3633
|
+
this.cursor = HeapCursor.from(sets, skip, minPoint);
|
|
3634
|
+
}
|
|
3635
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3636
|
+
this.cursor.goto(pos, side);
|
|
3637
|
+
this.active.length = this.activeTo.length = this.activeRank.length = 0;
|
|
3638
|
+
this.minActive = -1;
|
|
3639
|
+
this.to = pos;
|
|
3640
|
+
this.endSide = side;
|
|
3641
|
+
this.openStart = -1;
|
|
3642
|
+
this.next();
|
|
3643
|
+
return this;
|
|
3644
|
+
}
|
|
3645
|
+
forward(pos, side) {
|
|
3646
|
+
while (this.minActive > -1 && (this.activeTo[this.minActive] - pos || this.active[this.minActive].endSide - side) < 0)
|
|
3647
|
+
this.removeActive(this.minActive);
|
|
3648
|
+
this.cursor.forward(pos, side);
|
|
3649
|
+
}
|
|
3650
|
+
removeActive(index) {
|
|
3651
|
+
remove(this.active, index);
|
|
3652
|
+
remove(this.activeTo, index);
|
|
3653
|
+
remove(this.activeRank, index);
|
|
3654
|
+
this.minActive = findMinIndex(this.active, this.activeTo);
|
|
3655
|
+
}
|
|
3656
|
+
addActive(trackOpen) {
|
|
3657
|
+
let i = 0, { value, to, rank } = this.cursor;
|
|
3658
|
+
while (i < this.activeRank.length && this.activeRank[i] <= rank)
|
|
3659
|
+
i++;
|
|
3660
|
+
insert(this.active, i, value);
|
|
3661
|
+
insert(this.activeTo, i, to);
|
|
3662
|
+
insert(this.activeRank, i, rank);
|
|
3663
|
+
if (trackOpen)
|
|
3664
|
+
insert(trackOpen, i, this.cursor.from);
|
|
3665
|
+
this.minActive = findMinIndex(this.active, this.activeTo);
|
|
3666
|
+
}
|
|
3667
|
+
// After calling this, if `this.point` != null, the next range is a
|
|
3668
|
+
// point. Otherwise, it's a regular range, covered by `this.active`.
|
|
3669
|
+
next() {
|
|
3670
|
+
let from = this.to, wasPoint = this.point;
|
|
3671
|
+
this.point = null;
|
|
3672
|
+
let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0;
|
|
3673
|
+
for (;;) {
|
|
3674
|
+
let a = this.minActive;
|
|
3675
|
+
if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) {
|
|
3676
|
+
if (this.activeTo[a] > from) {
|
|
3677
|
+
this.to = this.activeTo[a];
|
|
3678
|
+
this.endSide = this.active[a].endSide;
|
|
3679
|
+
break;
|
|
3680
|
+
}
|
|
3681
|
+
this.removeActive(a);
|
|
3682
|
+
if (trackOpen)
|
|
3683
|
+
remove(trackOpen, a);
|
|
3684
|
+
}
|
|
3685
|
+
else if (!this.cursor.value) {
|
|
3686
|
+
this.to = this.endSide = 1000000000 /* Far */;
|
|
3687
|
+
break;
|
|
3688
|
+
}
|
|
3689
|
+
else if (this.cursor.from > from) {
|
|
3690
|
+
this.to = this.cursor.from;
|
|
3691
|
+
this.endSide = this.cursor.startSide;
|
|
3692
|
+
break;
|
|
3693
|
+
}
|
|
3694
|
+
else {
|
|
3695
|
+
let nextVal = this.cursor.value;
|
|
3696
|
+
if (!nextVal.point) { // Opening a range
|
|
3697
|
+
this.addActive(trackOpen);
|
|
3698
|
+
this.cursor.next();
|
|
3699
|
+
}
|
|
3700
|
+
else if (wasPoint && this.cursor.to == this.to && this.cursor.from < this.cursor.to) {
|
|
3701
|
+
// Ignore any non-empty points that end precisely at the end of the prev point
|
|
3702
|
+
this.cursor.next();
|
|
3703
|
+
}
|
|
3704
|
+
else { // New point
|
|
3705
|
+
this.point = nextVal;
|
|
3706
|
+
this.pointFrom = this.cursor.from;
|
|
3707
|
+
this.pointRank = this.cursor.rank;
|
|
3708
|
+
this.to = this.cursor.to;
|
|
3709
|
+
this.endSide = nextVal.endSide;
|
|
3710
|
+
if (this.cursor.from < from)
|
|
3711
|
+
trackExtra = 1;
|
|
3712
|
+
this.cursor.next();
|
|
3713
|
+
this.forward(this.to, this.endSide);
|
|
3714
|
+
break;
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
if (trackOpen) {
|
|
3719
|
+
let openStart = 0;
|
|
3720
|
+
while (openStart < trackOpen.length && trackOpen[openStart] < from)
|
|
3721
|
+
openStart++;
|
|
3722
|
+
this.openStart = openStart + trackExtra;
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
activeForPoint(to) {
|
|
3726
|
+
if (!this.active.length)
|
|
3727
|
+
return this.active;
|
|
3728
|
+
let active = [];
|
|
3729
|
+
for (let i = this.active.length - 1; i >= 0; i--) {
|
|
3730
|
+
if (this.activeRank[i] < this.pointRank)
|
|
3731
|
+
break;
|
|
3732
|
+
if (this.activeTo[i] > to || this.activeTo[i] == to && this.active[i].endSide >= this.point.endSide)
|
|
3733
|
+
active.push(this.active[i]);
|
|
3734
|
+
}
|
|
3735
|
+
return active.reverse();
|
|
3736
|
+
}
|
|
3737
|
+
openEnd(to) {
|
|
3738
|
+
let open = 0;
|
|
3739
|
+
for (let i = this.activeTo.length - 1; i >= 0 && this.activeTo[i] > to; i--)
|
|
3740
|
+
open++;
|
|
3741
|
+
return open;
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
function compare(a, startA, b, startB, length, comparator) {
|
|
3745
|
+
a.goto(startA);
|
|
3746
|
+
b.goto(startB);
|
|
3747
|
+
let endB = startB + length;
|
|
3748
|
+
let pos = startB, dPos = startB - startA;
|
|
3749
|
+
for (;;) {
|
|
3750
|
+
let diff = (a.to + dPos) - b.to || a.endSide - b.endSide;
|
|
3751
|
+
let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB);
|
|
3752
|
+
if (a.point || b.point) {
|
|
3753
|
+
if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) &&
|
|
3754
|
+
sameValues(a.activeForPoint(a.to + dPos), b.activeForPoint(b.to))))
|
|
3755
|
+
comparator.comparePoint(pos, clipEnd, a.point, b.point);
|
|
3756
|
+
}
|
|
3757
|
+
else {
|
|
3758
|
+
if (clipEnd > pos && !sameValues(a.active, b.active))
|
|
3759
|
+
comparator.compareRange(pos, clipEnd, a.active, b.active);
|
|
3760
|
+
}
|
|
3761
|
+
if (end > endB)
|
|
3762
|
+
break;
|
|
3763
|
+
pos = end;
|
|
3764
|
+
if (diff <= 0)
|
|
3765
|
+
a.next();
|
|
3766
|
+
if (diff >= 0)
|
|
3767
|
+
b.next();
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
function sameValues(a, b) {
|
|
3771
|
+
if (a.length != b.length)
|
|
3772
|
+
return false;
|
|
3773
|
+
for (let i = 0; i < a.length; i++)
|
|
3774
|
+
if (a[i] != b[i] && !a[i].eq(b[i]))
|
|
3775
|
+
return false;
|
|
3776
|
+
return true;
|
|
3777
|
+
}
|
|
3778
|
+
function remove(array, index) {
|
|
3779
|
+
for (let i = index, e = array.length - 1; i < e; i++)
|
|
3780
|
+
array[i] = array[i + 1];
|
|
3781
|
+
array.pop();
|
|
3782
|
+
}
|
|
3783
|
+
function insert(array, index, value) {
|
|
3784
|
+
for (let i = array.length - 1; i >= index; i--)
|
|
3785
|
+
array[i + 1] = array[i];
|
|
3786
|
+
array[index] = value;
|
|
3787
|
+
}
|
|
3788
|
+
function findMinIndex(value, array) {
|
|
3789
|
+
let found = -1, foundPos = 1000000000 /* Far */;
|
|
3790
|
+
for (let i = 0; i < array.length; i++)
|
|
3791
|
+
if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) {
|
|
3792
|
+
found = i;
|
|
3793
|
+
foundPos = array[i];
|
|
3794
|
+
}
|
|
3795
|
+
return found;
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3798
|
+
/**
|
|
3799
|
+
Count the column position at the given offset into the string,
|
|
3800
|
+
taking extending characters and tab size into account.
|
|
3801
|
+
*/
|
|
3802
|
+
function countColumn(string, tabSize, to = string.length) {
|
|
3803
|
+
let n = 0;
|
|
3804
|
+
for (let i = 0; i < to;) {
|
|
3805
|
+
if (string.charCodeAt(i) == 9) {
|
|
3806
|
+
n += tabSize - (n % tabSize);
|
|
3807
|
+
i++;
|
|
3808
|
+
}
|
|
3809
|
+
else {
|
|
3810
|
+
n++;
|
|
3811
|
+
i = findClusterBreak(string, i);
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
return n;
|
|
3815
|
+
}
|
|
3816
|
+
/**
|
|
3817
|
+
Find the offset that corresponds to the given column position in a
|
|
3818
|
+
string, taking extending characters and tab size into account. By
|
|
3819
|
+
default, the string length is returned when it is too short to
|
|
3820
|
+
reach the column. Pass `strict` true to make it return -1 in that
|
|
3821
|
+
situation.
|
|
3822
|
+
*/
|
|
3823
|
+
function findColumn(string, col, tabSize, strict) {
|
|
3824
|
+
for (let i = 0, n = 0;;) {
|
|
3825
|
+
if (n >= col)
|
|
3826
|
+
return i;
|
|
3827
|
+
if (i == string.length)
|
|
3828
|
+
break;
|
|
3829
|
+
n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1;
|
|
3830
|
+
i = findClusterBreak(string, i);
|
|
3831
|
+
}
|
|
3832
|
+
return strict === true ? -1 : string.length;
|
|
3833
|
+
}
|
|
3834
|
+
|
|
2310
3835
|
exports.Annotation = Annotation;
|
|
2311
3836
|
exports.AnnotationType = AnnotationType;
|
|
2312
3837
|
exports.ChangeDesc = ChangeDesc;
|
|
@@ -2315,10 +3840,22 @@ exports.Compartment = Compartment;
|
|
|
2315
3840
|
exports.EditorSelection = EditorSelection;
|
|
2316
3841
|
exports.EditorState = EditorState;
|
|
2317
3842
|
exports.Facet = Facet;
|
|
3843
|
+
exports.Line = Line;
|
|
2318
3844
|
exports.Prec = Prec;
|
|
3845
|
+
exports.Range = Range;
|
|
3846
|
+
exports.RangeSet = RangeSet;
|
|
3847
|
+
exports.RangeSetBuilder = RangeSetBuilder;
|
|
3848
|
+
exports.RangeValue = RangeValue;
|
|
2319
3849
|
exports.SelectionRange = SelectionRange;
|
|
2320
3850
|
exports.StateEffect = StateEffect;
|
|
2321
3851
|
exports.StateEffectType = StateEffectType;
|
|
2322
3852
|
exports.StateField = StateField;
|
|
3853
|
+
exports.Text = Text;
|
|
2323
3854
|
exports.Transaction = Transaction;
|
|
3855
|
+
exports.codePointAt = codePointAt;
|
|
3856
|
+
exports.codePointSize = codePointSize;
|
|
2324
3857
|
exports.combineConfig = combineConfig;
|
|
3858
|
+
exports.countColumn = countColumn;
|
|
3859
|
+
exports.findClusterBreak = findClusterBreak;
|
|
3860
|
+
exports.findColumn = findColumn;
|
|
3861
|
+
exports.fromCodePoint = fromCodePoint;
|