@codemirror/state 0.19.8 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/index.cjs +1694 -123
- package/dist/index.d.ts +527 -65
- package/dist/index.js +1664 -102
- package/package.json +1 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,655 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
The data structure for documents. @nonabstract
|
|
3
|
+
*/
|
|
4
|
+
class Text {
|
|
5
|
+
/**
|
|
6
|
+
@internal
|
|
7
|
+
*/
|
|
8
|
+
constructor() { }
|
|
9
|
+
/**
|
|
10
|
+
Get the line description around the given position.
|
|
11
|
+
*/
|
|
12
|
+
lineAt(pos) {
|
|
13
|
+
if (pos < 0 || pos > this.length)
|
|
14
|
+
throw new RangeError(`Invalid position ${pos} in document of length ${this.length}`);
|
|
15
|
+
return this.lineInner(pos, false, 1, 0);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
Get the description for the given (1-based) line number.
|
|
19
|
+
*/
|
|
20
|
+
line(n) {
|
|
21
|
+
if (n < 1 || n > this.lines)
|
|
22
|
+
throw new RangeError(`Invalid line number ${n} in ${this.lines}-line document`);
|
|
23
|
+
return this.lineInner(n, true, 1, 0);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
Replace a range of the text with the given content.
|
|
27
|
+
*/
|
|
28
|
+
replace(from, to, text) {
|
|
29
|
+
let parts = [];
|
|
30
|
+
this.decompose(0, from, parts, 2 /* To */);
|
|
31
|
+
if (text.length)
|
|
32
|
+
text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */);
|
|
33
|
+
this.decompose(to, this.length, parts, 1 /* From */);
|
|
34
|
+
return TextNode.from(parts, this.length - (to - from) + text.length);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
Append another document to this one.
|
|
38
|
+
*/
|
|
39
|
+
append(other) {
|
|
40
|
+
return this.replace(this.length, this.length, other);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
Retrieve the text between the given points.
|
|
44
|
+
*/
|
|
45
|
+
slice(from, to = this.length) {
|
|
46
|
+
let parts = [];
|
|
47
|
+
this.decompose(from, to, parts, 0);
|
|
48
|
+
return TextNode.from(parts, to - from);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
Test whether this text is equal to another instance.
|
|
52
|
+
*/
|
|
53
|
+
eq(other) {
|
|
54
|
+
if (other == this)
|
|
55
|
+
return true;
|
|
56
|
+
if (other.length != this.length || other.lines != this.lines)
|
|
57
|
+
return false;
|
|
58
|
+
let start = this.scanIdentical(other, 1), end = this.length - this.scanIdentical(other, -1);
|
|
59
|
+
let a = new RawTextCursor(this), b = new RawTextCursor(other);
|
|
60
|
+
for (let skip = start, pos = start;;) {
|
|
61
|
+
a.next(skip);
|
|
62
|
+
b.next(skip);
|
|
63
|
+
skip = 0;
|
|
64
|
+
if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value)
|
|
65
|
+
return false;
|
|
66
|
+
pos += a.value.length;
|
|
67
|
+
if (a.done || pos >= end)
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
Iterate over the text. When `dir` is `-1`, iteration happens
|
|
73
|
+
from end to start. This will return lines and the breaks between
|
|
74
|
+
them as separate strings.
|
|
75
|
+
*/
|
|
76
|
+
iter(dir = 1) { return new RawTextCursor(this, dir); }
|
|
77
|
+
/**
|
|
78
|
+
Iterate over a range of the text. When `from` > `to`, the
|
|
79
|
+
iterator will run in reverse.
|
|
80
|
+
*/
|
|
81
|
+
iterRange(from, to = this.length) { return new PartialTextCursor(this, from, to); }
|
|
82
|
+
/**
|
|
83
|
+
Return a cursor that iterates over the given range of lines,
|
|
84
|
+
_without_ returning the line breaks between, and yielding empty
|
|
85
|
+
strings for empty lines.
|
|
86
|
+
|
|
87
|
+
When `from` and `to` are given, they should be 1-based line numbers.
|
|
88
|
+
*/
|
|
89
|
+
iterLines(from, to) {
|
|
90
|
+
let inner;
|
|
91
|
+
if (from == null) {
|
|
92
|
+
inner = this.iter();
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (to == null)
|
|
96
|
+
to = this.lines + 1;
|
|
97
|
+
let start = this.line(from).from;
|
|
98
|
+
inner = this.iterRange(start, Math.max(start, to == this.lines + 1 ? this.length : to <= 1 ? 0 : this.line(to - 1).to));
|
|
99
|
+
}
|
|
100
|
+
return new LineCursor(inner);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
@internal
|
|
104
|
+
*/
|
|
105
|
+
toString() { return this.sliceString(0); }
|
|
106
|
+
/**
|
|
107
|
+
Convert the document to an array of lines (which can be
|
|
108
|
+
deserialized again via [`Text.of`](https://codemirror.net/6/docs/ref/#state.Text^of)).
|
|
109
|
+
*/
|
|
110
|
+
toJSON() {
|
|
111
|
+
let lines = [];
|
|
112
|
+
this.flatten(lines);
|
|
113
|
+
return lines;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
Create a `Text` instance for the given array of lines.
|
|
117
|
+
*/
|
|
118
|
+
static of(text) {
|
|
119
|
+
if (text.length == 0)
|
|
120
|
+
throw new RangeError("A document must have at least one line");
|
|
121
|
+
if (text.length == 1 && !text[0])
|
|
122
|
+
return Text.empty;
|
|
123
|
+
return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Leaves store an array of line strings. There are always line breaks
|
|
127
|
+
// between these strings. Leaves are limited in size and have to be
|
|
128
|
+
// contained in TextNode instances for bigger documents.
|
|
129
|
+
class TextLeaf extends Text {
|
|
130
|
+
constructor(text, length = textLength(text)) {
|
|
131
|
+
super();
|
|
132
|
+
this.text = text;
|
|
133
|
+
this.length = length;
|
|
134
|
+
}
|
|
135
|
+
get lines() { return this.text.length; }
|
|
136
|
+
get children() { return null; }
|
|
137
|
+
lineInner(target, isLine, line, offset) {
|
|
138
|
+
for (let i = 0;; i++) {
|
|
139
|
+
let string = this.text[i], end = offset + string.length;
|
|
140
|
+
if ((isLine ? line : end) >= target)
|
|
141
|
+
return new Line(offset, end, line, string);
|
|
142
|
+
offset = end + 1;
|
|
143
|
+
line++;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
decompose(from, to, target, open) {
|
|
147
|
+
let text = from <= 0 && to >= this.length ? this
|
|
148
|
+
: new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from));
|
|
149
|
+
if (open & 1 /* From */) {
|
|
150
|
+
let prev = target.pop();
|
|
151
|
+
let joined = appendText(text.text, prev.text.slice(), 0, text.length);
|
|
152
|
+
if (joined.length <= 32 /* Branch */) {
|
|
153
|
+
target.push(new TextLeaf(joined, prev.length + text.length));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
let mid = joined.length >> 1;
|
|
157
|
+
target.push(new TextLeaf(joined.slice(0, mid)), new TextLeaf(joined.slice(mid)));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
target.push(text);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
replace(from, to, text) {
|
|
165
|
+
if (!(text instanceof TextLeaf))
|
|
166
|
+
return super.replace(from, to, text);
|
|
167
|
+
let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to);
|
|
168
|
+
let newLen = this.length + text.length - (to - from);
|
|
169
|
+
if (lines.length <= 32 /* Branch */)
|
|
170
|
+
return new TextLeaf(lines, newLen);
|
|
171
|
+
return TextNode.from(TextLeaf.split(lines, []), newLen);
|
|
172
|
+
}
|
|
173
|
+
sliceString(from, to = this.length, lineSep = "\n") {
|
|
174
|
+
let result = "";
|
|
175
|
+
for (let pos = 0, i = 0; pos <= to && i < this.text.length; i++) {
|
|
176
|
+
let line = this.text[i], end = pos + line.length;
|
|
177
|
+
if (pos > from && i)
|
|
178
|
+
result += lineSep;
|
|
179
|
+
if (from < end && to > pos)
|
|
180
|
+
result += line.slice(Math.max(0, from - pos), to - pos);
|
|
181
|
+
pos = end + 1;
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
flatten(target) {
|
|
186
|
+
for (let line of this.text)
|
|
187
|
+
target.push(line);
|
|
188
|
+
}
|
|
189
|
+
scanIdentical() { return 0; }
|
|
190
|
+
static split(text, target) {
|
|
191
|
+
let part = [], len = -1;
|
|
192
|
+
for (let line of text) {
|
|
193
|
+
part.push(line);
|
|
194
|
+
len += line.length + 1;
|
|
195
|
+
if (part.length == 32 /* Branch */) {
|
|
196
|
+
target.push(new TextLeaf(part, len));
|
|
197
|
+
part = [];
|
|
198
|
+
len = -1;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (len > -1)
|
|
202
|
+
target.push(new TextLeaf(part, len));
|
|
203
|
+
return target;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Nodes provide the tree structure of the `Text` type. They store a
|
|
207
|
+
// number of other nodes or leaves, taking care to balance themselves
|
|
208
|
+
// on changes. There are implied line breaks _between_ the children of
|
|
209
|
+
// a node (but not before the first or after the last child).
|
|
210
|
+
class TextNode extends Text {
|
|
211
|
+
constructor(children, length) {
|
|
212
|
+
super();
|
|
213
|
+
this.children = children;
|
|
214
|
+
this.length = length;
|
|
215
|
+
this.lines = 0;
|
|
216
|
+
for (let child of children)
|
|
217
|
+
this.lines += child.lines;
|
|
218
|
+
}
|
|
219
|
+
lineInner(target, isLine, line, offset) {
|
|
220
|
+
for (let i = 0;; i++) {
|
|
221
|
+
let child = this.children[i], end = offset + child.length, endLine = line + child.lines - 1;
|
|
222
|
+
if ((isLine ? endLine : end) >= target)
|
|
223
|
+
return child.lineInner(target, isLine, line, offset);
|
|
224
|
+
offset = end + 1;
|
|
225
|
+
line = endLine + 1;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
decompose(from, to, target, open) {
|
|
229
|
+
for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) {
|
|
230
|
+
let child = this.children[i], end = pos + child.length;
|
|
231
|
+
if (from <= end && to >= pos) {
|
|
232
|
+
let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0));
|
|
233
|
+
if (pos >= from && end <= to && !childOpen)
|
|
234
|
+
target.push(child);
|
|
235
|
+
else
|
|
236
|
+
child.decompose(from - pos, to - pos, target, childOpen);
|
|
237
|
+
}
|
|
238
|
+
pos = end + 1;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
replace(from, to, text) {
|
|
242
|
+
if (text.lines < this.lines)
|
|
243
|
+
for (let i = 0, pos = 0; i < this.children.length; i++) {
|
|
244
|
+
let child = this.children[i], end = pos + child.length;
|
|
245
|
+
// Fast path: if the change only affects one child and the
|
|
246
|
+
// child's size remains in the acceptable range, only update
|
|
247
|
+
// that child
|
|
248
|
+
if (from >= pos && to <= end) {
|
|
249
|
+
let updated = child.replace(from - pos, to - pos, text);
|
|
250
|
+
let totalLines = this.lines - child.lines + updated.lines;
|
|
251
|
+
if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) &&
|
|
252
|
+
updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) {
|
|
253
|
+
let copy = this.children.slice();
|
|
254
|
+
copy[i] = updated;
|
|
255
|
+
return new TextNode(copy, this.length - (to - from) + text.length);
|
|
256
|
+
}
|
|
257
|
+
return super.replace(pos, end, updated);
|
|
258
|
+
}
|
|
259
|
+
pos = end + 1;
|
|
260
|
+
}
|
|
261
|
+
return super.replace(from, to, text);
|
|
262
|
+
}
|
|
263
|
+
sliceString(from, to = this.length, lineSep = "\n") {
|
|
264
|
+
let result = "";
|
|
265
|
+
for (let i = 0, pos = 0; i < this.children.length && pos <= to; i++) {
|
|
266
|
+
let child = this.children[i], end = pos + child.length;
|
|
267
|
+
if (pos > from && i)
|
|
268
|
+
result += lineSep;
|
|
269
|
+
if (from < end && to > pos)
|
|
270
|
+
result += child.sliceString(from - pos, to - pos, lineSep);
|
|
271
|
+
pos = end + 1;
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
flatten(target) {
|
|
276
|
+
for (let child of this.children)
|
|
277
|
+
child.flatten(target);
|
|
278
|
+
}
|
|
279
|
+
scanIdentical(other, dir) {
|
|
280
|
+
if (!(other instanceof TextNode))
|
|
281
|
+
return 0;
|
|
282
|
+
let length = 0;
|
|
283
|
+
let [iA, iB, eA, eB] = dir > 0 ? [0, 0, this.children.length, other.children.length]
|
|
284
|
+
: [this.children.length - 1, other.children.length - 1, -1, -1];
|
|
285
|
+
for (;; iA += dir, iB += dir) {
|
|
286
|
+
if (iA == eA || iB == eB)
|
|
287
|
+
return length;
|
|
288
|
+
let chA = this.children[iA], chB = other.children[iB];
|
|
289
|
+
if (chA != chB)
|
|
290
|
+
return length + chA.scanIdentical(chB, dir);
|
|
291
|
+
length += chA.length + 1;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
static from(children, length = children.reduce((l, ch) => l + ch.length + 1, -1)) {
|
|
295
|
+
let lines = 0;
|
|
296
|
+
for (let ch of children)
|
|
297
|
+
lines += ch.lines;
|
|
298
|
+
if (lines < 32 /* Branch */) {
|
|
299
|
+
let flat = [];
|
|
300
|
+
for (let ch of children)
|
|
301
|
+
ch.flatten(flat);
|
|
302
|
+
return new TextLeaf(flat, length);
|
|
303
|
+
}
|
|
304
|
+
let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
|
305
|
+
let chunked = [], currentLines = 0, currentLen = -1, currentChunk = [];
|
|
306
|
+
function add(child) {
|
|
307
|
+
let last;
|
|
308
|
+
if (child.lines > maxChunk && child instanceof TextNode) {
|
|
309
|
+
for (let node of child.children)
|
|
310
|
+
add(node);
|
|
311
|
+
}
|
|
312
|
+
else if (child.lines > minChunk && (currentLines > minChunk || !currentLines)) {
|
|
313
|
+
flush();
|
|
314
|
+
chunked.push(child);
|
|
315
|
+
}
|
|
316
|
+
else if (child instanceof TextLeaf && currentLines &&
|
|
317
|
+
(last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf &&
|
|
318
|
+
child.lines + last.lines <= 32 /* Branch */) {
|
|
319
|
+
currentLines += child.lines;
|
|
320
|
+
currentLen += child.length + 1;
|
|
321
|
+
currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
if (currentLines + child.lines > chunk)
|
|
325
|
+
flush();
|
|
326
|
+
currentLines += child.lines;
|
|
327
|
+
currentLen += child.length + 1;
|
|
328
|
+
currentChunk.push(child);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function flush() {
|
|
332
|
+
if (currentLines == 0)
|
|
333
|
+
return;
|
|
334
|
+
chunked.push(currentChunk.length == 1 ? currentChunk[0] : TextNode.from(currentChunk, currentLen));
|
|
335
|
+
currentLen = -1;
|
|
336
|
+
currentLines = currentChunk.length = 0;
|
|
337
|
+
}
|
|
338
|
+
for (let child of children)
|
|
339
|
+
add(child);
|
|
340
|
+
flush();
|
|
341
|
+
return chunked.length == 1 ? chunked[0] : new TextNode(chunked, length);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
Text.empty = /*@__PURE__*/new TextLeaf([""], 0);
|
|
345
|
+
function textLength(text) {
|
|
346
|
+
let length = -1;
|
|
347
|
+
for (let line of text)
|
|
348
|
+
length += line.length + 1;
|
|
349
|
+
return length;
|
|
350
|
+
}
|
|
351
|
+
function appendText(text, target, from = 0, to = 1e9) {
|
|
352
|
+
for (let pos = 0, i = 0, first = true; i < text.length && pos <= to; i++) {
|
|
353
|
+
let line = text[i], end = pos + line.length;
|
|
354
|
+
if (end >= from) {
|
|
355
|
+
if (end > to)
|
|
356
|
+
line = line.slice(0, to - pos);
|
|
357
|
+
if (pos < from)
|
|
358
|
+
line = line.slice(from - pos);
|
|
359
|
+
if (first) {
|
|
360
|
+
target[target.length - 1] += line;
|
|
361
|
+
first = false;
|
|
362
|
+
}
|
|
363
|
+
else
|
|
364
|
+
target.push(line);
|
|
365
|
+
}
|
|
366
|
+
pos = end + 1;
|
|
367
|
+
}
|
|
368
|
+
return target;
|
|
369
|
+
}
|
|
370
|
+
function sliceText(text, from, to) {
|
|
371
|
+
return appendText(text, [""], from, to);
|
|
372
|
+
}
|
|
373
|
+
class RawTextCursor {
|
|
374
|
+
constructor(text, dir = 1) {
|
|
375
|
+
this.dir = dir;
|
|
376
|
+
this.done = false;
|
|
377
|
+
this.lineBreak = false;
|
|
378
|
+
this.value = "";
|
|
379
|
+
this.nodes = [text];
|
|
380
|
+
this.offsets = [dir > 0 ? 1 : (text instanceof TextLeaf ? text.text.length : text.children.length) << 1];
|
|
381
|
+
}
|
|
382
|
+
nextInner(skip, dir) {
|
|
383
|
+
this.done = this.lineBreak = false;
|
|
384
|
+
for (;;) {
|
|
385
|
+
let last = this.nodes.length - 1;
|
|
386
|
+
let top = this.nodes[last], offsetValue = this.offsets[last], offset = offsetValue >> 1;
|
|
387
|
+
let size = top instanceof TextLeaf ? top.text.length : top.children.length;
|
|
388
|
+
if (offset == (dir > 0 ? size : 0)) {
|
|
389
|
+
if (last == 0) {
|
|
390
|
+
this.done = true;
|
|
391
|
+
this.value = "";
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
if (dir > 0)
|
|
395
|
+
this.offsets[last - 1]++;
|
|
396
|
+
this.nodes.pop();
|
|
397
|
+
this.offsets.pop();
|
|
398
|
+
}
|
|
399
|
+
else if ((offsetValue & 1) == (dir > 0 ? 0 : 1)) {
|
|
400
|
+
this.offsets[last] += dir;
|
|
401
|
+
if (skip == 0) {
|
|
402
|
+
this.lineBreak = true;
|
|
403
|
+
this.value = "\n";
|
|
404
|
+
return this;
|
|
405
|
+
}
|
|
406
|
+
skip--;
|
|
407
|
+
}
|
|
408
|
+
else if (top instanceof TextLeaf) {
|
|
409
|
+
// Move to the next string
|
|
410
|
+
let next = top.text[offset + (dir < 0 ? -1 : 0)];
|
|
411
|
+
this.offsets[last] += dir;
|
|
412
|
+
if (next.length > Math.max(0, skip)) {
|
|
413
|
+
this.value = skip == 0 ? next : dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip);
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
skip -= next.length;
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
let next = top.children[offset + (dir < 0 ? -1 : 0)];
|
|
420
|
+
if (skip > next.length) {
|
|
421
|
+
skip -= next.length;
|
|
422
|
+
this.offsets[last] += dir;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
if (dir < 0)
|
|
426
|
+
this.offsets[last]--;
|
|
427
|
+
this.nodes.push(next);
|
|
428
|
+
this.offsets.push(dir > 0 ? 1 : (next instanceof TextLeaf ? next.text.length : next.children.length) << 1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
next(skip = 0) {
|
|
434
|
+
if (skip < 0) {
|
|
435
|
+
this.nextInner(-skip, (-this.dir));
|
|
436
|
+
skip = this.value.length;
|
|
437
|
+
}
|
|
438
|
+
return this.nextInner(skip, this.dir);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
class PartialTextCursor {
|
|
442
|
+
constructor(text, start, end) {
|
|
443
|
+
this.value = "";
|
|
444
|
+
this.done = false;
|
|
445
|
+
this.cursor = new RawTextCursor(text, start > end ? -1 : 1);
|
|
446
|
+
this.pos = start > end ? text.length : 0;
|
|
447
|
+
this.from = Math.min(start, end);
|
|
448
|
+
this.to = Math.max(start, end);
|
|
449
|
+
}
|
|
450
|
+
nextInner(skip, dir) {
|
|
451
|
+
if (dir < 0 ? this.pos <= this.from : this.pos >= this.to) {
|
|
452
|
+
this.value = "";
|
|
453
|
+
this.done = true;
|
|
454
|
+
return this;
|
|
455
|
+
}
|
|
456
|
+
skip += Math.max(0, dir < 0 ? this.pos - this.to : this.from - this.pos);
|
|
457
|
+
let limit = dir < 0 ? this.pos - this.from : this.to - this.pos;
|
|
458
|
+
if (skip > limit)
|
|
459
|
+
skip = limit;
|
|
460
|
+
limit -= skip;
|
|
461
|
+
let { value } = this.cursor.next(skip);
|
|
462
|
+
this.pos += (value.length + skip) * dir;
|
|
463
|
+
this.value = value.length <= limit ? value : dir < 0 ? value.slice(value.length - limit) : value.slice(0, limit);
|
|
464
|
+
this.done = !this.value;
|
|
465
|
+
return this;
|
|
466
|
+
}
|
|
467
|
+
next(skip = 0) {
|
|
468
|
+
if (skip < 0)
|
|
469
|
+
skip = Math.max(skip, this.from - this.pos);
|
|
470
|
+
else if (skip > 0)
|
|
471
|
+
skip = Math.min(skip, this.to - this.pos);
|
|
472
|
+
return this.nextInner(skip, this.cursor.dir);
|
|
473
|
+
}
|
|
474
|
+
get lineBreak() { return this.cursor.lineBreak && this.value != ""; }
|
|
475
|
+
}
|
|
476
|
+
class LineCursor {
|
|
477
|
+
constructor(inner) {
|
|
478
|
+
this.inner = inner;
|
|
479
|
+
this.afterBreak = true;
|
|
480
|
+
this.value = "";
|
|
481
|
+
this.done = false;
|
|
482
|
+
}
|
|
483
|
+
next(skip = 0) {
|
|
484
|
+
let { done, lineBreak, value } = this.inner.next(skip);
|
|
485
|
+
if (done) {
|
|
486
|
+
this.done = true;
|
|
487
|
+
this.value = "";
|
|
488
|
+
}
|
|
489
|
+
else if (lineBreak) {
|
|
490
|
+
if (this.afterBreak) {
|
|
491
|
+
this.value = "";
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
this.afterBreak = true;
|
|
495
|
+
this.next();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
this.value = value;
|
|
500
|
+
this.afterBreak = false;
|
|
501
|
+
}
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
get lineBreak() { return false; }
|
|
505
|
+
}
|
|
506
|
+
if (typeof Symbol != "undefined") {
|
|
507
|
+
Text.prototype[Symbol.iterator] = function () { return this.iter(); };
|
|
508
|
+
RawTextCursor.prototype[Symbol.iterator] = PartialTextCursor.prototype[Symbol.iterator] =
|
|
509
|
+
LineCursor.prototype[Symbol.iterator] = function () { return this; };
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
This type describes a line in the document. It is created
|
|
513
|
+
on-demand when lines are [queried](https://codemirror.net/6/docs/ref/#state.Text.lineAt).
|
|
514
|
+
*/
|
|
515
|
+
class Line {
|
|
516
|
+
/**
|
|
517
|
+
@internal
|
|
518
|
+
*/
|
|
519
|
+
constructor(
|
|
520
|
+
/**
|
|
521
|
+
The position of the start of the line.
|
|
522
|
+
*/
|
|
523
|
+
from,
|
|
524
|
+
/**
|
|
525
|
+
The position at the end of the line (_before_ the line break,
|
|
526
|
+
or at the end of document for the last line).
|
|
527
|
+
*/
|
|
528
|
+
to,
|
|
529
|
+
/**
|
|
530
|
+
This line's line number (1-based).
|
|
531
|
+
*/
|
|
532
|
+
number,
|
|
533
|
+
/**
|
|
534
|
+
The line's content.
|
|
535
|
+
*/
|
|
536
|
+
text) {
|
|
537
|
+
this.from = from;
|
|
538
|
+
this.to = to;
|
|
539
|
+
this.number = number;
|
|
540
|
+
this.text = text;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
The length of the line (not including any line break after it).
|
|
544
|
+
*/
|
|
545
|
+
get length() { return this.to - this.from; }
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Compressed representation of the Grapheme_Cluster_Break=Extend
|
|
549
|
+
// information from
|
|
550
|
+
// http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt.
|
|
551
|
+
// Each pair of elements represents a range, as an offet from the
|
|
552
|
+
// previous range and a length. Numbers are in base-36, with the empty
|
|
553
|
+
// string being a shorthand for 1.
|
|
554
|
+
let extend = /*@__PURE__*/"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);
|
|
555
|
+
// Convert offsets into absolute values
|
|
556
|
+
for (let i = 1; i < extend.length; i++)
|
|
557
|
+
extend[i] += extend[i - 1];
|
|
558
|
+
function isExtendingChar(code) {
|
|
559
|
+
for (let i = 1; i < extend.length; i += 2)
|
|
560
|
+
if (extend[i] > code)
|
|
561
|
+
return extend[i - 1] <= code;
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
function isRegionalIndicator(code) {
|
|
565
|
+
return code >= 0x1F1E6 && code <= 0x1F1FF;
|
|
566
|
+
}
|
|
567
|
+
const ZWJ = 0x200d;
|
|
568
|
+
/**
|
|
569
|
+
Returns a next grapheme cluster break _after_ (not equal to)
|
|
570
|
+
`pos`, if `forward` is true, or before otherwise. Returns `pos`
|
|
571
|
+
itself if no further cluster break is available in the string.
|
|
572
|
+
Moves across surrogate pairs, extending characters (when
|
|
573
|
+
`includeExtending` is true), characters joined with zero-width
|
|
574
|
+
joiners, and flag emoji.
|
|
575
|
+
*/
|
|
576
|
+
function findClusterBreak(str, pos, forward = true, includeExtending = true) {
|
|
577
|
+
return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending);
|
|
578
|
+
}
|
|
579
|
+
function nextClusterBreak(str, pos, includeExtending) {
|
|
580
|
+
if (pos == str.length)
|
|
581
|
+
return pos;
|
|
582
|
+
// If pos is in the middle of a surrogate pair, move to its start
|
|
583
|
+
if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1)))
|
|
584
|
+
pos--;
|
|
585
|
+
let prev = codePointAt(str, pos);
|
|
586
|
+
pos += codePointSize(prev);
|
|
587
|
+
while (pos < str.length) {
|
|
588
|
+
let next = codePointAt(str, pos);
|
|
589
|
+
if (prev == ZWJ || next == ZWJ || includeExtending && isExtendingChar(next)) {
|
|
590
|
+
pos += codePointSize(next);
|
|
591
|
+
prev = next;
|
|
592
|
+
}
|
|
593
|
+
else if (isRegionalIndicator(next)) {
|
|
594
|
+
let countBefore = 0, i = pos - 2;
|
|
595
|
+
while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) {
|
|
596
|
+
countBefore++;
|
|
597
|
+
i -= 2;
|
|
598
|
+
}
|
|
599
|
+
if (countBefore % 2 == 0)
|
|
600
|
+
break;
|
|
601
|
+
else
|
|
602
|
+
pos += 2;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return pos;
|
|
609
|
+
}
|
|
610
|
+
function prevClusterBreak(str, pos, includeExtending) {
|
|
611
|
+
while (pos > 0) {
|
|
612
|
+
let found = nextClusterBreak(str, pos - 2, includeExtending);
|
|
613
|
+
if (found < pos)
|
|
614
|
+
return found;
|
|
615
|
+
pos--;
|
|
616
|
+
}
|
|
617
|
+
return 0;
|
|
618
|
+
}
|
|
619
|
+
function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
|
|
620
|
+
function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
|
|
621
|
+
/**
|
|
622
|
+
Find the code point at the given position in a string (like the
|
|
623
|
+
[`codePointAt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt)
|
|
624
|
+
string method).
|
|
625
|
+
*/
|
|
626
|
+
function codePointAt(str, pos) {
|
|
627
|
+
let code0 = str.charCodeAt(pos);
|
|
628
|
+
if (!surrogateHigh(code0) || pos + 1 == str.length)
|
|
629
|
+
return code0;
|
|
630
|
+
let code1 = str.charCodeAt(pos + 1);
|
|
631
|
+
if (!surrogateLow(code1))
|
|
632
|
+
return code0;
|
|
633
|
+
return ((code0 - 0xd800) << 10) + (code1 - 0xdc00) + 0x10000;
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
Given a Unicode codepoint, return the JavaScript string that
|
|
637
|
+
respresents it (like
|
|
638
|
+
[`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)).
|
|
639
|
+
*/
|
|
640
|
+
function fromCodePoint(code) {
|
|
641
|
+
if (code <= 0xffff)
|
|
642
|
+
return String.fromCharCode(code);
|
|
643
|
+
code -= 0x10000;
|
|
644
|
+
return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
The first character that takes up two positions in a JavaScript
|
|
648
|
+
string. It is often useful to compare with this after calling
|
|
649
|
+
`codePointAt`, to figure out whether your character takes up 1 or
|
|
650
|
+
2 index positions.
|
|
651
|
+
*/
|
|
652
|
+
function codePointSize(code) { return code < 0x10000 ? 1 : 2; }
|
|
3
653
|
|
|
4
654
|
const DefaultSplit = /\r\n?|\n/;
|
|
5
655
|
/**
|
|
@@ -35,9 +685,6 @@ class ChangeDesc {
|
|
|
35
685
|
// unaffected sections, and the length of the replacement content
|
|
36
686
|
// otherwise. So an insertion would be (0, n>0), a deletion (n>0,
|
|
37
687
|
// 0), and a replacement two positive numbers.
|
|
38
|
-
/**
|
|
39
|
-
@internal
|
|
40
|
-
*/
|
|
41
688
|
constructor(
|
|
42
689
|
/**
|
|
43
690
|
@internal
|
|
@@ -70,7 +717,9 @@ class ChangeDesc {
|
|
|
70
717
|
*/
|
|
71
718
|
get empty() { return this.sections.length == 0 || this.sections.length == 2 && this.sections[1] < 0; }
|
|
72
719
|
/**
|
|
73
|
-
Iterate over the unchanged parts left by these changes.
|
|
720
|
+
Iterate over the unchanged parts left by these changes. `posA`
|
|
721
|
+
provides the position of the range in the old document, `posB`
|
|
722
|
+
the new position in the changed document.
|
|
74
723
|
*/
|
|
75
724
|
iterGaps(f) {
|
|
76
725
|
for (let i = 0, posA = 0, posB = 0; i < this.sections.length;) {
|
|
@@ -89,6 +738,9 @@ class ChangeDesc {
|
|
|
89
738
|
Iterate over the ranges changed by these changes. (See
|
|
90
739
|
[`ChangeSet.iterChanges`](https://codemirror.net/6/docs/ref/#state.ChangeSet.iterChanges) for a
|
|
91
740
|
variant that also provides you with the inserted text.)
|
|
741
|
+
`fromA`/`toA` provides the extent of the change in the starting
|
|
742
|
+
document, `fromB`/`toB` the extent of the replacement in the
|
|
743
|
+
changed document.
|
|
92
744
|
|
|
93
745
|
When `individual` is true, adjacent changes (which are kept
|
|
94
746
|
separate for [position mapping](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) are
|
|
@@ -187,6 +839,10 @@ class ChangeDesc {
|
|
|
187
839
|
throw new RangeError("Invalid JSON representation of ChangeDesc");
|
|
188
840
|
return new ChangeDesc(json);
|
|
189
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
@internal
|
|
844
|
+
*/
|
|
845
|
+
static create(sections) { return new ChangeDesc(sections); }
|
|
190
846
|
}
|
|
191
847
|
/**
|
|
192
848
|
A change set represents a group of modifications to a document. It
|
|
@@ -194,9 +850,6 @@ stores the document length, and can only be applied to documents
|
|
|
194
850
|
with exactly that length.
|
|
195
851
|
*/
|
|
196
852
|
class ChangeSet extends ChangeDesc {
|
|
197
|
-
/**
|
|
198
|
-
@internal
|
|
199
|
-
*/
|
|
200
853
|
constructor(sections,
|
|
201
854
|
/**
|
|
202
855
|
@internal
|
|
@@ -275,7 +928,7 @@ class ChangeSet extends ChangeDesc {
|
|
|
275
928
|
Get a [change description](https://codemirror.net/6/docs/ref/#state.ChangeDesc) for this change
|
|
276
929
|
set.
|
|
277
930
|
*/
|
|
278
|
-
get desc() { return
|
|
931
|
+
get desc() { return ChangeDesc.create(this.sections); }
|
|
279
932
|
/**
|
|
280
933
|
@internal
|
|
281
934
|
*/
|
|
@@ -308,7 +961,7 @@ class ChangeSet extends ChangeDesc {
|
|
|
308
961
|
}
|
|
309
962
|
}
|
|
310
963
|
return { changes: new ChangeSet(resultSections, resultInserted),
|
|
311
|
-
filtered:
|
|
964
|
+
filtered: ChangeDesc.create(filteredSections) };
|
|
312
965
|
}
|
|
313
966
|
/**
|
|
314
967
|
Serialize this change set to a JSON-representable value.
|
|
@@ -410,6 +1063,12 @@ class ChangeSet extends ChangeDesc {
|
|
|
410
1063
|
}
|
|
411
1064
|
return new ChangeSet(sections, inserted);
|
|
412
1065
|
}
|
|
1066
|
+
/**
|
|
1067
|
+
@internal
|
|
1068
|
+
*/
|
|
1069
|
+
static createSet(sections, inserted) {
|
|
1070
|
+
return new ChangeSet(sections, inserted);
|
|
1071
|
+
}
|
|
413
1072
|
}
|
|
414
1073
|
function addSection(sections, len, ins, forceJoin = false) {
|
|
415
1074
|
if (len == 0 && ins <= 0)
|
|
@@ -513,7 +1172,7 @@ function mapSet(setA, setB, before, mkSet = false) {
|
|
|
513
1172
|
a.next();
|
|
514
1173
|
}
|
|
515
1174
|
else if (a.done && b.done) {
|
|
516
|
-
return insert ?
|
|
1175
|
+
return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections);
|
|
517
1176
|
}
|
|
518
1177
|
else {
|
|
519
1178
|
throw new Error("Mismatched change set lengths");
|
|
@@ -526,7 +1185,7 @@ function composeSets(setA, setB, mkSet = false) {
|
|
|
526
1185
|
let a = new SectionIter(setA), b = new SectionIter(setB);
|
|
527
1186
|
for (let open = false;;) {
|
|
528
1187
|
if (a.done && b.done) {
|
|
529
|
-
return insert ?
|
|
1188
|
+
return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections);
|
|
530
1189
|
}
|
|
531
1190
|
else if (a.ins == 0) { // Deletion in A
|
|
532
1191
|
addSection(sections, a.len, 0, open);
|
|
@@ -621,9 +1280,6 @@ is enabled, a [selection](https://codemirror.net/6/docs/ref/#state.EditorSelecti
|
|
|
621
1280
|
multiple ranges. By default, selections hold exactly one range.
|
|
622
1281
|
*/
|
|
623
1282
|
class SelectionRange {
|
|
624
|
-
/**
|
|
625
|
-
@internal
|
|
626
|
-
*/
|
|
627
1283
|
constructor(
|
|
628
1284
|
/**
|
|
629
1285
|
The lower boundary of the range.
|
|
@@ -681,7 +1337,14 @@ class SelectionRange {
|
|
|
681
1337
|
updated document.
|
|
682
1338
|
*/
|
|
683
1339
|
map(change, assoc = -1) {
|
|
684
|
-
let from
|
|
1340
|
+
let from, to;
|
|
1341
|
+
if (this.empty) {
|
|
1342
|
+
from = to = change.mapPos(this.from, assoc);
|
|
1343
|
+
}
|
|
1344
|
+
else {
|
|
1345
|
+
from = change.mapPos(this.from, 1);
|
|
1346
|
+
to = change.mapPos(this.to, -1);
|
|
1347
|
+
}
|
|
685
1348
|
return from == this.from && to == this.to ? this : new SelectionRange(from, to, this.flags);
|
|
686
1349
|
}
|
|
687
1350
|
/**
|
|
@@ -712,14 +1375,17 @@ class SelectionRange {
|
|
|
712
1375
|
throw new RangeError("Invalid JSON representation for SelectionRange");
|
|
713
1376
|
return EditorSelection.range(json.anchor, json.head);
|
|
714
1377
|
}
|
|
1378
|
+
/**
|
|
1379
|
+
@internal
|
|
1380
|
+
*/
|
|
1381
|
+
static create(from, to, flags) {
|
|
1382
|
+
return new SelectionRange(from, to, flags);
|
|
1383
|
+
}
|
|
715
1384
|
}
|
|
716
1385
|
/**
|
|
717
1386
|
An editor selection holds one or more selection ranges.
|
|
718
1387
|
*/
|
|
719
1388
|
class EditorSelection {
|
|
720
|
-
/**
|
|
721
|
-
@internal
|
|
722
|
-
*/
|
|
723
1389
|
constructor(
|
|
724
1390
|
/**
|
|
725
1391
|
The ranges in the selection, sorted by position. Ranges cannot
|
|
@@ -730,7 +1396,7 @@ class EditorSelection {
|
|
|
730
1396
|
The index of the _main_ range in the selection (which is
|
|
731
1397
|
usually the range that was added last).
|
|
732
1398
|
*/
|
|
733
|
-
mainIndex
|
|
1399
|
+
mainIndex) {
|
|
734
1400
|
this.ranges = ranges;
|
|
735
1401
|
this.mainIndex = mainIndex;
|
|
736
1402
|
}
|
|
@@ -766,7 +1432,7 @@ class EditorSelection {
|
|
|
766
1432
|
holding only the main range from this selection.
|
|
767
1433
|
*/
|
|
768
1434
|
asSingle() {
|
|
769
|
-
return this.ranges.length == 1 ? this : new EditorSelection([this.main]);
|
|
1435
|
+
return this.ranges.length == 1 ? this : new EditorSelection([this.main], 0);
|
|
770
1436
|
}
|
|
771
1437
|
/**
|
|
772
1438
|
Extend this selection with an extra range.
|
|
@@ -814,7 +1480,7 @@ class EditorSelection {
|
|
|
814
1480
|
for (let pos = 0, i = 0; i < ranges.length; i++) {
|
|
815
1481
|
let range = ranges[i];
|
|
816
1482
|
if (range.empty ? range.from <= pos : range.from < pos)
|
|
817
|
-
return normalized(ranges.slice(), mainIndex);
|
|
1483
|
+
return EditorSelection.normalized(ranges.slice(), mainIndex);
|
|
818
1484
|
pos = range.to;
|
|
819
1485
|
}
|
|
820
1486
|
return new EditorSelection(ranges, mainIndex);
|
|
@@ -824,7 +1490,7 @@ class EditorSelection {
|
|
|
824
1490
|
safely ignore the optional arguments in most situations.
|
|
825
1491
|
*/
|
|
826
1492
|
static cursor(pos, assoc = 0, bidiLevel, goalColumn) {
|
|
827
|
-
return
|
|
1493
|
+
return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* AssocBefore */ : 8 /* AssocAfter */) |
|
|
828
1494
|
(bidiLevel == null ? 3 : Math.min(2, bidiLevel)) |
|
|
829
1495
|
((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */));
|
|
830
1496
|
}
|
|
@@ -833,24 +1499,27 @@ class EditorSelection {
|
|
|
833
1499
|
*/
|
|
834
1500
|
static range(anchor, head, goalColumn) {
|
|
835
1501
|
let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */;
|
|
836
|
-
return head < anchor ?
|
|
837
|
-
:
|
|
1502
|
+
return head < anchor ? SelectionRange.create(head, anchor, 16 /* Inverted */ | goal | 8 /* AssocAfter */)
|
|
1503
|
+
: SelectionRange.create(anchor, head, goal | (head > anchor ? 4 /* AssocBefore */ : 0));
|
|
838
1504
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
ranges
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
let
|
|
848
|
-
if (
|
|
849
|
-
|
|
850
|
-
|
|
1505
|
+
/**
|
|
1506
|
+
@internal
|
|
1507
|
+
*/
|
|
1508
|
+
static normalized(ranges, mainIndex = 0) {
|
|
1509
|
+
let main = ranges[mainIndex];
|
|
1510
|
+
ranges.sort((a, b) => a.from - b.from);
|
|
1511
|
+
mainIndex = ranges.indexOf(main);
|
|
1512
|
+
for (let i = 1; i < ranges.length; i++) {
|
|
1513
|
+
let range = ranges[i], prev = ranges[i - 1];
|
|
1514
|
+
if (range.empty ? range.from <= prev.to : range.from < prev.to) {
|
|
1515
|
+
let from = prev.from, to = Math.max(range.to, prev.to);
|
|
1516
|
+
if (i <= mainIndex)
|
|
1517
|
+
mainIndex--;
|
|
1518
|
+
ranges.splice(--i, 2, range.anchor > range.head ? EditorSelection.range(to, from) : EditorSelection.range(from, to));
|
|
1519
|
+
}
|
|
851
1520
|
}
|
|
1521
|
+
return new EditorSelection(ranges, mainIndex);
|
|
852
1522
|
}
|
|
853
|
-
return new EditorSelection(ranges, mainIndex);
|
|
854
1523
|
}
|
|
855
1524
|
function checkSelection(selection, docLength) {
|
|
856
1525
|
for (let range of selection.ranges)
|
|
@@ -864,10 +1533,10 @@ A facet is a labeled value that is associated with an editor
|
|
|
864
1533
|
state. It takes inputs from any number of extensions, and combines
|
|
865
1534
|
those into a single output value.
|
|
866
1535
|
|
|
867
|
-
Examples of facets are the [
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1536
|
+
Examples of uses of facets are the [tab
|
|
1537
|
+
size](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize), [editor
|
|
1538
|
+
attributes](https://codemirror.net/6/docs/ref/#view.EditorView^editorAttributes), and [update
|
|
1539
|
+
listeners](https://codemirror.net/6/docs/ref/#view.EditorView^updateListener).
|
|
871
1540
|
*/
|
|
872
1541
|
class Facet {
|
|
873
1542
|
constructor(
|
|
@@ -905,7 +1574,7 @@ class Facet {
|
|
|
905
1574
|
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);
|
|
906
1575
|
}
|
|
907
1576
|
/**
|
|
908
|
-
Returns an extension that adds the given value
|
|
1577
|
+
Returns an extension that adds the given value to this facet.
|
|
909
1578
|
*/
|
|
910
1579
|
of(value) {
|
|
911
1580
|
return new FacetProvider([], this, 0 /* Static */, value);
|
|
@@ -916,9 +1585,8 @@ class Facet {
|
|
|
916
1585
|
this value depends on, since your function is only called again
|
|
917
1586
|
for a new state when one of those parts changed.
|
|
918
1587
|
|
|
919
|
-
In
|
|
920
|
-
[`
|
|
921
|
-
defining a field instead.
|
|
1588
|
+
In cases where your value depends only on a single field, you'll
|
|
1589
|
+
want to use the [`from`](https://codemirror.net/6/docs/ref/#state.Facet.from) method instead.
|
|
922
1590
|
*/
|
|
923
1591
|
compute(deps, get) {
|
|
924
1592
|
if (this.isStatic)
|
|
@@ -971,8 +1639,7 @@ class FacetProvider {
|
|
|
971
1639
|
return 1 /* Changed */;
|
|
972
1640
|
},
|
|
973
1641
|
update(state, tr) {
|
|
974
|
-
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) ||
|
|
975
|
-
depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0)) {
|
|
1642
|
+
if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) {
|
|
976
1643
|
let newVal = getter(state);
|
|
977
1644
|
if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) {
|
|
978
1645
|
state.values[idx] = newVal;
|
|
@@ -981,12 +1648,15 @@ class FacetProvider {
|
|
|
981
1648
|
}
|
|
982
1649
|
return 0;
|
|
983
1650
|
},
|
|
984
|
-
reconfigure(state, oldState) {
|
|
1651
|
+
reconfigure: (state, oldState) => {
|
|
985
1652
|
let newVal = getter(state);
|
|
986
1653
|
let oldAddr = oldState.config.address[id];
|
|
987
1654
|
if (oldAddr != null) {
|
|
988
1655
|
let oldVal = getAddr(oldState, oldAddr);
|
|
989
|
-
if (
|
|
1656
|
+
if (this.dependencies.every(dep => {
|
|
1657
|
+
return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) :
|
|
1658
|
+
dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true;
|
|
1659
|
+
}) || (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))) {
|
|
990
1660
|
state.values[idx] = oldVal;
|
|
991
1661
|
return 0;
|
|
992
1662
|
}
|
|
@@ -1005,6 +1675,13 @@ function compareArray(a, b, compare) {
|
|
|
1005
1675
|
return false;
|
|
1006
1676
|
return true;
|
|
1007
1677
|
}
|
|
1678
|
+
function ensureAll(state, addrs) {
|
|
1679
|
+
let changed = false;
|
|
1680
|
+
for (let addr of addrs)
|
|
1681
|
+
if (ensureAddr(state, addr) & 1 /* Changed */)
|
|
1682
|
+
changed = true;
|
|
1683
|
+
return changed;
|
|
1684
|
+
}
|
|
1008
1685
|
function dynamicFacetSlot(addresses, facet, providers) {
|
|
1009
1686
|
let providerAddrs = providers.map(p => addresses[p.id]);
|
|
1010
1687
|
let providerTypes = providers.map(p => p.type);
|
|
@@ -1030,7 +1707,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|
|
1030
1707
|
return 1 /* Changed */;
|
|
1031
1708
|
},
|
|
1032
1709
|
update(state, tr) {
|
|
1033
|
-
if (!
|
|
1710
|
+
if (!ensureAll(state, dynamic))
|
|
1034
1711
|
return 0;
|
|
1035
1712
|
let value = get(state);
|
|
1036
1713
|
if (facet.compare(value, state.values[idx]))
|
|
@@ -1039,7 +1716,7 @@ function dynamicFacetSlot(addresses, facet, providers) {
|
|
|
1039
1716
|
return 1 /* Changed */;
|
|
1040
1717
|
},
|
|
1041
1718
|
reconfigure(state, oldState) {
|
|
1042
|
-
let depChanged =
|
|
1719
|
+
let depChanged = ensureAll(state, providerAddrs);
|
|
1043
1720
|
let oldProviders = oldState.config.facets[facet.id], oldValue = oldState.facet(facet);
|
|
1044
1721
|
if (oldProviders && !depChanged && sameArray(providers, oldProviders)) {
|
|
1045
1722
|
state.values[idx] = oldValue;
|
|
@@ -1152,42 +1829,29 @@ precedence and then by order within each precedence.
|
|
|
1152
1829
|
*/
|
|
1153
1830
|
const Prec = {
|
|
1154
1831
|
/**
|
|
1155
|
-
The
|
|
1156
|
-
near the
|
|
1157
|
-
*/
|
|
1158
|
-
lowest: /*@__PURE__*/prec(Prec_.lowest),
|
|
1159
|
-
/**
|
|
1160
|
-
A lower-than-default precedence, for extensions.
|
|
1161
|
-
*/
|
|
1162
|
-
low: /*@__PURE__*/prec(Prec_.low),
|
|
1163
|
-
/**
|
|
1164
|
-
The default precedence, which is also used for extensions
|
|
1165
|
-
without an explicit precedence.
|
|
1832
|
+
The highest precedence level, for extensions that should end up
|
|
1833
|
+
near the start of the precedence ordering.
|
|
1166
1834
|
*/
|
|
1167
|
-
|
|
1835
|
+
highest: /*@__PURE__*/prec(Prec_.highest),
|
|
1168
1836
|
/**
|
|
1169
1837
|
A higher-than-default precedence, for extensions that should
|
|
1170
1838
|
come before those with default precedence.
|
|
1171
1839
|
*/
|
|
1172
1840
|
high: /*@__PURE__*/prec(Prec_.high),
|
|
1173
1841
|
/**
|
|
1174
|
-
The
|
|
1175
|
-
|
|
1176
|
-
*/
|
|
1177
|
-
highest: /*@__PURE__*/prec(Prec_.highest),
|
|
1178
|
-
// FIXME Drop these in some future breaking version
|
|
1179
|
-
/**
|
|
1180
|
-
Backwards-compatible synonym for `Prec.lowest`.
|
|
1842
|
+
The default precedence, which is also used for extensions
|
|
1843
|
+
without an explicit precedence.
|
|
1181
1844
|
*/
|
|
1182
|
-
|
|
1845
|
+
default: /*@__PURE__*/prec(Prec_.default),
|
|
1183
1846
|
/**
|
|
1184
|
-
|
|
1847
|
+
A lower-than-default precedence.
|
|
1185
1848
|
*/
|
|
1186
|
-
|
|
1849
|
+
low: /*@__PURE__*/prec(Prec_.low),
|
|
1187
1850
|
/**
|
|
1188
|
-
|
|
1851
|
+
The lowest precedence level. Meant for things that should end up
|
|
1852
|
+
near the end of the extension order.
|
|
1189
1853
|
*/
|
|
1190
|
-
|
|
1854
|
+
lowest: /*@__PURE__*/prec(Prec_.lowest)
|
|
1191
1855
|
};
|
|
1192
1856
|
class PrecExtension {
|
|
1193
1857
|
constructor(inner, prec) {
|
|
@@ -1301,7 +1965,7 @@ function flatten(extension, compartments, newCompartments) {
|
|
|
1301
1965
|
function inner(ext, prec) {
|
|
1302
1966
|
let known = seen.get(ext);
|
|
1303
1967
|
if (known != null) {
|
|
1304
|
-
if (known
|
|
1968
|
+
if (known <= prec)
|
|
1305
1969
|
return;
|
|
1306
1970
|
let found = result[known].indexOf(ext);
|
|
1307
1971
|
if (found > -1)
|
|
@@ -1516,12 +2180,11 @@ Changes to the editor state are grouped into transactions.
|
|
|
1516
2180
|
Typically, a user action creates a single transaction, which may
|
|
1517
2181
|
contain any number of document changes, may change the selection,
|
|
1518
2182
|
or have other effects. Create a transaction by calling
|
|
1519
|
-
[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update)
|
|
2183
|
+
[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update), or immediately
|
|
2184
|
+
dispatch one by calling
|
|
2185
|
+
[`EditorView.dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch).
|
|
1520
2186
|
*/
|
|
1521
2187
|
class Transaction {
|
|
1522
|
-
/**
|
|
1523
|
-
@internal
|
|
1524
|
-
*/
|
|
1525
2188
|
constructor(
|
|
1526
2189
|
/**
|
|
1527
2190
|
The state from which the transaction starts.
|
|
@@ -1569,6 +2232,12 @@ class Transaction {
|
|
|
1569
2232
|
this.annotations = annotations.concat(Transaction.time.of(Date.now()));
|
|
1570
2233
|
}
|
|
1571
2234
|
/**
|
|
2235
|
+
@internal
|
|
2236
|
+
*/
|
|
2237
|
+
static create(startState, changes, selection, effects, annotations, scrollIntoView) {
|
|
2238
|
+
return new Transaction(startState, changes, selection, effects, annotations, scrollIntoView);
|
|
2239
|
+
}
|
|
2240
|
+
/**
|
|
1572
2241
|
The new document produced by the transaction. Contrary to
|
|
1573
2242
|
[`.state`](https://codemirror.net/6/docs/ref/#state.Transaction.state)`.doc`, accessing this won't
|
|
1574
2243
|
force the entire new state to be computed right away, so it is
|
|
@@ -1590,7 +2259,7 @@ class Transaction {
|
|
|
1590
2259
|
}
|
|
1591
2260
|
/**
|
|
1592
2261
|
The new state created by the transaction. Computed on demand
|
|
1593
|
-
(but retained for subsequent access), so
|
|
2262
|
+
(but retained for subsequent access), so it is recommended not to
|
|
1594
2263
|
access it in [transaction
|
|
1595
2264
|
filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) when possible.
|
|
1596
2265
|
*/
|
|
@@ -1632,7 +2301,8 @@ class Transaction {
|
|
|
1632
2301
|
}
|
|
1633
2302
|
}
|
|
1634
2303
|
/**
|
|
1635
|
-
Annotation used to store transaction timestamps.
|
|
2304
|
+
Annotation used to store transaction timestamps. Automatically
|
|
2305
|
+
added to every transaction, holding `Date.now()`.
|
|
1636
2306
|
*/
|
|
1637
2307
|
Transaction.time = /*@__PURE__*/Annotation.define();
|
|
1638
2308
|
/**
|
|
@@ -1738,7 +2408,7 @@ function resolveTransaction(state, specs, filter) {
|
|
|
1738
2408
|
let seq = !!specs[i].sequential;
|
|
1739
2409
|
s = mergeTransaction(s, resolveTransactionInner(state, specs[i], seq ? s.changes.newLength : state.doc.length), seq);
|
|
1740
2410
|
}
|
|
1741
|
-
let tr =
|
|
2411
|
+
let tr = Transaction.create(state, s.changes, s.selection, s.effects, s.annotations, s.scrollIntoView);
|
|
1742
2412
|
return extendTransaction(filter ? filterTransaction(tr) : tr);
|
|
1743
2413
|
}
|
|
1744
2414
|
// Finish a transaction by applying filters if necessary.
|
|
@@ -1766,7 +2436,7 @@ function filterTransaction(tr) {
|
|
|
1766
2436
|
changes = filtered.changes;
|
|
1767
2437
|
back = filtered.filtered.invertedDesc;
|
|
1768
2438
|
}
|
|
1769
|
-
tr =
|
|
2439
|
+
tr = Transaction.create(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.scrollIntoView);
|
|
1770
2440
|
}
|
|
1771
2441
|
// Transaction filters
|
|
1772
2442
|
let filters = state.facet(transactionFilter);
|
|
@@ -1788,7 +2458,7 @@ function extendTransaction(tr) {
|
|
|
1788
2458
|
if (extension && Object.keys(extension).length)
|
|
1789
2459
|
spec = mergeTransaction(tr, resolveTransactionInner(state, extension, tr.changes.newLength), true);
|
|
1790
2460
|
}
|
|
1791
|
-
return spec == tr ? tr :
|
|
2461
|
+
return spec == tr ? tr : Transaction.create(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView);
|
|
1792
2462
|
}
|
|
1793
2463
|
const none = [];
|
|
1794
2464
|
function asArray(value) {
|
|
@@ -1853,9 +2523,6 @@ As such, _never_ mutate properties of a state directly. That'll
|
|
|
1853
2523
|
just break things.
|
|
1854
2524
|
*/
|
|
1855
2525
|
class EditorState {
|
|
1856
|
-
/**
|
|
1857
|
-
@internal
|
|
1858
|
-
*/
|
|
1859
2526
|
constructor(
|
|
1860
2527
|
/**
|
|
1861
2528
|
@internal
|
|
@@ -2004,7 +2671,7 @@ class EditorState {
|
|
|
2004
2671
|
/**
|
|
2005
2672
|
Using the state's [line
|
|
2006
2673
|
separator](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator), create a
|
|
2007
|
-
[`Text`](https://codemirror.net/6/docs/ref/#
|
|
2674
|
+
[`Text`](https://codemirror.net/6/docs/ref/#state.Text) instance from the given string.
|
|
2008
2675
|
*/
|
|
2009
2676
|
toText(string) {
|
|
2010
2677
|
return Text.of(string.split(this.facet(EditorState.lineSeparator) || DefaultSplit));
|
|
@@ -2101,11 +2768,25 @@ class EditorState {
|
|
|
2101
2768
|
Look up a translation for the given phrase (via the
|
|
2102
2769
|
[`phrases`](https://codemirror.net/6/docs/ref/#state.EditorState^phrases) facet), or return the
|
|
2103
2770
|
original string if no translation is found.
|
|
2771
|
+
|
|
2772
|
+
If additional arguments are passed, they will be inserted in
|
|
2773
|
+
place of markers like `$1` (for the first value) and `$2`, etc.
|
|
2774
|
+
A single `$` is equivalent to `$1`, and `$$` will produce a
|
|
2775
|
+
literal dollar sign.
|
|
2104
2776
|
*/
|
|
2105
|
-
phrase(phrase) {
|
|
2777
|
+
phrase(phrase, ...insert) {
|
|
2106
2778
|
for (let map of this.facet(EditorState.phrases))
|
|
2107
|
-
if (Object.prototype.hasOwnProperty.call(map, phrase))
|
|
2108
|
-
|
|
2779
|
+
if (Object.prototype.hasOwnProperty.call(map, phrase)) {
|
|
2780
|
+
phrase = map[phrase];
|
|
2781
|
+
break;
|
|
2782
|
+
}
|
|
2783
|
+
if (insert.length)
|
|
2784
|
+
phrase = phrase.replace(/\$(\$|\d*)/g, (m, i) => {
|
|
2785
|
+
if (i == "$")
|
|
2786
|
+
return "$";
|
|
2787
|
+
let n = +(i || 1);
|
|
2788
|
+
return n > insert.length ? m : insert[n - 1];
|
|
2789
|
+
});
|
|
2109
2790
|
return phrase;
|
|
2110
2791
|
}
|
|
2111
2792
|
/**
|
|
@@ -2124,7 +2805,7 @@ class EditorState {
|
|
|
2124
2805
|
}
|
|
2125
2806
|
/**
|
|
2126
2807
|
Return a function that can categorize strings (expected to
|
|
2127
|
-
represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#
|
|
2808
|
+
represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#state.findClusterBreak))
|
|
2128
2809
|
into one of:
|
|
2129
2810
|
|
|
2130
2811
|
- Word (contains an alphanumeric character or a character
|
|
@@ -2208,8 +2889,13 @@ Registers translation phrases. The
|
|
|
2208
2889
|
all objects registered with this facet to find translations for
|
|
2209
2890
|
its argument.
|
|
2210
2891
|
*/
|
|
2211
|
-
EditorState.phrases = /*@__PURE__*/Facet.define(
|
|
2212
|
-
|
|
2892
|
+
EditorState.phrases = /*@__PURE__*/Facet.define({
|
|
2893
|
+
compare(a, b) {
|
|
2894
|
+
let kA = Object.keys(a), kB = Object.keys(b);
|
|
2895
|
+
return kA.length == kB.length && kA.every(k => a[k] == b[k]);
|
|
2896
|
+
}
|
|
2897
|
+
});
|
|
2898
|
+
/**
|
|
2213
2899
|
A facet used to register [language
|
|
2214
2900
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) providers.
|
|
2215
2901
|
*/
|
|
@@ -2224,7 +2910,7 @@ Such a function can return `true` to indicate that it doesn't
|
|
|
2224
2910
|
want to do anything, `false` to completely stop the changes in
|
|
2225
2911
|
the transaction, or a set of ranges in which changes should be
|
|
2226
2912
|
suppressed. Such ranges are represented as an array of numbers,
|
|
2227
|
-
with each pair of two
|
|
2913
|
+
with each pair of two numbers indicating the start and end of a
|
|
2228
2914
|
range. So for example `[10, 20, 100, 110]` suppresses changes
|
|
2229
2915
|
between 10 and 20, and between 100 and 110.
|
|
2230
2916
|
*/
|
|
@@ -2255,19 +2941,22 @@ This is a more limited form of
|
|
|
2255
2941
|
which can only add
|
|
2256
2942
|
[annotations](https://codemirror.net/6/docs/ref/#state.TransactionSpec.annotations) and
|
|
2257
2943
|
[effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects). _But_, this type
|
|
2258
|
-
of filter runs even the transaction has disabled regular
|
|
2944
|
+
of filter runs even if the transaction has disabled regular
|
|
2259
2945
|
[filtering](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter), making it suitable
|
|
2260
2946
|
for effects that don't need to touch the changes or selection,
|
|
2261
2947
|
but do want to process every transaction.
|
|
2262
2948
|
|
|
2263
|
-
Extenders run _after_ filters, when both are
|
|
2949
|
+
Extenders run _after_ filters, when both are present.
|
|
2264
2950
|
*/
|
|
2265
2951
|
EditorState.transactionExtender = transactionExtender;
|
|
2266
2952
|
Compartment.reconfigure = /*@__PURE__*/StateEffect.define();
|
|
2267
2953
|
|
|
2268
2954
|
/**
|
|
2269
2955
|
Utility function for combining behaviors to fill in a config
|
|
2270
|
-
object from an array of provided configs.
|
|
2956
|
+
object from an array of provided configs. `defaults` should hold
|
|
2957
|
+
default values for all optional fields in `Config`.
|
|
2958
|
+
|
|
2959
|
+
The function will, by default, error
|
|
2271
2960
|
when a field gets two values that aren't `===`-equal, but you can
|
|
2272
2961
|
provide combine functions per field to do something else.
|
|
2273
2962
|
*/
|
|
@@ -2291,4 +2980,877 @@ combine = {}) {
|
|
|
2291
2980
|
return result;
|
|
2292
2981
|
}
|
|
2293
2982
|
|
|
2294
|
-
|
|
2983
|
+
/**
|
|
2984
|
+
Each range is associated with a value, which must inherit from
|
|
2985
|
+
this class.
|
|
2986
|
+
*/
|
|
2987
|
+
class RangeValue {
|
|
2988
|
+
/**
|
|
2989
|
+
Compare this value with another value. Used when comparing
|
|
2990
|
+
rangesets. The default implementation compares by identity.
|
|
2991
|
+
Unless you are only creating a fixed number of unique instances
|
|
2992
|
+
of your value type, it is a good idea to implement this
|
|
2993
|
+
properly.
|
|
2994
|
+
*/
|
|
2995
|
+
eq(other) { return this == other; }
|
|
2996
|
+
/**
|
|
2997
|
+
Create a [range](https://codemirror.net/6/docs/ref/#state.Range) with this value.
|
|
2998
|
+
*/
|
|
2999
|
+
range(from, to = from) { return Range.create(from, to, this); }
|
|
3000
|
+
}
|
|
3001
|
+
RangeValue.prototype.startSide = RangeValue.prototype.endSide = 0;
|
|
3002
|
+
RangeValue.prototype.point = false;
|
|
3003
|
+
RangeValue.prototype.mapMode = MapMode.TrackDel;
|
|
3004
|
+
/**
|
|
3005
|
+
A range associates a value with a range of positions.
|
|
3006
|
+
*/
|
|
3007
|
+
class Range {
|
|
3008
|
+
constructor(
|
|
3009
|
+
/**
|
|
3010
|
+
The range's start position.
|
|
3011
|
+
*/
|
|
3012
|
+
from,
|
|
3013
|
+
/**
|
|
3014
|
+
Its end position.
|
|
3015
|
+
*/
|
|
3016
|
+
to,
|
|
3017
|
+
/**
|
|
3018
|
+
The value associated with this range.
|
|
3019
|
+
*/
|
|
3020
|
+
value) {
|
|
3021
|
+
this.from = from;
|
|
3022
|
+
this.to = to;
|
|
3023
|
+
this.value = value;
|
|
3024
|
+
}
|
|
3025
|
+
/**
|
|
3026
|
+
@internal
|
|
3027
|
+
*/
|
|
3028
|
+
static create(from, to, value) {
|
|
3029
|
+
return new Range(from, to, value);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
function cmpRange(a, b) {
|
|
3033
|
+
return a.from - b.from || a.value.startSide - b.value.startSide;
|
|
3034
|
+
}
|
|
3035
|
+
class Chunk {
|
|
3036
|
+
constructor(from, to, value,
|
|
3037
|
+
// Chunks are marked with the largest point that occurs
|
|
3038
|
+
// in them (or -1 for no points), so that scans that are
|
|
3039
|
+
// only interested in points (such as the
|
|
3040
|
+
// heightmap-related logic) can skip range-only chunks.
|
|
3041
|
+
maxPoint) {
|
|
3042
|
+
this.from = from;
|
|
3043
|
+
this.to = to;
|
|
3044
|
+
this.value = value;
|
|
3045
|
+
this.maxPoint = maxPoint;
|
|
3046
|
+
}
|
|
3047
|
+
get length() { return this.to[this.to.length - 1]; }
|
|
3048
|
+
// Find the index of the given position and side. Use the ranges'
|
|
3049
|
+
// `from` pos when `end == false`, `to` when `end == true`.
|
|
3050
|
+
findIndex(pos, side, end, startAt = 0) {
|
|
3051
|
+
let arr = end ? this.to : this.from;
|
|
3052
|
+
for (let lo = startAt, hi = arr.length;;) {
|
|
3053
|
+
if (lo == hi)
|
|
3054
|
+
return lo;
|
|
3055
|
+
let mid = (lo + hi) >> 1;
|
|
3056
|
+
let diff = arr[mid] - pos || (end ? this.value[mid].endSide : this.value[mid].startSide) - side;
|
|
3057
|
+
if (mid == lo)
|
|
3058
|
+
return diff >= 0 ? lo : hi;
|
|
3059
|
+
if (diff >= 0)
|
|
3060
|
+
hi = mid;
|
|
3061
|
+
else
|
|
3062
|
+
lo = mid + 1;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
between(offset, from, to, f) {
|
|
3066
|
+
for (let i = this.findIndex(from, -1000000000 /* Far */, true), e = this.findIndex(to, 1000000000 /* Far */, false, i); i < e; i++)
|
|
3067
|
+
if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false)
|
|
3068
|
+
return false;
|
|
3069
|
+
}
|
|
3070
|
+
map(offset, changes) {
|
|
3071
|
+
let value = [], from = [], to = [], newPos = -1, maxPoint = -1;
|
|
3072
|
+
for (let i = 0; i < this.value.length; i++) {
|
|
3073
|
+
let val = this.value[i], curFrom = this.from[i] + offset, curTo = this.to[i] + offset, newFrom, newTo;
|
|
3074
|
+
if (curFrom == curTo) {
|
|
3075
|
+
let mapped = changes.mapPos(curFrom, val.startSide, val.mapMode);
|
|
3076
|
+
if (mapped == null)
|
|
3077
|
+
continue;
|
|
3078
|
+
newFrom = newTo = mapped;
|
|
3079
|
+
if (val.startSide != val.endSide) {
|
|
3080
|
+
newTo = changes.mapPos(curFrom, val.endSide);
|
|
3081
|
+
if (newTo < newFrom)
|
|
3082
|
+
continue;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
else {
|
|
3086
|
+
newFrom = changes.mapPos(curFrom, val.startSide);
|
|
3087
|
+
newTo = changes.mapPos(curTo, val.endSide);
|
|
3088
|
+
if (newFrom > newTo || newFrom == newTo && val.startSide > 0 && val.endSide <= 0)
|
|
3089
|
+
continue;
|
|
3090
|
+
}
|
|
3091
|
+
if ((newTo - newFrom || val.endSide - val.startSide) < 0)
|
|
3092
|
+
continue;
|
|
3093
|
+
if (newPos < 0)
|
|
3094
|
+
newPos = newFrom;
|
|
3095
|
+
if (val.point)
|
|
3096
|
+
maxPoint = Math.max(maxPoint, newTo - newFrom);
|
|
3097
|
+
value.push(val);
|
|
3098
|
+
from.push(newFrom - newPos);
|
|
3099
|
+
to.push(newTo - newPos);
|
|
3100
|
+
}
|
|
3101
|
+
return { mapped: value.length ? new Chunk(from, to, value, maxPoint) : null, pos: newPos };
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
/**
|
|
3105
|
+
A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#state.Range) in a
|
|
3106
|
+
way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#state.RangeSet.map) and
|
|
3107
|
+
[update](https://codemirror.net/6/docs/ref/#state.RangeSet.update). This is an immutable data
|
|
3108
|
+
structure.
|
|
3109
|
+
*/
|
|
3110
|
+
class RangeSet {
|
|
3111
|
+
constructor(
|
|
3112
|
+
/**
|
|
3113
|
+
@internal
|
|
3114
|
+
*/
|
|
3115
|
+
chunkPos,
|
|
3116
|
+
/**
|
|
3117
|
+
@internal
|
|
3118
|
+
*/
|
|
3119
|
+
chunk,
|
|
3120
|
+
/**
|
|
3121
|
+
@internal
|
|
3122
|
+
*/
|
|
3123
|
+
nextLayer,
|
|
3124
|
+
/**
|
|
3125
|
+
@internal
|
|
3126
|
+
*/
|
|
3127
|
+
maxPoint) {
|
|
3128
|
+
this.chunkPos = chunkPos;
|
|
3129
|
+
this.chunk = chunk;
|
|
3130
|
+
this.nextLayer = nextLayer;
|
|
3131
|
+
this.maxPoint = maxPoint;
|
|
3132
|
+
}
|
|
3133
|
+
/**
|
|
3134
|
+
@internal
|
|
3135
|
+
*/
|
|
3136
|
+
static create(chunkPos, chunk, nextLayer, maxPoint) {
|
|
3137
|
+
return new RangeSet(chunkPos, chunk, nextLayer, maxPoint);
|
|
3138
|
+
}
|
|
3139
|
+
/**
|
|
3140
|
+
@internal
|
|
3141
|
+
*/
|
|
3142
|
+
get length() {
|
|
3143
|
+
let last = this.chunk.length - 1;
|
|
3144
|
+
return last < 0 ? 0 : Math.max(this.chunkEnd(last), this.nextLayer.length);
|
|
3145
|
+
}
|
|
3146
|
+
/**
|
|
3147
|
+
The number of ranges in the set.
|
|
3148
|
+
*/
|
|
3149
|
+
get size() {
|
|
3150
|
+
if (this.isEmpty)
|
|
3151
|
+
return 0;
|
|
3152
|
+
let size = this.nextLayer.size;
|
|
3153
|
+
for (let chunk of this.chunk)
|
|
3154
|
+
size += chunk.value.length;
|
|
3155
|
+
return size;
|
|
3156
|
+
}
|
|
3157
|
+
/**
|
|
3158
|
+
@internal
|
|
3159
|
+
*/
|
|
3160
|
+
chunkEnd(index) {
|
|
3161
|
+
return this.chunkPos[index] + this.chunk[index].length;
|
|
3162
|
+
}
|
|
3163
|
+
/**
|
|
3164
|
+
Update the range set, optionally adding new ranges or filtering
|
|
3165
|
+
out existing ones.
|
|
3166
|
+
|
|
3167
|
+
(Note: The type parameter is just there as a kludge to work
|
|
3168
|
+
around TypeScript variance issues that prevented `RangeSet<X>`
|
|
3169
|
+
from being a subtype of `RangeSet<Y>` when `X` is a subtype of
|
|
3170
|
+
`Y`.)
|
|
3171
|
+
*/
|
|
3172
|
+
update(updateSpec) {
|
|
3173
|
+
let { add = [], sort = false, filterFrom = 0, filterTo = this.length } = updateSpec;
|
|
3174
|
+
let filter = updateSpec.filter;
|
|
3175
|
+
if (add.length == 0 && !filter)
|
|
3176
|
+
return this;
|
|
3177
|
+
if (sort)
|
|
3178
|
+
add = add.slice().sort(cmpRange);
|
|
3179
|
+
if (this.isEmpty)
|
|
3180
|
+
return add.length ? RangeSet.of(add) : this;
|
|
3181
|
+
let cur = new LayerCursor(this, null, -1).goto(0), i = 0, spill = [];
|
|
3182
|
+
let builder = new RangeSetBuilder();
|
|
3183
|
+
while (cur.value || i < add.length) {
|
|
3184
|
+
if (i < add.length && (cur.from - add[i].from || cur.startSide - add[i].value.startSide) >= 0) {
|
|
3185
|
+
let range = add[i++];
|
|
3186
|
+
if (!builder.addInner(range.from, range.to, range.value))
|
|
3187
|
+
spill.push(range);
|
|
3188
|
+
}
|
|
3189
|
+
else if (cur.rangeIndex == 1 && cur.chunkIndex < this.chunk.length &&
|
|
3190
|
+
(i == add.length || this.chunkEnd(cur.chunkIndex) < add[i].from) &&
|
|
3191
|
+
(!filter || filterFrom > this.chunkEnd(cur.chunkIndex) || filterTo < this.chunkPos[cur.chunkIndex]) &&
|
|
3192
|
+
builder.addChunk(this.chunkPos[cur.chunkIndex], this.chunk[cur.chunkIndex])) {
|
|
3193
|
+
cur.nextChunk();
|
|
3194
|
+
}
|
|
3195
|
+
else {
|
|
3196
|
+
if (!filter || filterFrom > cur.to || filterTo < cur.from || filter(cur.from, cur.to, cur.value)) {
|
|
3197
|
+
if (!builder.addInner(cur.from, cur.to, cur.value))
|
|
3198
|
+
spill.push(Range.create(cur.from, cur.to, cur.value));
|
|
3199
|
+
}
|
|
3200
|
+
cur.next();
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
return builder.finishInner(this.nextLayer.isEmpty && !spill.length ? RangeSet.empty
|
|
3204
|
+
: this.nextLayer.update({ add: spill, filter, filterFrom, filterTo }));
|
|
3205
|
+
}
|
|
3206
|
+
/**
|
|
3207
|
+
Map this range set through a set of changes, return the new set.
|
|
3208
|
+
*/
|
|
3209
|
+
map(changes) {
|
|
3210
|
+
if (changes.empty || this.isEmpty)
|
|
3211
|
+
return this;
|
|
3212
|
+
let chunks = [], chunkPos = [], maxPoint = -1;
|
|
3213
|
+
for (let i = 0; i < this.chunk.length; i++) {
|
|
3214
|
+
let start = this.chunkPos[i], chunk = this.chunk[i];
|
|
3215
|
+
let touch = changes.touchesRange(start, start + chunk.length);
|
|
3216
|
+
if (touch === false) {
|
|
3217
|
+
maxPoint = Math.max(maxPoint, chunk.maxPoint);
|
|
3218
|
+
chunks.push(chunk);
|
|
3219
|
+
chunkPos.push(changes.mapPos(start));
|
|
3220
|
+
}
|
|
3221
|
+
else if (touch === true) {
|
|
3222
|
+
let { mapped, pos } = chunk.map(start, changes);
|
|
3223
|
+
if (mapped) {
|
|
3224
|
+
maxPoint = Math.max(maxPoint, mapped.maxPoint);
|
|
3225
|
+
chunks.push(mapped);
|
|
3226
|
+
chunkPos.push(pos);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
let next = this.nextLayer.map(changes);
|
|
3231
|
+
return chunks.length == 0 ? next : new RangeSet(chunkPos, chunks, next || RangeSet.empty, maxPoint);
|
|
3232
|
+
}
|
|
3233
|
+
/**
|
|
3234
|
+
Iterate over the ranges that touch the region `from` to `to`,
|
|
3235
|
+
calling `f` for each. There is no guarantee that the ranges will
|
|
3236
|
+
be reported in any specific order. When the callback returns
|
|
3237
|
+
`false`, iteration stops.
|
|
3238
|
+
*/
|
|
3239
|
+
between(from, to, f) {
|
|
3240
|
+
if (this.isEmpty)
|
|
3241
|
+
return;
|
|
3242
|
+
for (let i = 0; i < this.chunk.length; i++) {
|
|
3243
|
+
let start = this.chunkPos[i], chunk = this.chunk[i];
|
|
3244
|
+
if (to >= start && from <= start + chunk.length &&
|
|
3245
|
+
chunk.between(start, from - start, to - start, f) === false)
|
|
3246
|
+
return;
|
|
3247
|
+
}
|
|
3248
|
+
this.nextLayer.between(from, to, f);
|
|
3249
|
+
}
|
|
3250
|
+
/**
|
|
3251
|
+
Iterate over the ranges in this set, in order, including all
|
|
3252
|
+
ranges that end at or after `from`.
|
|
3253
|
+
*/
|
|
3254
|
+
iter(from = 0) {
|
|
3255
|
+
return HeapCursor.from([this]).goto(from);
|
|
3256
|
+
}
|
|
3257
|
+
/**
|
|
3258
|
+
@internal
|
|
3259
|
+
*/
|
|
3260
|
+
get isEmpty() { return this.nextLayer == this; }
|
|
3261
|
+
/**
|
|
3262
|
+
Iterate over the ranges in a collection of sets, in order,
|
|
3263
|
+
starting from `from`.
|
|
3264
|
+
*/
|
|
3265
|
+
static iter(sets, from = 0) {
|
|
3266
|
+
return HeapCursor.from(sets).goto(from);
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
Iterate over two groups of sets, calling methods on `comparator`
|
|
3270
|
+
to notify it of possible differences.
|
|
3271
|
+
*/
|
|
3272
|
+
static compare(oldSets, newSets,
|
|
3273
|
+
/**
|
|
3274
|
+
This indicates how the underlying data changed between these
|
|
3275
|
+
ranges, and is needed to synchronize the iteration. `from` and
|
|
3276
|
+
`to` are coordinates in the _new_ space, after these changes.
|
|
3277
|
+
*/
|
|
3278
|
+
textDiff, comparator,
|
|
3279
|
+
/**
|
|
3280
|
+
Can be used to ignore all non-point ranges, and points below
|
|
3281
|
+
the given size. When -1, all ranges are compared.
|
|
3282
|
+
*/
|
|
3283
|
+
minPointSize = -1) {
|
|
3284
|
+
let a = oldSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize);
|
|
3285
|
+
let b = newSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize);
|
|
3286
|
+
let sharedChunks = findSharedChunks(a, b, textDiff);
|
|
3287
|
+
let sideA = new SpanCursor(a, sharedChunks, minPointSize);
|
|
3288
|
+
let sideB = new SpanCursor(b, sharedChunks, minPointSize);
|
|
3289
|
+
textDiff.iterGaps((fromA, fromB, length) => compare(sideA, fromA, sideB, fromB, length, comparator));
|
|
3290
|
+
if (textDiff.empty && textDiff.length == 0)
|
|
3291
|
+
compare(sideA, 0, sideB, 0, 0, comparator);
|
|
3292
|
+
}
|
|
3293
|
+
/**
|
|
3294
|
+
Compare the contents of two groups of range sets, returning true
|
|
3295
|
+
if they are equivalent in the given range.
|
|
3296
|
+
*/
|
|
3297
|
+
static eq(oldSets, newSets, from = 0, to) {
|
|
3298
|
+
if (to == null)
|
|
3299
|
+
to = 1000000000 /* Far */;
|
|
3300
|
+
let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0);
|
|
3301
|
+
let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0);
|
|
3302
|
+
if (a.length != b.length)
|
|
3303
|
+
return false;
|
|
3304
|
+
if (!a.length)
|
|
3305
|
+
return true;
|
|
3306
|
+
let sharedChunks = findSharedChunks(a, b);
|
|
3307
|
+
let sideA = new SpanCursor(a, sharedChunks, 0).goto(from), sideB = new SpanCursor(b, sharedChunks, 0).goto(from);
|
|
3308
|
+
for (;;) {
|
|
3309
|
+
if (sideA.to != sideB.to ||
|
|
3310
|
+
!sameValues(sideA.active, sideB.active) ||
|
|
3311
|
+
sideA.point && (!sideB.point || !sideA.point.eq(sideB.point)))
|
|
3312
|
+
return false;
|
|
3313
|
+
if (sideA.to > to)
|
|
3314
|
+
return true;
|
|
3315
|
+
sideA.next();
|
|
3316
|
+
sideB.next();
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
/**
|
|
3320
|
+
Iterate over a group of range sets at the same time, notifying
|
|
3321
|
+
the iterator about the ranges covering every given piece of
|
|
3322
|
+
content. Returns the open count (see
|
|
3323
|
+
[`SpanIterator.span`](https://codemirror.net/6/docs/ref/#state.SpanIterator.span)) at the end
|
|
3324
|
+
of the iteration.
|
|
3325
|
+
*/
|
|
3326
|
+
static spans(sets, from, to, iterator,
|
|
3327
|
+
/**
|
|
3328
|
+
When given and greater than -1, only points of at least this
|
|
3329
|
+
size are taken into account.
|
|
3330
|
+
*/
|
|
3331
|
+
minPointSize = -1) {
|
|
3332
|
+
let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from;
|
|
3333
|
+
let open = cursor.openStart;
|
|
3334
|
+
for (;;) {
|
|
3335
|
+
let curTo = Math.min(cursor.to, to);
|
|
3336
|
+
if (cursor.point) {
|
|
3337
|
+
iterator.point(pos, curTo, cursor.point, cursor.activeForPoint(cursor.to), open, cursor.pointRank);
|
|
3338
|
+
open = cursor.openEnd(curTo) + (cursor.to > curTo ? 1 : 0);
|
|
3339
|
+
}
|
|
3340
|
+
else if (curTo > pos) {
|
|
3341
|
+
iterator.span(pos, curTo, cursor.active, open);
|
|
3342
|
+
open = cursor.openEnd(curTo);
|
|
3343
|
+
}
|
|
3344
|
+
if (cursor.to > to)
|
|
3345
|
+
break;
|
|
3346
|
+
pos = cursor.to;
|
|
3347
|
+
cursor.next();
|
|
3348
|
+
}
|
|
3349
|
+
return open;
|
|
3350
|
+
}
|
|
3351
|
+
/**
|
|
3352
|
+
Create a range set for the given range or array of ranges. By
|
|
3353
|
+
default, this expects the ranges to be _sorted_ (by start
|
|
3354
|
+
position and, if two start at the same position,
|
|
3355
|
+
`value.startSide`). You can pass `true` as second argument to
|
|
3356
|
+
cause the method to sort them.
|
|
3357
|
+
*/
|
|
3358
|
+
static of(ranges, sort = false) {
|
|
3359
|
+
let build = new RangeSetBuilder();
|
|
3360
|
+
for (let range of ranges instanceof Range ? [ranges] : sort ? lazySort(ranges) : ranges)
|
|
3361
|
+
build.add(range.from, range.to, range.value);
|
|
3362
|
+
return build.finish();
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
/**
|
|
3366
|
+
The empty set of ranges.
|
|
3367
|
+
*/
|
|
3368
|
+
RangeSet.empty = /*@__PURE__*/new RangeSet([], [], null, -1);
|
|
3369
|
+
function lazySort(ranges) {
|
|
3370
|
+
if (ranges.length > 1)
|
|
3371
|
+
for (let prev = ranges[0], i = 1; i < ranges.length; i++) {
|
|
3372
|
+
let cur = ranges[i];
|
|
3373
|
+
if (cmpRange(prev, cur) > 0)
|
|
3374
|
+
return ranges.slice().sort(cmpRange);
|
|
3375
|
+
prev = cur;
|
|
3376
|
+
}
|
|
3377
|
+
return ranges;
|
|
3378
|
+
}
|
|
3379
|
+
RangeSet.empty.nextLayer = RangeSet.empty;
|
|
3380
|
+
/**
|
|
3381
|
+
A range set builder is a data structure that helps build up a
|
|
3382
|
+
[range set](https://codemirror.net/6/docs/ref/#state.RangeSet) directly, without first allocating
|
|
3383
|
+
an array of [`Range`](https://codemirror.net/6/docs/ref/#state.Range) objects.
|
|
3384
|
+
*/
|
|
3385
|
+
class RangeSetBuilder {
|
|
3386
|
+
/**
|
|
3387
|
+
Create an empty builder.
|
|
3388
|
+
*/
|
|
3389
|
+
constructor() {
|
|
3390
|
+
this.chunks = [];
|
|
3391
|
+
this.chunkPos = [];
|
|
3392
|
+
this.chunkStart = -1;
|
|
3393
|
+
this.last = null;
|
|
3394
|
+
this.lastFrom = -1000000000 /* Far */;
|
|
3395
|
+
this.lastTo = -1000000000 /* Far */;
|
|
3396
|
+
this.from = [];
|
|
3397
|
+
this.to = [];
|
|
3398
|
+
this.value = [];
|
|
3399
|
+
this.maxPoint = -1;
|
|
3400
|
+
this.setMaxPoint = -1;
|
|
3401
|
+
this.nextLayer = null;
|
|
3402
|
+
}
|
|
3403
|
+
finishChunk(newArrays) {
|
|
3404
|
+
this.chunks.push(new Chunk(this.from, this.to, this.value, this.maxPoint));
|
|
3405
|
+
this.chunkPos.push(this.chunkStart);
|
|
3406
|
+
this.chunkStart = -1;
|
|
3407
|
+
this.setMaxPoint = Math.max(this.setMaxPoint, this.maxPoint);
|
|
3408
|
+
this.maxPoint = -1;
|
|
3409
|
+
if (newArrays) {
|
|
3410
|
+
this.from = [];
|
|
3411
|
+
this.to = [];
|
|
3412
|
+
this.value = [];
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
/**
|
|
3416
|
+
Add a range. Ranges should be added in sorted (by `from` and
|
|
3417
|
+
`value.startSide`) order.
|
|
3418
|
+
*/
|
|
3419
|
+
add(from, to, value) {
|
|
3420
|
+
if (!this.addInner(from, to, value))
|
|
3421
|
+
(this.nextLayer || (this.nextLayer = new RangeSetBuilder)).add(from, to, value);
|
|
3422
|
+
}
|
|
3423
|
+
/**
|
|
3424
|
+
@internal
|
|
3425
|
+
*/
|
|
3426
|
+
addInner(from, to, value) {
|
|
3427
|
+
let diff = from - this.lastTo || value.startSide - this.last.endSide;
|
|
3428
|
+
if (diff <= 0 && (from - this.lastFrom || value.startSide - this.last.startSide) < 0)
|
|
3429
|
+
throw new Error("Ranges must be added sorted by `from` position and `startSide`");
|
|
3430
|
+
if (diff < 0)
|
|
3431
|
+
return false;
|
|
3432
|
+
if (this.from.length == 250 /* ChunkSize */)
|
|
3433
|
+
this.finishChunk(true);
|
|
3434
|
+
if (this.chunkStart < 0)
|
|
3435
|
+
this.chunkStart = from;
|
|
3436
|
+
this.from.push(from - this.chunkStart);
|
|
3437
|
+
this.to.push(to - this.chunkStart);
|
|
3438
|
+
this.last = value;
|
|
3439
|
+
this.lastFrom = from;
|
|
3440
|
+
this.lastTo = to;
|
|
3441
|
+
this.value.push(value);
|
|
3442
|
+
if (value.point)
|
|
3443
|
+
this.maxPoint = Math.max(this.maxPoint, to - from);
|
|
3444
|
+
return true;
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
@internal
|
|
3448
|
+
*/
|
|
3449
|
+
addChunk(from, chunk) {
|
|
3450
|
+
if ((from - this.lastTo || chunk.value[0].startSide - this.last.endSide) < 0)
|
|
3451
|
+
return false;
|
|
3452
|
+
if (this.from.length)
|
|
3453
|
+
this.finishChunk(true);
|
|
3454
|
+
this.setMaxPoint = Math.max(this.setMaxPoint, chunk.maxPoint);
|
|
3455
|
+
this.chunks.push(chunk);
|
|
3456
|
+
this.chunkPos.push(from);
|
|
3457
|
+
let last = chunk.value.length - 1;
|
|
3458
|
+
this.last = chunk.value[last];
|
|
3459
|
+
this.lastFrom = chunk.from[last] + from;
|
|
3460
|
+
this.lastTo = chunk.to[last] + from;
|
|
3461
|
+
return true;
|
|
3462
|
+
}
|
|
3463
|
+
/**
|
|
3464
|
+
Finish the range set. Returns the new set. The builder can't be
|
|
3465
|
+
used anymore after this has been called.
|
|
3466
|
+
*/
|
|
3467
|
+
finish() { return this.finishInner(RangeSet.empty); }
|
|
3468
|
+
/**
|
|
3469
|
+
@internal
|
|
3470
|
+
*/
|
|
3471
|
+
finishInner(next) {
|
|
3472
|
+
if (this.from.length)
|
|
3473
|
+
this.finishChunk(false);
|
|
3474
|
+
if (this.chunks.length == 0)
|
|
3475
|
+
return next;
|
|
3476
|
+
let result = RangeSet.create(this.chunkPos, this.chunks, this.nextLayer ? this.nextLayer.finishInner(next) : next, this.setMaxPoint);
|
|
3477
|
+
this.from = null; // Make sure further `add` calls produce errors
|
|
3478
|
+
return result;
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
function findSharedChunks(a, b, textDiff) {
|
|
3482
|
+
let inA = new Map();
|
|
3483
|
+
for (let set of a)
|
|
3484
|
+
for (let i = 0; i < set.chunk.length; i++)
|
|
3485
|
+
if (set.chunk[i].maxPoint <= 0)
|
|
3486
|
+
inA.set(set.chunk[i], set.chunkPos[i]);
|
|
3487
|
+
let shared = new Set();
|
|
3488
|
+
for (let set of b)
|
|
3489
|
+
for (let i = 0; i < set.chunk.length; i++) {
|
|
3490
|
+
let known = inA.get(set.chunk[i]);
|
|
3491
|
+
if (known != null && (textDiff ? textDiff.mapPos(known) : known) == set.chunkPos[i] &&
|
|
3492
|
+
!(textDiff === null || textDiff === void 0 ? void 0 : textDiff.touchesRange(known, known + set.chunk[i].length)))
|
|
3493
|
+
shared.add(set.chunk[i]);
|
|
3494
|
+
}
|
|
3495
|
+
return shared;
|
|
3496
|
+
}
|
|
3497
|
+
class LayerCursor {
|
|
3498
|
+
constructor(layer, skip, minPoint, rank = 0) {
|
|
3499
|
+
this.layer = layer;
|
|
3500
|
+
this.skip = skip;
|
|
3501
|
+
this.minPoint = minPoint;
|
|
3502
|
+
this.rank = rank;
|
|
3503
|
+
}
|
|
3504
|
+
get startSide() { return this.value ? this.value.startSide : 0; }
|
|
3505
|
+
get endSide() { return this.value ? this.value.endSide : 0; }
|
|
3506
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3507
|
+
this.chunkIndex = this.rangeIndex = 0;
|
|
3508
|
+
this.gotoInner(pos, side, false);
|
|
3509
|
+
return this;
|
|
3510
|
+
}
|
|
3511
|
+
gotoInner(pos, side, forward) {
|
|
3512
|
+
while (this.chunkIndex < this.layer.chunk.length) {
|
|
3513
|
+
let next = this.layer.chunk[this.chunkIndex];
|
|
3514
|
+
if (!(this.skip && this.skip.has(next) ||
|
|
3515
|
+
this.layer.chunkEnd(this.chunkIndex) < pos ||
|
|
3516
|
+
next.maxPoint < this.minPoint))
|
|
3517
|
+
break;
|
|
3518
|
+
this.chunkIndex++;
|
|
3519
|
+
forward = false;
|
|
3520
|
+
}
|
|
3521
|
+
if (this.chunkIndex < this.layer.chunk.length) {
|
|
3522
|
+
let rangeIndex = this.layer.chunk[this.chunkIndex].findIndex(pos - this.layer.chunkPos[this.chunkIndex], side, true);
|
|
3523
|
+
if (!forward || this.rangeIndex < rangeIndex)
|
|
3524
|
+
this.setRangeIndex(rangeIndex);
|
|
3525
|
+
}
|
|
3526
|
+
this.next();
|
|
3527
|
+
}
|
|
3528
|
+
forward(pos, side) {
|
|
3529
|
+
if ((this.to - pos || this.endSide - side) < 0)
|
|
3530
|
+
this.gotoInner(pos, side, true);
|
|
3531
|
+
}
|
|
3532
|
+
next() {
|
|
3533
|
+
for (;;) {
|
|
3534
|
+
if (this.chunkIndex == this.layer.chunk.length) {
|
|
3535
|
+
this.from = this.to = 1000000000 /* Far */;
|
|
3536
|
+
this.value = null;
|
|
3537
|
+
break;
|
|
3538
|
+
}
|
|
3539
|
+
else {
|
|
3540
|
+
let chunkPos = this.layer.chunkPos[this.chunkIndex], chunk = this.layer.chunk[this.chunkIndex];
|
|
3541
|
+
let from = chunkPos + chunk.from[this.rangeIndex];
|
|
3542
|
+
this.from = from;
|
|
3543
|
+
this.to = chunkPos + chunk.to[this.rangeIndex];
|
|
3544
|
+
this.value = chunk.value[this.rangeIndex];
|
|
3545
|
+
this.setRangeIndex(this.rangeIndex + 1);
|
|
3546
|
+
if (this.minPoint < 0 || this.value.point && this.to - this.from >= this.minPoint)
|
|
3547
|
+
break;
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
setRangeIndex(index) {
|
|
3552
|
+
if (index == this.layer.chunk[this.chunkIndex].value.length) {
|
|
3553
|
+
this.chunkIndex++;
|
|
3554
|
+
if (this.skip) {
|
|
3555
|
+
while (this.chunkIndex < this.layer.chunk.length && this.skip.has(this.layer.chunk[this.chunkIndex]))
|
|
3556
|
+
this.chunkIndex++;
|
|
3557
|
+
}
|
|
3558
|
+
this.rangeIndex = 0;
|
|
3559
|
+
}
|
|
3560
|
+
else {
|
|
3561
|
+
this.rangeIndex = index;
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
nextChunk() {
|
|
3565
|
+
this.chunkIndex++;
|
|
3566
|
+
this.rangeIndex = 0;
|
|
3567
|
+
this.next();
|
|
3568
|
+
}
|
|
3569
|
+
compare(other) {
|
|
3570
|
+
return this.from - other.from || this.startSide - other.startSide || this.rank - other.rank ||
|
|
3571
|
+
this.to - other.to || this.endSide - other.endSide;
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
class HeapCursor {
|
|
3575
|
+
constructor(heap) {
|
|
3576
|
+
this.heap = heap;
|
|
3577
|
+
}
|
|
3578
|
+
static from(sets, skip = null, minPoint = -1) {
|
|
3579
|
+
let heap = [];
|
|
3580
|
+
for (let i = 0; i < sets.length; i++) {
|
|
3581
|
+
for (let cur = sets[i]; !cur.isEmpty; cur = cur.nextLayer) {
|
|
3582
|
+
if (cur.maxPoint >= minPoint)
|
|
3583
|
+
heap.push(new LayerCursor(cur, skip, minPoint, i));
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
return heap.length == 1 ? heap[0] : new HeapCursor(heap);
|
|
3587
|
+
}
|
|
3588
|
+
get startSide() { return this.value ? this.value.startSide : 0; }
|
|
3589
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3590
|
+
for (let cur of this.heap)
|
|
3591
|
+
cur.goto(pos, side);
|
|
3592
|
+
for (let i = this.heap.length >> 1; i >= 0; i--)
|
|
3593
|
+
heapBubble(this.heap, i);
|
|
3594
|
+
this.next();
|
|
3595
|
+
return this;
|
|
3596
|
+
}
|
|
3597
|
+
forward(pos, side) {
|
|
3598
|
+
for (let cur of this.heap)
|
|
3599
|
+
cur.forward(pos, side);
|
|
3600
|
+
for (let i = this.heap.length >> 1; i >= 0; i--)
|
|
3601
|
+
heapBubble(this.heap, i);
|
|
3602
|
+
if ((this.to - pos || this.value.endSide - side) < 0)
|
|
3603
|
+
this.next();
|
|
3604
|
+
}
|
|
3605
|
+
next() {
|
|
3606
|
+
if (this.heap.length == 0) {
|
|
3607
|
+
this.from = this.to = 1000000000 /* Far */;
|
|
3608
|
+
this.value = null;
|
|
3609
|
+
this.rank = -1;
|
|
3610
|
+
}
|
|
3611
|
+
else {
|
|
3612
|
+
let top = this.heap[0];
|
|
3613
|
+
this.from = top.from;
|
|
3614
|
+
this.to = top.to;
|
|
3615
|
+
this.value = top.value;
|
|
3616
|
+
this.rank = top.rank;
|
|
3617
|
+
if (top.value)
|
|
3618
|
+
top.next();
|
|
3619
|
+
heapBubble(this.heap, 0);
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
function heapBubble(heap, index) {
|
|
3624
|
+
for (let cur = heap[index];;) {
|
|
3625
|
+
let childIndex = (index << 1) + 1;
|
|
3626
|
+
if (childIndex >= heap.length)
|
|
3627
|
+
break;
|
|
3628
|
+
let child = heap[childIndex];
|
|
3629
|
+
if (childIndex + 1 < heap.length && child.compare(heap[childIndex + 1]) >= 0) {
|
|
3630
|
+
child = heap[childIndex + 1];
|
|
3631
|
+
childIndex++;
|
|
3632
|
+
}
|
|
3633
|
+
if (cur.compare(child) < 0)
|
|
3634
|
+
break;
|
|
3635
|
+
heap[childIndex] = cur;
|
|
3636
|
+
heap[index] = child;
|
|
3637
|
+
index = childIndex;
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
class SpanCursor {
|
|
3641
|
+
constructor(sets, skip, minPoint) {
|
|
3642
|
+
this.minPoint = minPoint;
|
|
3643
|
+
this.active = [];
|
|
3644
|
+
this.activeTo = [];
|
|
3645
|
+
this.activeRank = [];
|
|
3646
|
+
this.minActive = -1;
|
|
3647
|
+
// A currently active point range, if any
|
|
3648
|
+
this.point = null;
|
|
3649
|
+
this.pointFrom = 0;
|
|
3650
|
+
this.pointRank = 0;
|
|
3651
|
+
this.to = -1000000000 /* Far */;
|
|
3652
|
+
this.endSide = 0;
|
|
3653
|
+
this.openStart = -1;
|
|
3654
|
+
this.cursor = HeapCursor.from(sets, skip, minPoint);
|
|
3655
|
+
}
|
|
3656
|
+
goto(pos, side = -1000000000 /* Far */) {
|
|
3657
|
+
this.cursor.goto(pos, side);
|
|
3658
|
+
this.active.length = this.activeTo.length = this.activeRank.length = 0;
|
|
3659
|
+
this.minActive = -1;
|
|
3660
|
+
this.to = pos;
|
|
3661
|
+
this.endSide = side;
|
|
3662
|
+
this.openStart = -1;
|
|
3663
|
+
this.next();
|
|
3664
|
+
return this;
|
|
3665
|
+
}
|
|
3666
|
+
forward(pos, side) {
|
|
3667
|
+
while (this.minActive > -1 && (this.activeTo[this.minActive] - pos || this.active[this.minActive].endSide - side) < 0)
|
|
3668
|
+
this.removeActive(this.minActive);
|
|
3669
|
+
this.cursor.forward(pos, side);
|
|
3670
|
+
}
|
|
3671
|
+
removeActive(index) {
|
|
3672
|
+
remove(this.active, index);
|
|
3673
|
+
remove(this.activeTo, index);
|
|
3674
|
+
remove(this.activeRank, index);
|
|
3675
|
+
this.minActive = findMinIndex(this.active, this.activeTo);
|
|
3676
|
+
}
|
|
3677
|
+
addActive(trackOpen) {
|
|
3678
|
+
let i = 0, { value, to, rank } = this.cursor;
|
|
3679
|
+
while (i < this.activeRank.length && this.activeRank[i] <= rank)
|
|
3680
|
+
i++;
|
|
3681
|
+
insert(this.active, i, value);
|
|
3682
|
+
insert(this.activeTo, i, to);
|
|
3683
|
+
insert(this.activeRank, i, rank);
|
|
3684
|
+
if (trackOpen)
|
|
3685
|
+
insert(trackOpen, i, this.cursor.from);
|
|
3686
|
+
this.minActive = findMinIndex(this.active, this.activeTo);
|
|
3687
|
+
}
|
|
3688
|
+
// After calling this, if `this.point` != null, the next range is a
|
|
3689
|
+
// point. Otherwise, it's a regular range, covered by `this.active`.
|
|
3690
|
+
next() {
|
|
3691
|
+
let from = this.to, wasPoint = this.point;
|
|
3692
|
+
this.point = null;
|
|
3693
|
+
let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0;
|
|
3694
|
+
for (;;) {
|
|
3695
|
+
let a = this.minActive;
|
|
3696
|
+
if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) {
|
|
3697
|
+
if (this.activeTo[a] > from) {
|
|
3698
|
+
this.to = this.activeTo[a];
|
|
3699
|
+
this.endSide = this.active[a].endSide;
|
|
3700
|
+
break;
|
|
3701
|
+
}
|
|
3702
|
+
this.removeActive(a);
|
|
3703
|
+
if (trackOpen)
|
|
3704
|
+
remove(trackOpen, a);
|
|
3705
|
+
}
|
|
3706
|
+
else if (!this.cursor.value) {
|
|
3707
|
+
this.to = this.endSide = 1000000000 /* Far */;
|
|
3708
|
+
break;
|
|
3709
|
+
}
|
|
3710
|
+
else if (this.cursor.from > from) {
|
|
3711
|
+
this.to = this.cursor.from;
|
|
3712
|
+
this.endSide = this.cursor.startSide;
|
|
3713
|
+
break;
|
|
3714
|
+
}
|
|
3715
|
+
else {
|
|
3716
|
+
let nextVal = this.cursor.value;
|
|
3717
|
+
if (!nextVal.point) { // Opening a range
|
|
3718
|
+
this.addActive(trackOpen);
|
|
3719
|
+
this.cursor.next();
|
|
3720
|
+
}
|
|
3721
|
+
else if (wasPoint && this.cursor.to == this.to && this.cursor.from < this.cursor.to) {
|
|
3722
|
+
// Ignore any non-empty points that end precisely at the end of the prev point
|
|
3723
|
+
this.cursor.next();
|
|
3724
|
+
}
|
|
3725
|
+
else { // New point
|
|
3726
|
+
this.point = nextVal;
|
|
3727
|
+
this.pointFrom = this.cursor.from;
|
|
3728
|
+
this.pointRank = this.cursor.rank;
|
|
3729
|
+
this.to = this.cursor.to;
|
|
3730
|
+
this.endSide = nextVal.endSide;
|
|
3731
|
+
if (this.cursor.from < from)
|
|
3732
|
+
trackExtra = 1;
|
|
3733
|
+
this.cursor.next();
|
|
3734
|
+
this.forward(this.to, this.endSide);
|
|
3735
|
+
break;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
if (trackOpen) {
|
|
3740
|
+
let openStart = 0;
|
|
3741
|
+
while (openStart < trackOpen.length && trackOpen[openStart] < from)
|
|
3742
|
+
openStart++;
|
|
3743
|
+
this.openStart = openStart + trackExtra;
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
activeForPoint(to) {
|
|
3747
|
+
if (!this.active.length)
|
|
3748
|
+
return this.active;
|
|
3749
|
+
let active = [];
|
|
3750
|
+
for (let i = this.active.length - 1; i >= 0; i--) {
|
|
3751
|
+
if (this.activeRank[i] < this.pointRank)
|
|
3752
|
+
break;
|
|
3753
|
+
if (this.activeTo[i] > to || this.activeTo[i] == to && this.active[i].endSide >= this.point.endSide)
|
|
3754
|
+
active.push(this.active[i]);
|
|
3755
|
+
}
|
|
3756
|
+
return active.reverse();
|
|
3757
|
+
}
|
|
3758
|
+
openEnd(to) {
|
|
3759
|
+
let open = 0;
|
|
3760
|
+
for (let i = this.activeTo.length - 1; i >= 0 && this.activeTo[i] > to; i--)
|
|
3761
|
+
open++;
|
|
3762
|
+
return open;
|
|
3763
|
+
}
|
|
3764
|
+
}
|
|
3765
|
+
function compare(a, startA, b, startB, length, comparator) {
|
|
3766
|
+
a.goto(startA);
|
|
3767
|
+
b.goto(startB);
|
|
3768
|
+
let endB = startB + length;
|
|
3769
|
+
let pos = startB, dPos = startB - startA;
|
|
3770
|
+
for (;;) {
|
|
3771
|
+
let diff = (a.to + dPos) - b.to || a.endSide - b.endSide;
|
|
3772
|
+
let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB);
|
|
3773
|
+
if (a.point || b.point) {
|
|
3774
|
+
if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) &&
|
|
3775
|
+
sameValues(a.activeForPoint(a.to + dPos), b.activeForPoint(b.to))))
|
|
3776
|
+
comparator.comparePoint(pos, clipEnd, a.point, b.point);
|
|
3777
|
+
}
|
|
3778
|
+
else {
|
|
3779
|
+
if (clipEnd > pos && !sameValues(a.active, b.active))
|
|
3780
|
+
comparator.compareRange(pos, clipEnd, a.active, b.active);
|
|
3781
|
+
}
|
|
3782
|
+
if (end > endB)
|
|
3783
|
+
break;
|
|
3784
|
+
pos = end;
|
|
3785
|
+
if (diff <= 0)
|
|
3786
|
+
a.next();
|
|
3787
|
+
if (diff >= 0)
|
|
3788
|
+
b.next();
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
function sameValues(a, b) {
|
|
3792
|
+
if (a.length != b.length)
|
|
3793
|
+
return false;
|
|
3794
|
+
for (let i = 0; i < a.length; i++)
|
|
3795
|
+
if (a[i] != b[i] && !a[i].eq(b[i]))
|
|
3796
|
+
return false;
|
|
3797
|
+
return true;
|
|
3798
|
+
}
|
|
3799
|
+
function remove(array, index) {
|
|
3800
|
+
for (let i = index, e = array.length - 1; i < e; i++)
|
|
3801
|
+
array[i] = array[i + 1];
|
|
3802
|
+
array.pop();
|
|
3803
|
+
}
|
|
3804
|
+
function insert(array, index, value) {
|
|
3805
|
+
for (let i = array.length - 1; i >= index; i--)
|
|
3806
|
+
array[i + 1] = array[i];
|
|
3807
|
+
array[index] = value;
|
|
3808
|
+
}
|
|
3809
|
+
function findMinIndex(value, array) {
|
|
3810
|
+
let found = -1, foundPos = 1000000000 /* Far */;
|
|
3811
|
+
for (let i = 0; i < array.length; i++)
|
|
3812
|
+
if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) {
|
|
3813
|
+
found = i;
|
|
3814
|
+
foundPos = array[i];
|
|
3815
|
+
}
|
|
3816
|
+
return found;
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3819
|
+
/**
|
|
3820
|
+
Count the column position at the given offset into the string,
|
|
3821
|
+
taking extending characters and tab size into account.
|
|
3822
|
+
*/
|
|
3823
|
+
function countColumn(string, tabSize, to = string.length) {
|
|
3824
|
+
let n = 0;
|
|
3825
|
+
for (let i = 0; i < to;) {
|
|
3826
|
+
if (string.charCodeAt(i) == 9) {
|
|
3827
|
+
n += tabSize - (n % tabSize);
|
|
3828
|
+
i++;
|
|
3829
|
+
}
|
|
3830
|
+
else {
|
|
3831
|
+
n++;
|
|
3832
|
+
i = findClusterBreak(string, i);
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
return n;
|
|
3836
|
+
}
|
|
3837
|
+
/**
|
|
3838
|
+
Find the offset that corresponds to the given column position in a
|
|
3839
|
+
string, taking extending characters and tab size into account. By
|
|
3840
|
+
default, the string length is returned when it is too short to
|
|
3841
|
+
reach the column. Pass `strict` true to make it return -1 in that
|
|
3842
|
+
situation.
|
|
3843
|
+
*/
|
|
3844
|
+
function findColumn(string, col, tabSize, strict) {
|
|
3845
|
+
for (let i = 0, n = 0;;) {
|
|
3846
|
+
if (n >= col)
|
|
3847
|
+
return i;
|
|
3848
|
+
if (i == string.length)
|
|
3849
|
+
break;
|
|
3850
|
+
n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1;
|
|
3851
|
+
i = findClusterBreak(string, i);
|
|
3852
|
+
}
|
|
3853
|
+
return strict === true ? -1 : string.length;
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
export { Annotation, AnnotationType, ChangeDesc, ChangeSet, CharCategory, Compartment, EditorSelection, EditorState, Facet, Line, MapMode, Prec, Range, RangeSet, RangeSetBuilder, RangeValue, SelectionRange, StateEffect, StateEffectType, StateField, Text, Transaction, codePointAt, codePointSize, combineConfig, countColumn, findClusterBreak, findColumn, fromCodePoint };
|