@uiw/react-codemirror 4.6.0 → 4.7.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/README.md +5 -0
- package/dist/codemirror.js +2890 -951
- package/dist/codemirror.min.js +1 -1
- package/package.json +20 -20
package/dist/codemirror.js
CHANGED
|
@@ -12,7 +12,7 @@ return /******/ (() => { // webpackBootstrap
|
|
|
12
12
|
/******/ "use strict";
|
|
13
13
|
/******/ var __webpack_modules__ = ({
|
|
14
14
|
|
|
15
|
-
/***/
|
|
15
|
+
/***/ 963:
|
|
16
16
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
17
17
|
|
|
18
18
|
|
|
@@ -93,700 +93,6 @@ var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_re
|
|
|
93
93
|
var basic_setup_ = __webpack_require__(573);
|
|
94
94
|
// EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"}
|
|
95
95
|
var state_ = __webpack_require__(242);
|
|
96
|
-
;// CONCATENATED MODULE: ./node_modules/@codemirror/text/dist/index.js
|
|
97
|
-
// Compressed representation of the Grapheme_Cluster_Break=Extend
|
|
98
|
-
// information from
|
|
99
|
-
// http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt.
|
|
100
|
-
// Each pair of elements represents a range, as an offet from the
|
|
101
|
-
// previous range and a length. Numbers are in base-36, with the empty
|
|
102
|
-
// string being a shorthand for 1.
|
|
103
|
-
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);
|
|
104
|
-
// Convert offsets into absolute values
|
|
105
|
-
for (let i = 1; i < extend.length; i++)
|
|
106
|
-
extend[i] += extend[i - 1];
|
|
107
|
-
function isExtendingChar(code) {
|
|
108
|
-
for (let i = 1; i < extend.length; i += 2)
|
|
109
|
-
if (extend[i] > code)
|
|
110
|
-
return extend[i - 1] <= code;
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
function isRegionalIndicator(code) {
|
|
114
|
-
return code >= 0x1F1E6 && code <= 0x1F1FF;
|
|
115
|
-
}
|
|
116
|
-
const ZWJ = 0x200d;
|
|
117
|
-
/**
|
|
118
|
-
Returns a next grapheme cluster break _after_ (not equal to)
|
|
119
|
-
`pos`, if `forward` is true, or before otherwise. Returns `pos`
|
|
120
|
-
itself if no further cluster break is available in the string.
|
|
121
|
-
Moves across surrogate pairs, extending characters (when
|
|
122
|
-
`includeExtending` is true), characters joined with zero-width
|
|
123
|
-
joiners, and flag emoji.
|
|
124
|
-
*/
|
|
125
|
-
function findClusterBreak(str, pos, forward = true, includeExtending = true) {
|
|
126
|
-
return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending);
|
|
127
|
-
}
|
|
128
|
-
function nextClusterBreak(str, pos, includeExtending) {
|
|
129
|
-
if (pos == str.length)
|
|
130
|
-
return pos;
|
|
131
|
-
// If pos is in the middle of a surrogate pair, move to its start
|
|
132
|
-
if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1)))
|
|
133
|
-
pos--;
|
|
134
|
-
let prev = codePointAt(str, pos);
|
|
135
|
-
pos += codePointSize(prev);
|
|
136
|
-
while (pos < str.length) {
|
|
137
|
-
let next = codePointAt(str, pos);
|
|
138
|
-
if (prev == ZWJ || next == ZWJ || includeExtending && isExtendingChar(next)) {
|
|
139
|
-
pos += codePointSize(next);
|
|
140
|
-
prev = next;
|
|
141
|
-
}
|
|
142
|
-
else if (isRegionalIndicator(next)) {
|
|
143
|
-
let countBefore = 0, i = pos - 2;
|
|
144
|
-
while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) {
|
|
145
|
-
countBefore++;
|
|
146
|
-
i -= 2;
|
|
147
|
-
}
|
|
148
|
-
if (countBefore % 2 == 0)
|
|
149
|
-
break;
|
|
150
|
-
else
|
|
151
|
-
pos += 2;
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return pos;
|
|
158
|
-
}
|
|
159
|
-
function prevClusterBreak(str, pos, includeExtending) {
|
|
160
|
-
while (pos > 0) {
|
|
161
|
-
let found = nextClusterBreak(str, pos - 2, includeExtending);
|
|
162
|
-
if (found < pos)
|
|
163
|
-
return found;
|
|
164
|
-
pos--;
|
|
165
|
-
}
|
|
166
|
-
return 0;
|
|
167
|
-
}
|
|
168
|
-
function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
|
|
169
|
-
function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
|
|
170
|
-
/**
|
|
171
|
-
Find the code point at the given position in a string (like the
|
|
172
|
-
[`codePointAt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt)
|
|
173
|
-
string method).
|
|
174
|
-
*/
|
|
175
|
-
function codePointAt(str, pos) {
|
|
176
|
-
let code0 = str.charCodeAt(pos);
|
|
177
|
-
if (!surrogateHigh(code0) || pos + 1 == str.length)
|
|
178
|
-
return code0;
|
|
179
|
-
let code1 = str.charCodeAt(pos + 1);
|
|
180
|
-
if (!surrogateLow(code1))
|
|
181
|
-
return code0;
|
|
182
|
-
return ((code0 - 0xd800) << 10) + (code1 - 0xdc00) + 0x10000;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
Given a Unicode codepoint, return the JavaScript string that
|
|
186
|
-
respresents it (like
|
|
187
|
-
[`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)).
|
|
188
|
-
*/
|
|
189
|
-
function fromCodePoint(code) {
|
|
190
|
-
if (code <= 0xffff)
|
|
191
|
-
return String.fromCharCode(code);
|
|
192
|
-
code -= 0x10000;
|
|
193
|
-
return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
The first character that takes up two positions in a JavaScript
|
|
197
|
-
string. It is often useful to compare with this after calling
|
|
198
|
-
`codePointAt`, to figure out whether your character takes up 1 or
|
|
199
|
-
2 index positions.
|
|
200
|
-
*/
|
|
201
|
-
function codePointSize(code) { return code < 0x10000 ? 1 : 2; }
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
Count the column position at the given offset into the string,
|
|
205
|
-
taking extending characters and tab size into account.
|
|
206
|
-
*/
|
|
207
|
-
function dist_countColumn(string, tabSize, to = string.length) {
|
|
208
|
-
let n = 0;
|
|
209
|
-
for (let i = 0; i < to;) {
|
|
210
|
-
if (string.charCodeAt(i) == 9) {
|
|
211
|
-
n += tabSize - (n % tabSize);
|
|
212
|
-
i++;
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
n++;
|
|
216
|
-
i = findClusterBreak(string, i);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return n;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
Find the offset that corresponds to the given column position in a
|
|
223
|
-
string, taking extending characters and tab size into account. By
|
|
224
|
-
default, the string length is returned when it is too short to
|
|
225
|
-
reach the column. Pass `strict` true to make it return -1 in that
|
|
226
|
-
situation.
|
|
227
|
-
*/
|
|
228
|
-
function findColumn(string, col, tabSize, strict) {
|
|
229
|
-
for (let i = 0, n = 0;;) {
|
|
230
|
-
if (n >= col)
|
|
231
|
-
return i;
|
|
232
|
-
if (i == string.length)
|
|
233
|
-
break;
|
|
234
|
-
n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1;
|
|
235
|
-
i = findClusterBreak(string, i);
|
|
236
|
-
}
|
|
237
|
-
return strict === true ? -1 : string.length;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
The data structure for documents.
|
|
242
|
-
*/
|
|
243
|
-
class dist_Text {
|
|
244
|
-
/**
|
|
245
|
-
@internal
|
|
246
|
-
*/
|
|
247
|
-
constructor() { }
|
|
248
|
-
/**
|
|
249
|
-
Get the line description around the given position.
|
|
250
|
-
*/
|
|
251
|
-
lineAt(pos) {
|
|
252
|
-
if (pos < 0 || pos > this.length)
|
|
253
|
-
throw new RangeError(`Invalid position ${pos} in document of length ${this.length}`);
|
|
254
|
-
return this.lineInner(pos, false, 1, 0);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
Get the description for the given (1-based) line number.
|
|
258
|
-
*/
|
|
259
|
-
line(n) {
|
|
260
|
-
if (n < 1 || n > this.lines)
|
|
261
|
-
throw new RangeError(`Invalid line number ${n} in ${this.lines}-line document`);
|
|
262
|
-
return this.lineInner(n, true, 1, 0);
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
Replace a range of the text with the given content.
|
|
266
|
-
*/
|
|
267
|
-
replace(from, to, text) {
|
|
268
|
-
let parts = [];
|
|
269
|
-
this.decompose(0, from, parts, 2 /* To */);
|
|
270
|
-
if (text.length)
|
|
271
|
-
text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */);
|
|
272
|
-
this.decompose(to, this.length, parts, 1 /* From */);
|
|
273
|
-
return TextNode.from(parts, this.length - (to - from) + text.length);
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
Append another document to this one.
|
|
277
|
-
*/
|
|
278
|
-
append(other) {
|
|
279
|
-
return this.replace(this.length, this.length, other);
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
Retrieve the text between the given points.
|
|
283
|
-
*/
|
|
284
|
-
slice(from, to = this.length) {
|
|
285
|
-
let parts = [];
|
|
286
|
-
this.decompose(from, to, parts, 0);
|
|
287
|
-
return TextNode.from(parts, to - from);
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
Test whether this text is equal to another instance.
|
|
291
|
-
*/
|
|
292
|
-
eq(other) {
|
|
293
|
-
if (other == this)
|
|
294
|
-
return true;
|
|
295
|
-
if (other.length != this.length || other.lines != this.lines)
|
|
296
|
-
return false;
|
|
297
|
-
let start = this.scanIdentical(other, 1), end = this.length - this.scanIdentical(other, -1);
|
|
298
|
-
let a = new RawTextCursor(this), b = new RawTextCursor(other);
|
|
299
|
-
for (let skip = start, pos = start;;) {
|
|
300
|
-
a.next(skip);
|
|
301
|
-
b.next(skip);
|
|
302
|
-
skip = 0;
|
|
303
|
-
if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value)
|
|
304
|
-
return false;
|
|
305
|
-
pos += a.value.length;
|
|
306
|
-
if (a.done || pos >= end)
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
Iterate over the text. When `dir` is `-1`, iteration happens
|
|
312
|
-
from end to start. This will return lines and the breaks between
|
|
313
|
-
them as separate strings, and for long lines, might split lines
|
|
314
|
-
themselves into multiple chunks as well.
|
|
315
|
-
*/
|
|
316
|
-
iter(dir = 1) { return new RawTextCursor(this, dir); }
|
|
317
|
-
/**
|
|
318
|
-
Iterate over a range of the text. When `from` > `to`, the
|
|
319
|
-
iterator will run in reverse.
|
|
320
|
-
*/
|
|
321
|
-
iterRange(from, to = this.length) { return new PartialTextCursor(this, from, to); }
|
|
322
|
-
/**
|
|
323
|
-
Return a cursor that iterates over the given range of lines,
|
|
324
|
-
_without_ returning the line breaks between, and yielding empty
|
|
325
|
-
strings for empty lines.
|
|
326
|
-
|
|
327
|
-
When `from` and `to` are given, they should be 1-based line numbers.
|
|
328
|
-
*/
|
|
329
|
-
iterLines(from, to) {
|
|
330
|
-
let inner;
|
|
331
|
-
if (from == null) {
|
|
332
|
-
inner = this.iter();
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
if (to == null)
|
|
336
|
-
to = this.lines + 1;
|
|
337
|
-
let start = this.line(from).from;
|
|
338
|
-
inner = this.iterRange(start, Math.max(start, to == this.lines + 1 ? this.length : to <= 1 ? 0 : this.line(to - 1).to));
|
|
339
|
-
}
|
|
340
|
-
return new LineCursor(inner);
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
@internal
|
|
344
|
-
*/
|
|
345
|
-
toString() { return this.sliceString(0); }
|
|
346
|
-
/**
|
|
347
|
-
Convert the document to an array of lines (which can be
|
|
348
|
-
deserialized again via [`Text.of`](https://codemirror.net/6/docs/ref/#text.Text^of)).
|
|
349
|
-
*/
|
|
350
|
-
toJSON() {
|
|
351
|
-
let lines = [];
|
|
352
|
-
this.flatten(lines);
|
|
353
|
-
return lines;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
Create a `Text` instance for the given array of lines.
|
|
357
|
-
*/
|
|
358
|
-
static of(text) {
|
|
359
|
-
if (text.length == 0)
|
|
360
|
-
throw new RangeError("A document must have at least one line");
|
|
361
|
-
if (text.length == 1 && !text[0])
|
|
362
|
-
return dist_Text.empty;
|
|
363
|
-
return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, []));
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
// Leaves store an array of line strings. There are always line breaks
|
|
367
|
-
// between these strings. Leaves are limited in size and have to be
|
|
368
|
-
// contained in TextNode instances for bigger documents.
|
|
369
|
-
class TextLeaf extends dist_Text {
|
|
370
|
-
constructor(text, length = textLength(text)) {
|
|
371
|
-
super();
|
|
372
|
-
this.text = text;
|
|
373
|
-
this.length = length;
|
|
374
|
-
}
|
|
375
|
-
get lines() { return this.text.length; }
|
|
376
|
-
get children() { return null; }
|
|
377
|
-
lineInner(target, isLine, line, offset) {
|
|
378
|
-
for (let i = 0;; i++) {
|
|
379
|
-
let string = this.text[i], end = offset + string.length;
|
|
380
|
-
if ((isLine ? line : end) >= target)
|
|
381
|
-
return new Line(offset, end, line, string);
|
|
382
|
-
offset = end + 1;
|
|
383
|
-
line++;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
decompose(from, to, target, open) {
|
|
387
|
-
let text = from <= 0 && to >= this.length ? this
|
|
388
|
-
: new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from));
|
|
389
|
-
if (open & 1 /* From */) {
|
|
390
|
-
let prev = target.pop();
|
|
391
|
-
let joined = appendText(text.text, prev.text.slice(), 0, text.length);
|
|
392
|
-
if (joined.length <= 32 /* Branch */) {
|
|
393
|
-
target.push(new TextLeaf(joined, prev.length + text.length));
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
let mid = joined.length >> 1;
|
|
397
|
-
target.push(new TextLeaf(joined.slice(0, mid)), new TextLeaf(joined.slice(mid)));
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
target.push(text);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
replace(from, to, text) {
|
|
405
|
-
if (!(text instanceof TextLeaf))
|
|
406
|
-
return super.replace(from, to, text);
|
|
407
|
-
let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to);
|
|
408
|
-
let newLen = this.length + text.length - (to - from);
|
|
409
|
-
if (lines.length <= 32 /* Branch */)
|
|
410
|
-
return new TextLeaf(lines, newLen);
|
|
411
|
-
return TextNode.from(TextLeaf.split(lines, []), newLen);
|
|
412
|
-
}
|
|
413
|
-
sliceString(from, to = this.length, lineSep = "\n") {
|
|
414
|
-
let result = "";
|
|
415
|
-
for (let pos = 0, i = 0; pos <= to && i < this.text.length; i++) {
|
|
416
|
-
let line = this.text[i], end = pos + line.length;
|
|
417
|
-
if (pos > from && i)
|
|
418
|
-
result += lineSep;
|
|
419
|
-
if (from < end && to > pos)
|
|
420
|
-
result += line.slice(Math.max(0, from - pos), to - pos);
|
|
421
|
-
pos = end + 1;
|
|
422
|
-
}
|
|
423
|
-
return result;
|
|
424
|
-
}
|
|
425
|
-
flatten(target) {
|
|
426
|
-
for (let line of this.text)
|
|
427
|
-
target.push(line);
|
|
428
|
-
}
|
|
429
|
-
scanIdentical() { return 0; }
|
|
430
|
-
static split(text, target) {
|
|
431
|
-
let part = [], len = -1;
|
|
432
|
-
for (let line of text) {
|
|
433
|
-
part.push(line);
|
|
434
|
-
len += line.length + 1;
|
|
435
|
-
if (part.length == 32 /* Branch */) {
|
|
436
|
-
target.push(new TextLeaf(part, len));
|
|
437
|
-
part = [];
|
|
438
|
-
len = -1;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (len > -1)
|
|
442
|
-
target.push(new TextLeaf(part, len));
|
|
443
|
-
return target;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
// Nodes provide the tree structure of the `Text` type. They store a
|
|
447
|
-
// number of other nodes or leaves, taking care to balance themselves
|
|
448
|
-
// on changes. There are implied line breaks _between_ the children of
|
|
449
|
-
// a node (but not before the first or after the last child).
|
|
450
|
-
class TextNode extends dist_Text {
|
|
451
|
-
constructor(children, length) {
|
|
452
|
-
super();
|
|
453
|
-
this.children = children;
|
|
454
|
-
this.length = length;
|
|
455
|
-
this.lines = 0;
|
|
456
|
-
for (let child of children)
|
|
457
|
-
this.lines += child.lines;
|
|
458
|
-
}
|
|
459
|
-
lineInner(target, isLine, line, offset) {
|
|
460
|
-
for (let i = 0;; i++) {
|
|
461
|
-
let child = this.children[i], end = offset + child.length, endLine = line + child.lines - 1;
|
|
462
|
-
if ((isLine ? endLine : end) >= target)
|
|
463
|
-
return child.lineInner(target, isLine, line, offset);
|
|
464
|
-
offset = end + 1;
|
|
465
|
-
line = endLine + 1;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
decompose(from, to, target, open) {
|
|
469
|
-
for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) {
|
|
470
|
-
let child = this.children[i], end = pos + child.length;
|
|
471
|
-
if (from <= end && to >= pos) {
|
|
472
|
-
let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0));
|
|
473
|
-
if (pos >= from && end <= to && !childOpen)
|
|
474
|
-
target.push(child);
|
|
475
|
-
else
|
|
476
|
-
child.decompose(from - pos, to - pos, target, childOpen);
|
|
477
|
-
}
|
|
478
|
-
pos = end + 1;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
replace(from, to, text) {
|
|
482
|
-
if (text.lines < this.lines)
|
|
483
|
-
for (let i = 0, pos = 0; i < this.children.length; i++) {
|
|
484
|
-
let child = this.children[i], end = pos + child.length;
|
|
485
|
-
// Fast path: if the change only affects one child and the
|
|
486
|
-
// child's size remains in the acceptable range, only update
|
|
487
|
-
// that child
|
|
488
|
-
if (from >= pos && to <= end) {
|
|
489
|
-
let updated = child.replace(from - pos, to - pos, text);
|
|
490
|
-
let totalLines = this.lines - child.lines + updated.lines;
|
|
491
|
-
if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) &&
|
|
492
|
-
updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) {
|
|
493
|
-
let copy = this.children.slice();
|
|
494
|
-
copy[i] = updated;
|
|
495
|
-
return new TextNode(copy, this.length - (to - from) + text.length);
|
|
496
|
-
}
|
|
497
|
-
return super.replace(pos, end, updated);
|
|
498
|
-
}
|
|
499
|
-
pos = end + 1;
|
|
500
|
-
}
|
|
501
|
-
return super.replace(from, to, text);
|
|
502
|
-
}
|
|
503
|
-
sliceString(from, to = this.length, lineSep = "\n") {
|
|
504
|
-
let result = "";
|
|
505
|
-
for (let i = 0, pos = 0; i < this.children.length && pos <= to; i++) {
|
|
506
|
-
let child = this.children[i], end = pos + child.length;
|
|
507
|
-
if (pos > from && i)
|
|
508
|
-
result += lineSep;
|
|
509
|
-
if (from < end && to > pos)
|
|
510
|
-
result += child.sliceString(from - pos, to - pos, lineSep);
|
|
511
|
-
pos = end + 1;
|
|
512
|
-
}
|
|
513
|
-
return result;
|
|
514
|
-
}
|
|
515
|
-
flatten(target) {
|
|
516
|
-
for (let child of this.children)
|
|
517
|
-
child.flatten(target);
|
|
518
|
-
}
|
|
519
|
-
scanIdentical(other, dir) {
|
|
520
|
-
if (!(other instanceof TextNode))
|
|
521
|
-
return 0;
|
|
522
|
-
let length = 0;
|
|
523
|
-
let [iA, iB, eA, eB] = dir > 0 ? [0, 0, this.children.length, other.children.length]
|
|
524
|
-
: [this.children.length - 1, other.children.length - 1, -1, -1];
|
|
525
|
-
for (;; iA += dir, iB += dir) {
|
|
526
|
-
if (iA == eA || iB == eB)
|
|
527
|
-
return length;
|
|
528
|
-
let chA = this.children[iA], chB = other.children[iB];
|
|
529
|
-
if (chA != chB)
|
|
530
|
-
return length + chA.scanIdentical(chB, dir);
|
|
531
|
-
length += chA.length + 1;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
static from(children, length = children.reduce((l, ch) => l + ch.length + 1, -1)) {
|
|
535
|
-
let lines = 0;
|
|
536
|
-
for (let ch of children)
|
|
537
|
-
lines += ch.lines;
|
|
538
|
-
if (lines < 32 /* Branch */) {
|
|
539
|
-
let flat = [];
|
|
540
|
-
for (let ch of children)
|
|
541
|
-
ch.flatten(flat);
|
|
542
|
-
return new TextLeaf(flat, length);
|
|
543
|
-
}
|
|
544
|
-
let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1;
|
|
545
|
-
let chunked = [], currentLines = 0, currentLen = -1, currentChunk = [];
|
|
546
|
-
function add(child) {
|
|
547
|
-
let last;
|
|
548
|
-
if (child.lines > maxChunk && child instanceof TextNode) {
|
|
549
|
-
for (let node of child.children)
|
|
550
|
-
add(node);
|
|
551
|
-
}
|
|
552
|
-
else if (child.lines > minChunk && (currentLines > minChunk || !currentLines)) {
|
|
553
|
-
flush();
|
|
554
|
-
chunked.push(child);
|
|
555
|
-
}
|
|
556
|
-
else if (child instanceof TextLeaf && currentLines &&
|
|
557
|
-
(last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf &&
|
|
558
|
-
child.lines + last.lines <= 32 /* Branch */) {
|
|
559
|
-
currentLines += child.lines;
|
|
560
|
-
currentLen += child.length + 1;
|
|
561
|
-
currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length);
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
if (currentLines + child.lines > chunk)
|
|
565
|
-
flush();
|
|
566
|
-
currentLines += child.lines;
|
|
567
|
-
currentLen += child.length + 1;
|
|
568
|
-
currentChunk.push(child);
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
function flush() {
|
|
572
|
-
if (currentLines == 0)
|
|
573
|
-
return;
|
|
574
|
-
chunked.push(currentChunk.length == 1 ? currentChunk[0] : TextNode.from(currentChunk, currentLen));
|
|
575
|
-
currentLen = -1;
|
|
576
|
-
currentLines = currentChunk.length = 0;
|
|
577
|
-
}
|
|
578
|
-
for (let child of children)
|
|
579
|
-
add(child);
|
|
580
|
-
flush();
|
|
581
|
-
return chunked.length == 1 ? chunked[0] : new TextNode(chunked, length);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
dist_Text.empty = /*@__PURE__*/new TextLeaf([""], 0);
|
|
585
|
-
function textLength(text) {
|
|
586
|
-
let length = -1;
|
|
587
|
-
for (let line of text)
|
|
588
|
-
length += line.length + 1;
|
|
589
|
-
return length;
|
|
590
|
-
}
|
|
591
|
-
function appendText(text, target, from = 0, to = 1e9) {
|
|
592
|
-
for (let pos = 0, i = 0, first = true; i < text.length && pos <= to; i++) {
|
|
593
|
-
let line = text[i], end = pos + line.length;
|
|
594
|
-
if (end >= from) {
|
|
595
|
-
if (end > to)
|
|
596
|
-
line = line.slice(0, to - pos);
|
|
597
|
-
if (pos < from)
|
|
598
|
-
line = line.slice(from - pos);
|
|
599
|
-
if (first) {
|
|
600
|
-
target[target.length - 1] += line;
|
|
601
|
-
first = false;
|
|
602
|
-
}
|
|
603
|
-
else
|
|
604
|
-
target.push(line);
|
|
605
|
-
}
|
|
606
|
-
pos = end + 1;
|
|
607
|
-
}
|
|
608
|
-
return target;
|
|
609
|
-
}
|
|
610
|
-
function sliceText(text, from, to) {
|
|
611
|
-
return appendText(text, [""], from, to);
|
|
612
|
-
}
|
|
613
|
-
class RawTextCursor {
|
|
614
|
-
constructor(text, dir = 1) {
|
|
615
|
-
this.dir = dir;
|
|
616
|
-
this.done = false;
|
|
617
|
-
this.lineBreak = false;
|
|
618
|
-
this.value = "";
|
|
619
|
-
this.nodes = [text];
|
|
620
|
-
this.offsets = [dir > 0 ? 1 : (text instanceof TextLeaf ? text.text.length : text.children.length) << 1];
|
|
621
|
-
}
|
|
622
|
-
nextInner(skip, dir) {
|
|
623
|
-
this.done = this.lineBreak = false;
|
|
624
|
-
for (;;) {
|
|
625
|
-
let last = this.nodes.length - 1;
|
|
626
|
-
let top = this.nodes[last], offsetValue = this.offsets[last], offset = offsetValue >> 1;
|
|
627
|
-
let size = top instanceof TextLeaf ? top.text.length : top.children.length;
|
|
628
|
-
if (offset == (dir > 0 ? size : 0)) {
|
|
629
|
-
if (last == 0) {
|
|
630
|
-
this.done = true;
|
|
631
|
-
this.value = "";
|
|
632
|
-
return this;
|
|
633
|
-
}
|
|
634
|
-
if (dir > 0)
|
|
635
|
-
this.offsets[last - 1]++;
|
|
636
|
-
this.nodes.pop();
|
|
637
|
-
this.offsets.pop();
|
|
638
|
-
}
|
|
639
|
-
else if ((offsetValue & 1) == (dir > 0 ? 0 : 1)) {
|
|
640
|
-
this.offsets[last] += dir;
|
|
641
|
-
if (skip == 0) {
|
|
642
|
-
this.lineBreak = true;
|
|
643
|
-
this.value = "\n";
|
|
644
|
-
return this;
|
|
645
|
-
}
|
|
646
|
-
skip--;
|
|
647
|
-
}
|
|
648
|
-
else if (top instanceof TextLeaf) {
|
|
649
|
-
// Move to the next string
|
|
650
|
-
let next = top.text[offset + (dir < 0 ? -1 : 0)];
|
|
651
|
-
this.offsets[last] += dir;
|
|
652
|
-
if (next.length > Math.max(0, skip)) {
|
|
653
|
-
this.value = skip == 0 ? next : dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip);
|
|
654
|
-
return this;
|
|
655
|
-
}
|
|
656
|
-
skip -= next.length;
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
let next = top.children[offset + (dir < 0 ? -1 : 0)];
|
|
660
|
-
if (skip > next.length) {
|
|
661
|
-
skip -= next.length;
|
|
662
|
-
this.offsets[last] += dir;
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
if (dir < 0)
|
|
666
|
-
this.offsets[last]--;
|
|
667
|
-
this.nodes.push(next);
|
|
668
|
-
this.offsets.push(dir > 0 ? 1 : (next instanceof TextLeaf ? next.text.length : next.children.length) << 1);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
next(skip = 0) {
|
|
674
|
-
if (skip < 0) {
|
|
675
|
-
this.nextInner(-skip, (-this.dir));
|
|
676
|
-
skip = this.value.length;
|
|
677
|
-
}
|
|
678
|
-
return this.nextInner(skip, this.dir);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
class PartialTextCursor {
|
|
682
|
-
constructor(text, start, end) {
|
|
683
|
-
this.value = "";
|
|
684
|
-
this.done = false;
|
|
685
|
-
this.cursor = new RawTextCursor(text, start > end ? -1 : 1);
|
|
686
|
-
this.pos = start > end ? text.length : 0;
|
|
687
|
-
this.from = Math.min(start, end);
|
|
688
|
-
this.to = Math.max(start, end);
|
|
689
|
-
}
|
|
690
|
-
nextInner(skip, dir) {
|
|
691
|
-
if (dir < 0 ? this.pos <= this.from : this.pos >= this.to) {
|
|
692
|
-
this.value = "";
|
|
693
|
-
this.done = true;
|
|
694
|
-
return this;
|
|
695
|
-
}
|
|
696
|
-
skip += Math.max(0, dir < 0 ? this.pos - this.to : this.from - this.pos);
|
|
697
|
-
let limit = dir < 0 ? this.pos - this.from : this.to - this.pos;
|
|
698
|
-
if (skip > limit)
|
|
699
|
-
skip = limit;
|
|
700
|
-
limit -= skip;
|
|
701
|
-
let { value } = this.cursor.next(skip);
|
|
702
|
-
this.pos += (value.length + skip) * dir;
|
|
703
|
-
this.value = value.length <= limit ? value : dir < 0 ? value.slice(value.length - limit) : value.slice(0, limit);
|
|
704
|
-
this.done = !this.value;
|
|
705
|
-
return this;
|
|
706
|
-
}
|
|
707
|
-
next(skip = 0) {
|
|
708
|
-
if (skip < 0)
|
|
709
|
-
skip = Math.max(skip, this.from - this.pos);
|
|
710
|
-
else if (skip > 0)
|
|
711
|
-
skip = Math.min(skip, this.to - this.pos);
|
|
712
|
-
return this.nextInner(skip, this.cursor.dir);
|
|
713
|
-
}
|
|
714
|
-
get lineBreak() { return this.cursor.lineBreak && this.value != ""; }
|
|
715
|
-
}
|
|
716
|
-
class LineCursor {
|
|
717
|
-
constructor(inner) {
|
|
718
|
-
this.inner = inner;
|
|
719
|
-
this.afterBreak = true;
|
|
720
|
-
this.value = "";
|
|
721
|
-
this.done = false;
|
|
722
|
-
}
|
|
723
|
-
next(skip = 0) {
|
|
724
|
-
let { done, lineBreak, value } = this.inner.next(skip);
|
|
725
|
-
if (done) {
|
|
726
|
-
this.done = true;
|
|
727
|
-
this.value = "";
|
|
728
|
-
}
|
|
729
|
-
else if (lineBreak) {
|
|
730
|
-
if (this.afterBreak) {
|
|
731
|
-
this.value = "";
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
this.afterBreak = true;
|
|
735
|
-
this.next();
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
else {
|
|
739
|
-
this.value = value;
|
|
740
|
-
this.afterBreak = false;
|
|
741
|
-
}
|
|
742
|
-
return this;
|
|
743
|
-
}
|
|
744
|
-
get lineBreak() { return false; }
|
|
745
|
-
}
|
|
746
|
-
if (typeof Symbol != "undefined") {
|
|
747
|
-
dist_Text.prototype[Symbol.iterator] = function () { return this.iter(); };
|
|
748
|
-
RawTextCursor.prototype[Symbol.iterator] = PartialTextCursor.prototype[Symbol.iterator] =
|
|
749
|
-
LineCursor.prototype[Symbol.iterator] = function () { return this; };
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
This type describes a line in the document. It is created
|
|
753
|
-
on-demand when lines are [queried](https://codemirror.net/6/docs/ref/#text.Text.lineAt).
|
|
754
|
-
*/
|
|
755
|
-
class Line {
|
|
756
|
-
/**
|
|
757
|
-
@internal
|
|
758
|
-
*/
|
|
759
|
-
constructor(
|
|
760
|
-
/**
|
|
761
|
-
The position of the start of the line.
|
|
762
|
-
*/
|
|
763
|
-
from,
|
|
764
|
-
/**
|
|
765
|
-
The position at the end of the line (_before_ the line break,
|
|
766
|
-
or at the end of document for the last line).
|
|
767
|
-
*/
|
|
768
|
-
to,
|
|
769
|
-
/**
|
|
770
|
-
This line's line number (1-based).
|
|
771
|
-
*/
|
|
772
|
-
number,
|
|
773
|
-
/**
|
|
774
|
-
The line's content.
|
|
775
|
-
*/
|
|
776
|
-
text) {
|
|
777
|
-
this.from = from;
|
|
778
|
-
this.to = to;
|
|
779
|
-
this.number = number;
|
|
780
|
-
this.text = text;
|
|
781
|
-
}
|
|
782
|
-
/**
|
|
783
|
-
The length of the line (not including any line break after it).
|
|
784
|
-
*/
|
|
785
|
-
get length() { return this.to - this.from; }
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
96
|
// EXTERNAL MODULE: external {"root":["CM","@codemirror/view"],"commonjs":"@codemirror/view","commonjs2":"@codemirror/view"}
|
|
791
97
|
var view_ = __webpack_require__(105);
|
|
792
98
|
;// CONCATENATED MODULE: ./node_modules/@lezer/common/dist/index.js
|
|
@@ -824,7 +130,7 @@ class dist_NodeProp {
|
|
|
824
130
|
if (this.perNode)
|
|
825
131
|
throw new RangeError("Can't add per-node props to node types");
|
|
826
132
|
if (typeof match != "function")
|
|
827
|
-
match =
|
|
133
|
+
match = dist_NodeType.match(match);
|
|
828
134
|
return (type) => {
|
|
829
135
|
let result = match(type);
|
|
830
136
|
return result === undefined ? null : [this, result];
|
|
@@ -881,7 +187,7 @@ class MountedTree {
|
|
|
881
187
|
}
|
|
882
188
|
const noProps = Object.create(null);
|
|
883
189
|
/// Each node in a syntax tree has a node type associated with it.
|
|
884
|
-
class
|
|
190
|
+
class dist_NodeType {
|
|
885
191
|
/// @internal
|
|
886
192
|
constructor(
|
|
887
193
|
/// The name of the node type. Not necessarily unique, but if the
|
|
@@ -905,7 +211,7 @@ class NodeType {
|
|
|
905
211
|
let props = spec.props && spec.props.length ? Object.create(null) : noProps;
|
|
906
212
|
let flags = (spec.top ? 1 /* Top */ : 0) | (spec.skipped ? 2 /* Skipped */ : 0) |
|
|
907
213
|
(spec.error ? 4 /* Error */ : 0) | (spec.name == null ? 8 /* Anonymous */ : 0);
|
|
908
|
-
let type = new
|
|
214
|
+
let type = new dist_NodeType(spec.name || "", props, spec.id, flags);
|
|
909
215
|
if (spec.props)
|
|
910
216
|
for (let src of spec.props) {
|
|
911
217
|
if (!Array.isArray(src))
|
|
@@ -962,7 +268,7 @@ class NodeType {
|
|
|
962
268
|
}
|
|
963
269
|
}
|
|
964
270
|
/// An empty dummy node type to use when no actual type is available.
|
|
965
|
-
|
|
271
|
+
dist_NodeType.none = new dist_NodeType("", Object.create(null), 0, 8 /* Anonymous */);
|
|
966
272
|
/// A node set holds a collection of node types. It is used to
|
|
967
273
|
/// compactly represent trees by storing their type ids, rather than a
|
|
968
274
|
/// full pointer to the type object, in a numeric array. Each parser
|
|
@@ -996,12 +302,34 @@ class NodeSet {
|
|
|
996
302
|
newProps[add[0].id] = add[1];
|
|
997
303
|
}
|
|
998
304
|
}
|
|
999
|
-
newTypes.push(newProps ? new
|
|
305
|
+
newTypes.push(newProps ? new dist_NodeType(type.name, newProps, type.id, type.flags) : type);
|
|
1000
306
|
}
|
|
1001
307
|
return new NodeSet(newTypes);
|
|
1002
308
|
}
|
|
1003
309
|
}
|
|
1004
310
|
const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
311
|
+
/// Options that control iteration. Can be combined with the `|`
|
|
312
|
+
/// operator to enable multiple ones.
|
|
313
|
+
var IterMode;
|
|
314
|
+
(function (IterMode) {
|
|
315
|
+
/// When enabled, iteration will only visit [`Tree`](#common.Tree)
|
|
316
|
+
/// objects, not nodes packed into
|
|
317
|
+
/// [`TreeBuffer`](#common.TreeBuffer)s.
|
|
318
|
+
IterMode[IterMode["ExcludeBuffers"] = 1] = "ExcludeBuffers";
|
|
319
|
+
/// Enable this to make iteration include anonymous nodes (such as
|
|
320
|
+
/// the nodes that wrap repeated grammar constructs into a balanced
|
|
321
|
+
/// tree).
|
|
322
|
+
IterMode[IterMode["IncludeAnonymous"] = 2] = "IncludeAnonymous";
|
|
323
|
+
/// By default, regular [mounted](#common.NodeProp^mounted) nodes
|
|
324
|
+
/// replace their base node in iteration. Enable this to ignore them
|
|
325
|
+
/// instead.
|
|
326
|
+
IterMode[IterMode["IgnoreMounts"] = 4] = "IgnoreMounts";
|
|
327
|
+
/// This option only applies in
|
|
328
|
+
/// [`enter`](#common.SyntaxNode.enter)-style methods. It tells the
|
|
329
|
+
/// library to not enter mounted overlays if one covers the given
|
|
330
|
+
/// position.
|
|
331
|
+
IterMode[IterMode["IgnoreOverlays"] = 8] = "IgnoreOverlays";
|
|
332
|
+
})(IterMode || (IterMode = {}));
|
|
1005
333
|
/// A piece of syntax tree. There are two ways to approach these
|
|
1006
334
|
/// trees: the way they are actually stored in memory, and the
|
|
1007
335
|
/// convenient way.
|
|
@@ -1016,7 +344,7 @@ const CachedNode = new WeakMap(), CachedInnerNode = new WeakMap();
|
|
|
1016
344
|
/// [`SyntaxNode`](#common.SyntaxNode) interface instead, which provides
|
|
1017
345
|
/// a view on some part of this data structure, and can be used to
|
|
1018
346
|
/// move around to adjacent nodes.
|
|
1019
|
-
class
|
|
347
|
+
class dist_Tree {
|
|
1020
348
|
/// Construct a new tree. See also [`Tree.build`](#common.Tree^build).
|
|
1021
349
|
constructor(
|
|
1022
350
|
/// The type of the top node.
|
|
@@ -1060,25 +388,22 @@ class Tree {
|
|
|
1060
388
|
(/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) +
|
|
1061
389
|
(children.length ? "(" + children + ")" : "");
|
|
1062
390
|
}
|
|
1063
|
-
/// Get a [tree cursor](#common.TreeCursor)
|
|
1064
|
-
///
|
|
1065
|
-
///
|
|
1066
|
-
cursor(
|
|
1067
|
-
|
|
391
|
+
/// Get a [tree cursor](#common.TreeCursor) positioned at the top of
|
|
392
|
+
/// the tree. Mode can be used to [control](#common.IterMode) which
|
|
393
|
+
/// nodes the cursor visits.
|
|
394
|
+
cursor(mode = 0) {
|
|
395
|
+
return new TreeCursor(this.topNode, mode);
|
|
396
|
+
}
|
|
397
|
+
/// Get a [tree cursor](#common.TreeCursor) pointing into this tree
|
|
398
|
+
/// at the given position and side (see
|
|
399
|
+
/// [`moveTo`](#common.TreeCursor.moveTo).
|
|
400
|
+
cursorAt(pos, side = 0, mode = 0) {
|
|
401
|
+
let scope = CachedNode.get(this) || this.topNode;
|
|
1068
402
|
let cursor = new TreeCursor(scope);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
CachedNode.set(this, cursor._tree);
|
|
1072
|
-
}
|
|
403
|
+
cursor.moveTo(pos, side);
|
|
404
|
+
CachedNode.set(this, cursor._tree);
|
|
1073
405
|
return cursor;
|
|
1074
406
|
}
|
|
1075
|
-
/// Get a [tree cursor](#common.TreeCursor) that, unlike regular
|
|
1076
|
-
/// cursors, doesn't skip through
|
|
1077
|
-
/// [anonymous](#common.NodeType.isAnonymous) nodes and doesn't
|
|
1078
|
-
/// automatically enter mounted nodes.
|
|
1079
|
-
fullCursor() {
|
|
1080
|
-
return new TreeCursor(this.topNode, 1 /* Full */);
|
|
1081
|
-
}
|
|
1082
407
|
/// Get a [syntax node](#common.SyntaxNode) object for the top of the
|
|
1083
408
|
/// tree.
|
|
1084
409
|
get topNode() {
|
|
@@ -1111,23 +436,21 @@ class Tree {
|
|
|
1111
436
|
/// not have its children iterated over (or `leave` called).
|
|
1112
437
|
iterate(spec) {
|
|
1113
438
|
let { enter, leave, from = 0, to = this.length } = spec;
|
|
1114
|
-
for (let c = this.cursor(
|
|
1115
|
-
let
|
|
1116
|
-
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c
|
|
439
|
+
for (let c = this.cursor((spec.mode || 0) | IterMode.IncludeAnonymous);;) {
|
|
440
|
+
let entered = false;
|
|
441
|
+
if (c.from <= to && c.to >= from && (c.type.isAnonymous || enter(c) !== false)) {
|
|
1117
442
|
if (c.firstChild())
|
|
1118
443
|
continue;
|
|
1119
|
-
|
|
1120
|
-
mustLeave = true;
|
|
444
|
+
entered = true;
|
|
1121
445
|
}
|
|
1122
446
|
for (;;) {
|
|
1123
|
-
if (
|
|
1124
|
-
leave(c
|
|
1125
|
-
mustLeave = c.type.isAnonymous;
|
|
447
|
+
if (entered && leave && !c.type.isAnonymous)
|
|
448
|
+
leave(c);
|
|
1126
449
|
if (c.nextSibling())
|
|
1127
450
|
break;
|
|
1128
451
|
if (!c.parent())
|
|
1129
452
|
return;
|
|
1130
|
-
|
|
453
|
+
entered = true;
|
|
1131
454
|
}
|
|
1132
455
|
}
|
|
1133
456
|
}
|
|
@@ -1151,14 +474,14 @@ class Tree {
|
|
|
1151
474
|
/// [`NodeType.none`](#common.NodeType^none).
|
|
1152
475
|
balance(config = {}) {
|
|
1153
476
|
return this.children.length <= 8 /* BranchFactor */ ? this :
|
|
1154
|
-
balanceRange(
|
|
477
|
+
balanceRange(dist_NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new dist_Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new dist_Tree(dist_NodeType.none, children, positions, length)));
|
|
1155
478
|
}
|
|
1156
479
|
/// Build a tree from a postfix-ordered buffer of node information,
|
|
1157
480
|
/// or a cursor over such a buffer.
|
|
1158
481
|
static build(data) { return buildTree(data); }
|
|
1159
482
|
}
|
|
1160
483
|
/// The empty tree
|
|
1161
|
-
|
|
484
|
+
dist_Tree.empty = new dist_Tree(dist_NodeType.none, [], [], 0);
|
|
1162
485
|
class FlatBufferCursor {
|
|
1163
486
|
constructor(buffer, index) {
|
|
1164
487
|
this.buffer = buffer;
|
|
@@ -1190,7 +513,7 @@ class TreeBuffer {
|
|
|
1190
513
|
this.set = set;
|
|
1191
514
|
}
|
|
1192
515
|
/// @internal
|
|
1193
|
-
get type() { return
|
|
516
|
+
get type() { return dist_NodeType.none; }
|
|
1194
517
|
/// @internal
|
|
1195
518
|
toString() {
|
|
1196
519
|
let result = [];
|
|
@@ -1278,72 +601,73 @@ function resolveNode(node, pos, side, overlays) {
|
|
|
1278
601
|
return node;
|
|
1279
602
|
node = parent;
|
|
1280
603
|
}
|
|
604
|
+
let mode = overlays ? 0 : IterMode.IgnoreOverlays;
|
|
1281
605
|
// Must go up out of overlays when those do not overlap with pos
|
|
1282
606
|
if (overlays)
|
|
1283
607
|
for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
|
|
1284
|
-
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side,
|
|
608
|
+
if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
|
|
1285
609
|
node = parent;
|
|
1286
610
|
}
|
|
1287
611
|
for (;;) {
|
|
1288
|
-
let inner = node.enter(pos, side,
|
|
612
|
+
let inner = node.enter(pos, side, mode);
|
|
1289
613
|
if (!inner)
|
|
1290
614
|
return node;
|
|
1291
615
|
node = inner;
|
|
1292
616
|
}
|
|
1293
617
|
}
|
|
1294
618
|
class TreeNode {
|
|
1295
|
-
constructor(
|
|
619
|
+
constructor(_tree, from,
|
|
1296
620
|
// Index in parent node, set to -1 if the node is not a direct child of _parent.node (overlay)
|
|
1297
621
|
index, _parent) {
|
|
1298
|
-
this.
|
|
1299
|
-
this.
|
|
622
|
+
this._tree = _tree;
|
|
623
|
+
this.from = from;
|
|
1300
624
|
this.index = index;
|
|
1301
625
|
this._parent = _parent;
|
|
1302
626
|
}
|
|
1303
|
-
get type() { return this.
|
|
1304
|
-
get name() { return this.
|
|
1305
|
-
get
|
|
1306
|
-
get to() { return this._from + this.node.length; }
|
|
627
|
+
get type() { return this._tree.type; }
|
|
628
|
+
get name() { return this._tree.type.name; }
|
|
629
|
+
get to() { return this.from + this._tree.length; }
|
|
1307
630
|
nextChild(i, dir, pos, side, mode = 0) {
|
|
1308
631
|
for (let parent = this;;) {
|
|
1309
|
-
for (let { children, positions } = parent.
|
|
1310
|
-
let next = children[i], start = positions[i] + parent.
|
|
632
|
+
for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
|
|
633
|
+
let next = children[i], start = positions[i] + parent.from;
|
|
1311
634
|
if (!checkSide(side, pos, start, start + next.length))
|
|
1312
635
|
continue;
|
|
1313
636
|
if (next instanceof TreeBuffer) {
|
|
1314
|
-
if (mode &
|
|
637
|
+
if (mode & IterMode.ExcludeBuffers)
|
|
1315
638
|
continue;
|
|
1316
639
|
let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
|
|
1317
640
|
if (index > -1)
|
|
1318
641
|
return new BufferNode(new BufferContext(parent, next, i, start), null, index);
|
|
1319
642
|
}
|
|
1320
|
-
else if ((mode &
|
|
643
|
+
else if ((mode & IterMode.IncludeAnonymous) || (!next.type.isAnonymous || hasChild(next))) {
|
|
1321
644
|
let mounted;
|
|
1322
|
-
if (!(mode &
|
|
645
|
+
if (!(mode & IterMode.IgnoreMounts) &&
|
|
646
|
+
next.props && (mounted = next.prop(dist_NodeProp.mounted)) && !mounted.overlay)
|
|
1323
647
|
return new TreeNode(mounted.tree, start, i, parent);
|
|
1324
648
|
let inner = new TreeNode(next, start, i, parent);
|
|
1325
|
-
return (mode &
|
|
649
|
+
return (mode & IterMode.IncludeAnonymous) || !inner.type.isAnonymous ? inner
|
|
1326
650
|
: inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
|
|
1327
651
|
}
|
|
1328
652
|
}
|
|
1329
|
-
if ((mode &
|
|
653
|
+
if ((mode & IterMode.IncludeAnonymous) || !parent.type.isAnonymous)
|
|
1330
654
|
return null;
|
|
1331
655
|
if (parent.index >= 0)
|
|
1332
656
|
i = parent.index + dir;
|
|
1333
657
|
else
|
|
1334
|
-
i = dir < 0 ? -1 : parent._parent.
|
|
658
|
+
i = dir < 0 ? -1 : parent._parent._tree.children.length;
|
|
1335
659
|
parent = parent._parent;
|
|
1336
660
|
if (!parent)
|
|
1337
661
|
return null;
|
|
1338
662
|
}
|
|
1339
663
|
}
|
|
1340
664
|
get firstChild() { return this.nextChild(0, 1, 0, 4 /* DontCare */); }
|
|
1341
|
-
get lastChild() { return this.nextChild(this.
|
|
665
|
+
get lastChild() { return this.nextChild(this._tree.children.length - 1, -1, 0, 4 /* DontCare */); }
|
|
1342
666
|
childAfter(pos) { return this.nextChild(0, 1, pos, 2 /* After */); }
|
|
1343
|
-
childBefore(pos) { return this.nextChild(this.
|
|
1344
|
-
enter(pos, side,
|
|
667
|
+
childBefore(pos) { return this.nextChild(this._tree.children.length - 1, -1, pos, -2 /* Before */); }
|
|
668
|
+
enter(pos, side, mode = 0) {
|
|
1345
669
|
let mounted;
|
|
1346
|
-
if (
|
|
670
|
+
if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree.prop(dist_NodeProp.mounted)) && mounted.overlay) {
|
|
1347
671
|
let rPos = pos - this.from;
|
|
1348
672
|
for (let { from, to } of mounted.overlay) {
|
|
1349
673
|
if ((side > 0 ? from <= rPos : from < rPos) &&
|
|
@@ -1351,7 +675,7 @@ class TreeNode {
|
|
|
1351
675
|
return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
|
|
1352
676
|
}
|
|
1353
677
|
}
|
|
1354
|
-
return this.nextChild(0, 1, pos, side,
|
|
678
|
+
return this.nextChild(0, 1, pos, side, mode);
|
|
1355
679
|
}
|
|
1356
680
|
nextSignificantParent() {
|
|
1357
681
|
let val = this;
|
|
@@ -1368,9 +692,9 @@ class TreeNode {
|
|
|
1368
692
|
get prevSibling() {
|
|
1369
693
|
return this._parent && this.index >= 0 ? this._parent.nextChild(this.index - 1, -1, 0, 4 /* DontCare */) : null;
|
|
1370
694
|
}
|
|
1371
|
-
|
|
1372
|
-
get tree() { return this.
|
|
1373
|
-
toTree() { return this.
|
|
695
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
696
|
+
get tree() { return this._tree; }
|
|
697
|
+
toTree() { return this._tree; }
|
|
1374
698
|
resolve(pos, side = 0) {
|
|
1375
699
|
return resolveNode(this, pos, side, false);
|
|
1376
700
|
}
|
|
@@ -1386,10 +710,12 @@ class TreeNode {
|
|
|
1386
710
|
return getChildren(this, type, before, after);
|
|
1387
711
|
}
|
|
1388
712
|
/// @internal
|
|
1389
|
-
toString() { return this.
|
|
713
|
+
toString() { return this._tree.toString(); }
|
|
714
|
+
get node() { return this; }
|
|
715
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
1390
716
|
}
|
|
1391
717
|
function getChildren(node, type, before, after) {
|
|
1392
|
-
let cur = node.cursor, result = [];
|
|
718
|
+
let cur = node.cursor(), result = [];
|
|
1393
719
|
if (!cur.firstChild())
|
|
1394
720
|
return result;
|
|
1395
721
|
if (before != null)
|
|
@@ -1405,6 +731,18 @@ function getChildren(node, type, before, after) {
|
|
|
1405
731
|
return after == null ? result : [];
|
|
1406
732
|
}
|
|
1407
733
|
}
|
|
734
|
+
function matchNodeContext(node, context, i = context.length - 1) {
|
|
735
|
+
for (let p = node.parent; i >= 0; p = p.parent) {
|
|
736
|
+
if (!p)
|
|
737
|
+
return false;
|
|
738
|
+
if (!p.type.isAnonymous) {
|
|
739
|
+
if (context[i] && context[i] != p.name)
|
|
740
|
+
return false;
|
|
741
|
+
i--;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
1408
746
|
class BufferContext {
|
|
1409
747
|
constructor(parent, buffer, index, start) {
|
|
1410
748
|
this.parent = parent;
|
|
@@ -1432,8 +770,8 @@ class BufferNode {
|
|
|
1432
770
|
get lastChild() { return this.child(-1, 0, 4 /* DontCare */); }
|
|
1433
771
|
childAfter(pos) { return this.child(1, pos, 2 /* After */); }
|
|
1434
772
|
childBefore(pos) { return this.child(-1, pos, -2 /* Before */); }
|
|
1435
|
-
enter(pos, side,
|
|
1436
|
-
if (
|
|
773
|
+
enter(pos, side, mode = 0) {
|
|
774
|
+
if (mode & IterMode.ExcludeBuffers)
|
|
1437
775
|
return null;
|
|
1438
776
|
let { buffer } = this.context;
|
|
1439
777
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
|
|
@@ -1459,7 +797,7 @@ class BufferNode {
|
|
|
1459
797
|
return this.externalSibling(-1);
|
|
1460
798
|
return new BufferNode(this.context, this._parent, buffer.findChild(parentStart, this.index, -1, 0, 4 /* DontCare */));
|
|
1461
799
|
}
|
|
1462
|
-
|
|
800
|
+
cursor(mode = 0) { return new TreeCursor(this, mode); }
|
|
1463
801
|
get tree() { return null; }
|
|
1464
802
|
toTree() {
|
|
1465
803
|
let children = [], positions = [];
|
|
@@ -1470,7 +808,7 @@ class BufferNode {
|
|
|
1470
808
|
children.push(buffer.slice(startI, endI, from, to));
|
|
1471
809
|
positions.push(0);
|
|
1472
810
|
}
|
|
1473
|
-
return new
|
|
811
|
+
return new dist_Tree(this.type, children, positions, this.to - this.from);
|
|
1474
812
|
}
|
|
1475
813
|
resolve(pos, side = 0) {
|
|
1476
814
|
return resolveNode(this, pos, side, false);
|
|
@@ -1488,6 +826,8 @@ class BufferNode {
|
|
|
1488
826
|
getChildren(type, before = null, after = null) {
|
|
1489
827
|
return getChildren(this, type, before, after);
|
|
1490
828
|
}
|
|
829
|
+
get node() { return this; }
|
|
830
|
+
matchContext(context) { return matchNodeContext(this, context); }
|
|
1491
831
|
}
|
|
1492
832
|
/// A tree cursor object focuses on a given node in a syntax tree, and
|
|
1493
833
|
/// allows you to move to adjacent nodes.
|
|
@@ -1497,8 +837,10 @@ class TreeCursor {
|
|
|
1497
837
|
/// @internal
|
|
1498
838
|
mode = 0) {
|
|
1499
839
|
this.mode = mode;
|
|
840
|
+
/// @internal
|
|
1500
841
|
this.buffer = null;
|
|
1501
842
|
this.stack = [];
|
|
843
|
+
/// @internal
|
|
1502
844
|
this.index = 0;
|
|
1503
845
|
this.bufferNode = null;
|
|
1504
846
|
if (node instanceof TreeNode) {
|
|
@@ -1549,7 +891,7 @@ class TreeCursor {
|
|
|
1549
891
|
/// @internal
|
|
1550
892
|
enterChild(dir, pos, side) {
|
|
1551
893
|
if (!this.buffer)
|
|
1552
|
-
return this.yield(this._tree.nextChild(dir < 0 ? this._tree.
|
|
894
|
+
return this.yield(this._tree.nextChild(dir < 0 ? this._tree._tree.children.length - 1 : 0, dir, pos, side, this.mode));
|
|
1553
895
|
let { buffer } = this.buffer;
|
|
1554
896
|
let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.buffer.start, side);
|
|
1555
897
|
if (index < 0)
|
|
@@ -1571,18 +913,18 @@ class TreeCursor {
|
|
|
1571
913
|
/// will also enter [overlaid](#common.MountedTree.overlay)
|
|
1572
914
|
/// [mounted](#common.NodeProp^mounted) trees unless `overlays` is
|
|
1573
915
|
/// set to false.
|
|
1574
|
-
enter(pos, side,
|
|
916
|
+
enter(pos, side, mode = this.mode) {
|
|
1575
917
|
if (!this.buffer)
|
|
1576
|
-
return this.yield(this._tree.enter(pos, side,
|
|
1577
|
-
return
|
|
918
|
+
return this.yield(this._tree.enter(pos, side, mode));
|
|
919
|
+
return mode & IterMode.ExcludeBuffers ? false : this.enterChild(1, pos, side);
|
|
1578
920
|
}
|
|
1579
921
|
/// Move to the node's parent node, if this isn't the top node.
|
|
1580
922
|
parent() {
|
|
1581
923
|
if (!this.buffer)
|
|
1582
|
-
return this.yieldNode((this.mode &
|
|
924
|
+
return this.yieldNode((this.mode & IterMode.IncludeAnonymous) ? this._tree._parent : this._tree.parent);
|
|
1583
925
|
if (this.stack.length)
|
|
1584
926
|
return this.yieldBuf(this.stack.pop());
|
|
1585
|
-
let parent = (this.mode &
|
|
927
|
+
let parent = (this.mode & IterMode.IncludeAnonymous) ? this.buffer.parent : this.buffer.parent.nextSignificantParent();
|
|
1586
928
|
this.buffer = null;
|
|
1587
929
|
return this.yieldNode(parent);
|
|
1588
930
|
}
|
|
@@ -1628,9 +970,12 @@ class TreeCursor {
|
|
|
1628
970
|
}
|
|
1629
971
|
for (; parent; { index, _parent: parent } = parent) {
|
|
1630
972
|
if (index > -1)
|
|
1631
|
-
for (let i = index + dir, e = dir < 0 ? -1 : parent.
|
|
1632
|
-
let child = parent.
|
|
1633
|
-
if ((this.mode &
|
|
973
|
+
for (let i = index + dir, e = dir < 0 ? -1 : parent._tree.children.length; i != e; i += dir) {
|
|
974
|
+
let child = parent._tree.children[i];
|
|
975
|
+
if ((this.mode & IterMode.IncludeAnonymous) ||
|
|
976
|
+
child instanceof TreeBuffer ||
|
|
977
|
+
!child.type.isAnonymous ||
|
|
978
|
+
hasChild(child))
|
|
1634
979
|
return false;
|
|
1635
980
|
}
|
|
1636
981
|
}
|
|
@@ -1698,7 +1043,55 @@ class TreeCursor {
|
|
|
1698
1043
|
/// any. Will return null when the node is in a [tree
|
|
1699
1044
|
/// buffer](#common.TreeBuffer).
|
|
1700
1045
|
get tree() {
|
|
1701
|
-
return this.buffer ? null : this._tree.
|
|
1046
|
+
return this.buffer ? null : this._tree._tree;
|
|
1047
|
+
}
|
|
1048
|
+
/// Iterate over the current node and all its descendants, calling
|
|
1049
|
+
/// `enter` when entering a node and `leave`, if given, when leaving
|
|
1050
|
+
/// one. When `enter` returns `false`, any children of that node are
|
|
1051
|
+
/// skipped, and `leave` isn't called for it.
|
|
1052
|
+
iterate(enter, leave) {
|
|
1053
|
+
for (let depth = 0;;) {
|
|
1054
|
+
let mustLeave = false;
|
|
1055
|
+
if (this.type.isAnonymous || enter(this) !== false) {
|
|
1056
|
+
if (this.firstChild()) {
|
|
1057
|
+
depth++;
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
if (!this.type.isAnonymous)
|
|
1061
|
+
mustLeave = true;
|
|
1062
|
+
}
|
|
1063
|
+
for (;;) {
|
|
1064
|
+
if (mustLeave && leave)
|
|
1065
|
+
leave(this);
|
|
1066
|
+
mustLeave = this.type.isAnonymous;
|
|
1067
|
+
if (this.nextSibling())
|
|
1068
|
+
break;
|
|
1069
|
+
if (!depth)
|
|
1070
|
+
return;
|
|
1071
|
+
this.parent();
|
|
1072
|
+
depth--;
|
|
1073
|
+
mustLeave = true;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
/// Test whether the current node matches a given context—a sequence
|
|
1078
|
+
/// of direct parent node names. Empty strings in the context array
|
|
1079
|
+
/// are treated as wildcards.
|
|
1080
|
+
matchContext(context) {
|
|
1081
|
+
if (!this.buffer)
|
|
1082
|
+
return matchNodeContext(this.node, context);
|
|
1083
|
+
let { buffer } = this.buffer, { types } = buffer.set;
|
|
1084
|
+
for (let i = context.length - 1, d = this.stack.length - 1; i >= 0; d--) {
|
|
1085
|
+
if (d < 0)
|
|
1086
|
+
return matchNodeContext(this.node, context, i);
|
|
1087
|
+
let type = types[buffer.buffer[this.stack[d]]];
|
|
1088
|
+
if (!type.isAnonymous) {
|
|
1089
|
+
if (context[i] && context[i] != type.name)
|
|
1090
|
+
return false;
|
|
1091
|
+
i--;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return true;
|
|
1702
1095
|
}
|
|
1703
1096
|
}
|
|
1704
1097
|
function hasChild(tree) {
|
|
@@ -1781,7 +1174,7 @@ function buildTree(data) {
|
|
|
1781
1174
|
function makeBalanced(type) {
|
|
1782
1175
|
return (children, positions, length) => {
|
|
1783
1176
|
let lookAhead = 0, lastI = children.length - 1, last, lookAheadProp;
|
|
1784
|
-
if (lastI >= 0 && (last = children[lastI]) instanceof
|
|
1177
|
+
if (lastI >= 0 && (last = children[lastI]) instanceof dist_Tree) {
|
|
1785
1178
|
if (!lastI && last.type == type && last.length == length)
|
|
1786
1179
|
return last;
|
|
1787
1180
|
if (lookAheadProp = last.prop(dist_NodeProp.lookAhead))
|
|
@@ -1808,7 +1201,7 @@ function buildTree(data) {
|
|
|
1808
1201
|
let pair = [dist_NodeProp.lookAhead, lookAhead];
|
|
1809
1202
|
props = props ? [pair].concat(props) : [pair];
|
|
1810
1203
|
}
|
|
1811
|
-
return new
|
|
1204
|
+
return new dist_Tree(type, children, positions, length, props);
|
|
1812
1205
|
}
|
|
1813
1206
|
function findBufferSize(maxSize, inRepeat) {
|
|
1814
1207
|
// Scan through the buffer to find previous siblings that fit
|
|
@@ -1890,7 +1283,7 @@ function buildTree(data) {
|
|
|
1890
1283
|
while (cursor.pos > 0)
|
|
1891
1284
|
takeNode(data.start || 0, data.bufferStart || 0, children, positions, -1);
|
|
1892
1285
|
let length = (_a = data.length) !== null && _a !== void 0 ? _a : (children.length ? positions[0] + children[0].length : 0);
|
|
1893
|
-
return new
|
|
1286
|
+
return new dist_Tree(types[data.topID], children.reverse(), positions.reverse(), length);
|
|
1894
1287
|
}
|
|
1895
1288
|
const nodeSizeCache = new WeakMap;
|
|
1896
1289
|
function nodeSize(balanceType, node) {
|
|
@@ -1900,7 +1293,7 @@ function nodeSize(balanceType, node) {
|
|
|
1900
1293
|
if (size == null) {
|
|
1901
1294
|
size = 1;
|
|
1902
1295
|
for (let child of node.children) {
|
|
1903
|
-
if (child.type != balanceType || !(child instanceof
|
|
1296
|
+
if (child.type != balanceType || !(child instanceof dist_Tree)) {
|
|
1904
1297
|
size = 1;
|
|
1905
1298
|
break;
|
|
1906
1299
|
}
|
|
@@ -1958,6 +1351,48 @@ mkTree) {
|
|
|
1958
1351
|
divide(children, positions, from, to, 0);
|
|
1959
1352
|
return (mkTop || mkTree)(localChildren, localPositions, length);
|
|
1960
1353
|
}
|
|
1354
|
+
/// Provides a way to associate values with pieces of trees. As long
|
|
1355
|
+
/// as that part of the tree is reused, the associated values can be
|
|
1356
|
+
/// retrieved from an updated tree.
|
|
1357
|
+
class NodeWeakMap {
|
|
1358
|
+
constructor() {
|
|
1359
|
+
this.map = new WeakMap();
|
|
1360
|
+
}
|
|
1361
|
+
setBuffer(buffer, index, value) {
|
|
1362
|
+
let inner = this.map.get(buffer);
|
|
1363
|
+
if (!inner)
|
|
1364
|
+
this.map.set(buffer, inner = new Map);
|
|
1365
|
+
inner.set(index, value);
|
|
1366
|
+
}
|
|
1367
|
+
getBuffer(buffer, index) {
|
|
1368
|
+
let inner = this.map.get(buffer);
|
|
1369
|
+
return inner && inner.get(index);
|
|
1370
|
+
}
|
|
1371
|
+
/// Set the value for this syntax node.
|
|
1372
|
+
set(node, value) {
|
|
1373
|
+
if (node instanceof BufferNode)
|
|
1374
|
+
this.setBuffer(node.context.buffer, node.index, value);
|
|
1375
|
+
else if (node instanceof TreeNode)
|
|
1376
|
+
this.map.set(node.tree, value);
|
|
1377
|
+
}
|
|
1378
|
+
/// Retrieve value for this syntax node, if it exists in the map.
|
|
1379
|
+
get(node) {
|
|
1380
|
+
return node instanceof BufferNode ? this.getBuffer(node.context.buffer, node.index)
|
|
1381
|
+
: node instanceof TreeNode ? this.map.get(node.tree) : undefined;
|
|
1382
|
+
}
|
|
1383
|
+
/// Set the value for the node that a cursor currently points to.
|
|
1384
|
+
cursorSet(cursor, value) {
|
|
1385
|
+
if (cursor.buffer)
|
|
1386
|
+
this.setBuffer(cursor.buffer.buffer, cursor.index, value);
|
|
1387
|
+
else
|
|
1388
|
+
this.map.set(cursor.tree, value);
|
|
1389
|
+
}
|
|
1390
|
+
/// Retrieve the value for the node that a cursor currently points
|
|
1391
|
+
/// to.
|
|
1392
|
+
cursorGet(cursor) {
|
|
1393
|
+
return cursor.buffer ? this.getBuffer(cursor.buffer.buffer, cursor.index) : this.map.get(cursor.tree);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1961
1396
|
|
|
1962
1397
|
/// Tree fragments are used during [incremental
|
|
1963
1398
|
/// parsing](#common.Parser.startParse) to track parts of old trees
|
|
@@ -2042,7 +1477,7 @@ class TreeFragment {
|
|
|
2042
1477
|
}
|
|
2043
1478
|
}
|
|
2044
1479
|
/// A superclass that parsers should extend.
|
|
2045
|
-
class
|
|
1480
|
+
class dist_Parser {
|
|
2046
1481
|
/// Start a parse, returning a [partial parse](#common.PartialParse)
|
|
2047
1482
|
/// object. [`fragments`](#common.TreeFragment) can be passed in to
|
|
2048
1483
|
/// make the parse incremental.
|
|
@@ -2140,7 +1575,7 @@ class MixedParse {
|
|
|
2140
1575
|
if (this.innerDone == this.inner.length) {
|
|
2141
1576
|
let result = this.baseTree;
|
|
2142
1577
|
if (this.stoppedAt != null)
|
|
2143
|
-
result = new
|
|
1578
|
+
result = new dist_Tree(result.type, result.children, result.positions, result.length, result.propValues.concat([[stoppedInner, this.stoppedAt]]));
|
|
2144
1579
|
return result;
|
|
2145
1580
|
}
|
|
2146
1581
|
let inner = this.inner[this.innerDone], done = inner.parse.advance();
|
|
@@ -2178,7 +1613,7 @@ class MixedParse {
|
|
|
2178
1613
|
let fragmentCursor = new FragmentCursor(this.fragments);
|
|
2179
1614
|
let overlay = null;
|
|
2180
1615
|
let covered = null;
|
|
2181
|
-
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null),
|
|
1616
|
+
let cursor = new TreeCursor(new TreeNode(this.baseTree, this.ranges[0].from, 0, null), IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
|
|
2182
1617
|
scan: for (let nest, isCovered; this.stoppedAt == null || cursor.from < this.stoppedAt;) {
|
|
2183
1618
|
let enter = true, range;
|
|
2184
1619
|
if (fragmentCursor.hasNode(cursor)) {
|
|
@@ -2295,9 +1730,9 @@ function materialize(cursor) {
|
|
|
2295
1730
|
children.push(isTarget ? node.toTree() : split(i + 4, b[i + 3], buf.set.types[b[i]], from, to - from));
|
|
2296
1731
|
positions.push(from - innerOffset);
|
|
2297
1732
|
sliceBuf(buf, b[i + 3], endI, children, positions, innerOffset);
|
|
2298
|
-
return new
|
|
1733
|
+
return new dist_Tree(type, children, positions, length);
|
|
2299
1734
|
}
|
|
2300
|
-
base.children[i] = split(0, b.length,
|
|
1735
|
+
base.children[i] = split(0, b.length, dist_NodeType.none, 0, buf.length);
|
|
2301
1736
|
// Move the cursor back to the target node
|
|
2302
1737
|
for (let d = 0; d <= depth; d++)
|
|
2303
1738
|
cursor.childAfter(node.from);
|
|
@@ -2306,13 +1741,13 @@ class StructureCursor {
|
|
|
2306
1741
|
constructor(root, offset) {
|
|
2307
1742
|
this.offset = offset;
|
|
2308
1743
|
this.done = false;
|
|
2309
|
-
this.cursor = root.
|
|
1744
|
+
this.cursor = root.cursor(IterMode.IncludeAnonymous | IterMode.IgnoreMounts);
|
|
2310
1745
|
}
|
|
2311
1746
|
// Move to the first node (in pre-order) that starts at or after `pos`.
|
|
2312
1747
|
moveTo(pos) {
|
|
2313
1748
|
let { cursor } = this, p = pos - this.offset;
|
|
2314
1749
|
while (!this.done && cursor.from < p) {
|
|
2315
|
-
if (cursor.to >= pos && cursor.enter(p, 1,
|
|
1750
|
+
if (cursor.to >= pos && cursor.enter(p, 1, IterMode.IgnoreOverlays | IterMode.ExcludeBuffers)) ;
|
|
2316
1751
|
else if (!cursor.next(false))
|
|
2317
1752
|
this.done = true;
|
|
2318
1753
|
}
|
|
@@ -2323,7 +1758,7 @@ class StructureCursor {
|
|
|
2323
1758
|
for (let tree = this.cursor.tree;;) {
|
|
2324
1759
|
if (tree == cursor.tree)
|
|
2325
1760
|
return true;
|
|
2326
|
-
if (tree.children.length && tree.positions[0] == 0 && tree.children[0] instanceof
|
|
1761
|
+
if (tree.children.length && tree.positions[0] == 0 && tree.children[0] instanceof dist_Tree)
|
|
2327
1762
|
tree = tree.children[0];
|
|
2328
1763
|
else
|
|
2329
1764
|
break;
|
|
@@ -2478,25 +1913,836 @@ function enterFragments(mounts, ranges) {
|
|
|
2478
1913
|
|
|
2479
1914
|
|
|
2480
1915
|
|
|
2481
|
-
;// CONCATENATED MODULE: ./node_modules/@
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
1916
|
+
;// CONCATENATED MODULE: ./node_modules/@lezer/highlight/dist/index.js
|
|
2485
1917
|
|
|
2486
1918
|
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
1919
|
+
let nextTagID = 0;
|
|
1920
|
+
/// Highlighting tags are markers that denote a highlighting category.
|
|
1921
|
+
/// They are [associated](#highlight.styleTags) with parts of a syntax
|
|
1922
|
+
/// tree by a language mode, and then mapped to an actual CSS style by
|
|
1923
|
+
/// a [highlighter](#highlight.Highlighter).
|
|
1924
|
+
///
|
|
1925
|
+
/// Because syntax tree node types and highlight styles have to be
|
|
1926
|
+
/// able to talk the same language, CodeMirror uses a mostly _closed_
|
|
1927
|
+
/// [vocabulary](#highlight.tags) of syntax tags (as opposed to
|
|
1928
|
+
/// traditional open string-based systems, which make it hard for
|
|
1929
|
+
/// highlighting themes to cover all the tokens produced by the
|
|
1930
|
+
/// various languages).
|
|
1931
|
+
///
|
|
1932
|
+
/// It _is_ possible to [define](#highlight.Tag^define) your own
|
|
1933
|
+
/// highlighting tags for system-internal use (where you control both
|
|
1934
|
+
/// the language package and the highlighter), but such tags will not
|
|
1935
|
+
/// be picked up by regular highlighters (though you can derive them
|
|
1936
|
+
/// from standard tags to allow highlighters to fall back to those).
|
|
1937
|
+
class Tag {
|
|
1938
|
+
/// @internal
|
|
1939
|
+
constructor(
|
|
1940
|
+
/// The set of this tag and all its parent tags, starting with
|
|
1941
|
+
/// this one itself and sorted in order of decreasing specificity.
|
|
1942
|
+
set,
|
|
1943
|
+
/// The base unmodified tag that this one is based on, if it's
|
|
1944
|
+
/// modified @internal
|
|
1945
|
+
base,
|
|
1946
|
+
/// The modifiers applied to this.base @internal
|
|
1947
|
+
modified) {
|
|
1948
|
+
this.set = set;
|
|
1949
|
+
this.base = base;
|
|
1950
|
+
this.modified = modified;
|
|
1951
|
+
/// @internal
|
|
1952
|
+
this.id = nextTagID++;
|
|
1953
|
+
}
|
|
1954
|
+
/// Define a new tag. If `parent` is given, the tag is treated as a
|
|
1955
|
+
/// sub-tag of that parent, and
|
|
1956
|
+
/// [highlighters](#highlight.tagHighlighter) that don't mention
|
|
1957
|
+
/// this tag will try to fall back to the parent tag (or grandparent
|
|
1958
|
+
/// tag, etc).
|
|
1959
|
+
static define(parent) {
|
|
1960
|
+
if (parent === null || parent === void 0 ? void 0 : parent.base)
|
|
1961
|
+
throw new Error("Can not derive from a modified tag");
|
|
1962
|
+
let tag = new Tag([], null, []);
|
|
1963
|
+
tag.set.push(tag);
|
|
1964
|
+
if (parent)
|
|
1965
|
+
for (let t of parent.set)
|
|
1966
|
+
tag.set.push(t);
|
|
1967
|
+
return tag;
|
|
1968
|
+
}
|
|
1969
|
+
/// Define a tag _modifier_, which is a function that, given a tag,
|
|
1970
|
+
/// will return a tag that is a subtag of the original. Applying the
|
|
1971
|
+
/// same modifier to a twice tag will return the same value (`m1(t1)
|
|
1972
|
+
/// == m1(t1)`) and applying multiple modifiers will, regardless or
|
|
1973
|
+
/// order, produce the same tag (`m1(m2(t1)) == m2(m1(t1))`).
|
|
1974
|
+
///
|
|
1975
|
+
/// When multiple modifiers are applied to a given base tag, each
|
|
1976
|
+
/// smaller set of modifiers is registered as a parent, so that for
|
|
1977
|
+
/// example `m1(m2(m3(t1)))` is a subtype of `m1(m2(t1))`,
|
|
1978
|
+
/// `m1(m3(t1)`, and so on.
|
|
1979
|
+
static defineModifier() {
|
|
1980
|
+
let mod = new Modifier;
|
|
1981
|
+
return (tag) => {
|
|
1982
|
+
if (tag.modified.indexOf(mod) > -1)
|
|
1983
|
+
return tag;
|
|
1984
|
+
return Modifier.get(tag.base || tag, tag.modified.concat(mod).sort((a, b) => a.id - b.id));
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
let nextModifierID = 0;
|
|
1989
|
+
class Modifier {
|
|
1990
|
+
constructor() {
|
|
1991
|
+
this.instances = [];
|
|
1992
|
+
this.id = nextModifierID++;
|
|
1993
|
+
}
|
|
1994
|
+
static get(base, mods) {
|
|
1995
|
+
if (!mods.length)
|
|
1996
|
+
return base;
|
|
1997
|
+
let exists = mods[0].instances.find(t => t.base == base && sameArray(mods, t.modified));
|
|
1998
|
+
if (exists)
|
|
1999
|
+
return exists;
|
|
2000
|
+
let set = [], tag = new Tag(set, base, mods);
|
|
2001
|
+
for (let m of mods)
|
|
2002
|
+
m.instances.push(tag);
|
|
2003
|
+
let configs = permute(mods);
|
|
2004
|
+
for (let parent of base.set)
|
|
2005
|
+
for (let config of configs)
|
|
2006
|
+
set.push(Modifier.get(parent, config));
|
|
2007
|
+
return tag;
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
function sameArray(a, b) {
|
|
2011
|
+
return a.length == b.length && a.every((x, i) => x == b[i]);
|
|
2012
|
+
}
|
|
2013
|
+
function permute(array) {
|
|
2014
|
+
let result = [array];
|
|
2015
|
+
for (let i = 0; i < array.length; i++) {
|
|
2016
|
+
for (let a of permute(array.slice(0, i).concat(array.slice(i + 1))))
|
|
2017
|
+
result.push(a);
|
|
2018
|
+
}
|
|
2019
|
+
return result;
|
|
2020
|
+
}
|
|
2021
|
+
/// This function is used to add a set of tags to a language syntax
|
|
2022
|
+
/// via [`NodeSet.extend`](#common.NodeSet.extend) or
|
|
2023
|
+
/// [`LRParser.configure`](#lr.LRParser.configure).
|
|
2024
|
+
///
|
|
2025
|
+
/// The argument object maps node selectors to [highlighting
|
|
2026
|
+
/// tags](#highlight.Tag) or arrays of tags.
|
|
2027
|
+
///
|
|
2028
|
+
/// Node selectors may hold one or more (space-separated) node paths.
|
|
2029
|
+
/// Such a path can be a [node name](#common.NodeType.name), or
|
|
2030
|
+
/// multiple node names (or `*` wildcards) separated by slash
|
|
2031
|
+
/// characters, as in `"Block/Declaration/VariableName"`. Such a path
|
|
2032
|
+
/// matches the final node but only if its direct parent nodes are the
|
|
2033
|
+
/// other nodes mentioned. A `*` in such a path matches any parent,
|
|
2034
|
+
/// but only a single level—wildcards that match multiple parents
|
|
2035
|
+
/// aren't supported, both for efficiency reasons and because Lezer
|
|
2036
|
+
/// trees make it rather hard to reason about what they would match.)
|
|
2037
|
+
///
|
|
2038
|
+
/// A path can be ended with `/...` to indicate that the tag assigned
|
|
2039
|
+
/// to the node should also apply to all child nodes, even if they
|
|
2040
|
+
/// match their own style (by default, only the innermost style is
|
|
2041
|
+
/// used).
|
|
2042
|
+
///
|
|
2043
|
+
/// When a path ends in `!`, as in `Attribute!`, no further matching
|
|
2044
|
+
/// happens for the node's child nodes, and the entire node gets the
|
|
2045
|
+
/// given style.
|
|
2046
|
+
///
|
|
2047
|
+
/// In this notation, node names that contain `/`, `!`, `*`, or `...`
|
|
2048
|
+
/// must be quoted as JSON strings.
|
|
2049
|
+
///
|
|
2050
|
+
/// For example:
|
|
2051
|
+
///
|
|
2052
|
+
/// ```javascript
|
|
2053
|
+
/// parser.withProps(
|
|
2054
|
+
/// styleTags({
|
|
2055
|
+
/// // Style Number and BigNumber nodes
|
|
2056
|
+
/// "Number BigNumber": tags.number,
|
|
2057
|
+
/// // Style Escape nodes whose parent is String
|
|
2058
|
+
/// "String/Escape": tags.escape,
|
|
2059
|
+
/// // Style anything inside Attributes nodes
|
|
2060
|
+
/// "Attributes!": tags.meta,
|
|
2061
|
+
/// // Add a style to all content inside Italic nodes
|
|
2062
|
+
/// "Italic/...": tags.emphasis,
|
|
2063
|
+
/// // Style InvalidString nodes as both `string` and `invalid`
|
|
2064
|
+
/// "InvalidString": [tags.string, tags.invalid],
|
|
2065
|
+
/// // Style the node named "/" as punctuation
|
|
2066
|
+
/// '"/"': tags.punctuation
|
|
2067
|
+
/// })
|
|
2068
|
+
/// )
|
|
2069
|
+
/// ```
|
|
2070
|
+
function styleTags(spec) {
|
|
2071
|
+
let byName = Object.create(null);
|
|
2072
|
+
for (let prop in spec) {
|
|
2073
|
+
let tags = spec[prop];
|
|
2074
|
+
if (!Array.isArray(tags))
|
|
2075
|
+
tags = [tags];
|
|
2076
|
+
for (let part of prop.split(" "))
|
|
2077
|
+
if (part) {
|
|
2078
|
+
let pieces = [], mode = 2 /* Normal */, rest = part;
|
|
2079
|
+
for (let pos = 0;;) {
|
|
2080
|
+
if (rest == "..." && pos > 0 && pos + 3 == part.length) {
|
|
2081
|
+
mode = 1 /* Inherit */;
|
|
2082
|
+
break;
|
|
2083
|
+
}
|
|
2084
|
+
let m = /^"(?:[^"\\]|\\.)*?"|[^\/!]+/.exec(rest);
|
|
2085
|
+
if (!m)
|
|
2086
|
+
throw new RangeError("Invalid path: " + part);
|
|
2087
|
+
pieces.push(m[0] == "*" ? "" : m[0][0] == '"' ? JSON.parse(m[0]) : m[0]);
|
|
2088
|
+
pos += m[0].length;
|
|
2089
|
+
if (pos == part.length)
|
|
2090
|
+
break;
|
|
2091
|
+
let next = part[pos++];
|
|
2092
|
+
if (pos == part.length && next == "!") {
|
|
2093
|
+
mode = 0 /* Opaque */;
|
|
2094
|
+
break;
|
|
2095
|
+
}
|
|
2096
|
+
if (next != "/")
|
|
2097
|
+
throw new RangeError("Invalid path: " + part);
|
|
2098
|
+
rest = part.slice(pos);
|
|
2099
|
+
}
|
|
2100
|
+
let last = pieces.length - 1, inner = pieces[last];
|
|
2101
|
+
if (!inner)
|
|
2102
|
+
throw new RangeError("Invalid path: " + part);
|
|
2103
|
+
let rule = new Rule(tags, mode, last > 0 ? pieces.slice(0, last) : null);
|
|
2104
|
+
byName[inner] = rule.sort(byName[inner]);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
return ruleNodeProp.add(byName);
|
|
2108
|
+
}
|
|
2109
|
+
const ruleNodeProp = new dist_NodeProp();
|
|
2110
|
+
class Rule {
|
|
2111
|
+
constructor(tags, mode, context, next) {
|
|
2112
|
+
this.tags = tags;
|
|
2113
|
+
this.mode = mode;
|
|
2114
|
+
this.context = context;
|
|
2115
|
+
this.next = next;
|
|
2116
|
+
}
|
|
2117
|
+
sort(other) {
|
|
2118
|
+
if (!other || other.depth < this.depth) {
|
|
2119
|
+
this.next = other;
|
|
2120
|
+
return this;
|
|
2121
|
+
}
|
|
2122
|
+
other.next = this.sort(other.next);
|
|
2123
|
+
return other;
|
|
2124
|
+
}
|
|
2125
|
+
get depth() { return this.context ? this.context.length : 0; }
|
|
2126
|
+
}
|
|
2127
|
+
/// Define a [highlighter](#highlight.Highlighter) from an array of
|
|
2128
|
+
/// tag/class pairs. Classes associated with more specific tags will
|
|
2129
|
+
/// take precedence.
|
|
2130
|
+
function tagHighlighter(tags, options) {
|
|
2131
|
+
let map = Object.create(null);
|
|
2132
|
+
for (let style of tags) {
|
|
2133
|
+
if (!Array.isArray(style.tag))
|
|
2134
|
+
map[style.tag.id] = style.class;
|
|
2135
|
+
else
|
|
2136
|
+
for (let tag of style.tag)
|
|
2137
|
+
map[tag.id] = style.class;
|
|
2138
|
+
}
|
|
2139
|
+
let { scope, all = null } = options || {};
|
|
2140
|
+
return {
|
|
2141
|
+
style: (tags) => {
|
|
2142
|
+
let cls = all;
|
|
2143
|
+
for (let tag of tags) {
|
|
2144
|
+
for (let sub of tag.set) {
|
|
2145
|
+
let tagClass = map[sub.id];
|
|
2146
|
+
if (tagClass) {
|
|
2147
|
+
cls = cls ? cls + " " + tagClass : tagClass;
|
|
2148
|
+
break;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return cls;
|
|
2153
|
+
},
|
|
2154
|
+
scope: scope
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
function highlightTags(highlighters, tags) {
|
|
2158
|
+
let result = null;
|
|
2159
|
+
for (let highlighter of highlighters) {
|
|
2160
|
+
let value = highlighter.style(tags);
|
|
2161
|
+
if (value)
|
|
2162
|
+
result = result ? result + " " + value : value;
|
|
2163
|
+
}
|
|
2164
|
+
return result;
|
|
2165
|
+
}
|
|
2166
|
+
/// Highlight the given [tree](#common.Tree) with the given
|
|
2167
|
+
/// [highlighter](#highlight.Highlighter).
|
|
2168
|
+
function highlightTree(tree, highlighter,
|
|
2169
|
+
/// Assign styling to a region of the text. Will be called, in order
|
|
2170
|
+
/// of position, for any ranges where more than zero classes apply.
|
|
2171
|
+
/// `classes` is a space separated string of CSS classes.
|
|
2172
|
+
putStyle,
|
|
2173
|
+
/// The start of the range to highlight.
|
|
2174
|
+
from = 0,
|
|
2175
|
+
/// The end of the range.
|
|
2176
|
+
to = tree.length) {
|
|
2177
|
+
let builder = new HighlightBuilder(from, Array.isArray(highlighter) ? highlighter : [highlighter], putStyle);
|
|
2178
|
+
builder.highlightRange(tree.cursor(), from, to, "", builder.highlighters);
|
|
2179
|
+
builder.flush(to);
|
|
2180
|
+
}
|
|
2181
|
+
class HighlightBuilder {
|
|
2182
|
+
constructor(at, highlighters, span) {
|
|
2183
|
+
this.at = at;
|
|
2184
|
+
this.highlighters = highlighters;
|
|
2185
|
+
this.span = span;
|
|
2186
|
+
this.class = "";
|
|
2187
|
+
}
|
|
2188
|
+
startSpan(at, cls) {
|
|
2189
|
+
if (cls != this.class) {
|
|
2190
|
+
this.flush(at);
|
|
2191
|
+
if (at > this.at)
|
|
2192
|
+
this.at = at;
|
|
2193
|
+
this.class = cls;
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
flush(to) {
|
|
2197
|
+
if (to > this.at && this.class)
|
|
2198
|
+
this.span(this.at, to, this.class);
|
|
2199
|
+
}
|
|
2200
|
+
highlightRange(cursor, from, to, inheritedClass, highlighters) {
|
|
2201
|
+
let { type, from: start, to: end } = cursor;
|
|
2202
|
+
if (start >= to || end <= from)
|
|
2203
|
+
return;
|
|
2204
|
+
if (type.isTop)
|
|
2205
|
+
highlighters = this.highlighters.filter(h => !h.scope || h.scope(type));
|
|
2206
|
+
let cls = inheritedClass;
|
|
2207
|
+
let rule = type.prop(ruleNodeProp), opaque = false;
|
|
2208
|
+
while (rule) {
|
|
2209
|
+
if (!rule.context || cursor.matchContext(rule.context)) {
|
|
2210
|
+
let tagCls = highlightTags(highlighters, rule.tags);
|
|
2211
|
+
if (tagCls) {
|
|
2212
|
+
if (cls)
|
|
2213
|
+
cls += " ";
|
|
2214
|
+
cls += tagCls;
|
|
2215
|
+
if (rule.mode == 1 /* Inherit */)
|
|
2216
|
+
inheritedClass += (inheritedClass ? " " : "") + tagCls;
|
|
2217
|
+
else if (rule.mode == 0 /* Opaque */)
|
|
2218
|
+
opaque = true;
|
|
2219
|
+
}
|
|
2220
|
+
break;
|
|
2221
|
+
}
|
|
2222
|
+
rule = rule.next;
|
|
2223
|
+
}
|
|
2224
|
+
this.startSpan(cursor.from, cls);
|
|
2225
|
+
if (opaque)
|
|
2226
|
+
return;
|
|
2227
|
+
let mounted = cursor.tree && cursor.tree.prop(dist_NodeProp.mounted);
|
|
2228
|
+
if (mounted && mounted.overlay) {
|
|
2229
|
+
let inner = cursor.node.enter(mounted.overlay[0].from + start, 1);
|
|
2230
|
+
let innerHighlighters = this.highlighters.filter(h => !h.scope || h.scope(mounted.tree.type));
|
|
2231
|
+
let hasChild = cursor.firstChild();
|
|
2232
|
+
for (let i = 0, pos = start;; i++) {
|
|
2233
|
+
let next = i < mounted.overlay.length ? mounted.overlay[i] : null;
|
|
2234
|
+
let nextPos = next ? next.from + start : end;
|
|
2235
|
+
let rangeFrom = Math.max(from, pos), rangeTo = Math.min(to, nextPos);
|
|
2236
|
+
if (rangeFrom < rangeTo && hasChild) {
|
|
2237
|
+
while (cursor.from < rangeTo) {
|
|
2238
|
+
this.highlightRange(cursor, rangeFrom, rangeTo, inheritedClass, highlighters);
|
|
2239
|
+
this.startSpan(Math.min(to, cursor.to), cls);
|
|
2240
|
+
if (cursor.to >= nextPos || !cursor.nextSibling())
|
|
2241
|
+
break;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
if (!next || nextPos > to)
|
|
2245
|
+
break;
|
|
2246
|
+
pos = next.to + start;
|
|
2247
|
+
if (pos > from) {
|
|
2248
|
+
this.highlightRange(inner.cursor(), Math.max(from, next.from + start), Math.min(to, pos), inheritedClass, innerHighlighters);
|
|
2249
|
+
this.startSpan(pos, cls);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
if (hasChild)
|
|
2253
|
+
cursor.parent();
|
|
2254
|
+
}
|
|
2255
|
+
else if (cursor.firstChild()) {
|
|
2256
|
+
do {
|
|
2257
|
+
if (cursor.to <= from)
|
|
2258
|
+
continue;
|
|
2259
|
+
if (cursor.from >= to)
|
|
2260
|
+
break;
|
|
2261
|
+
this.highlightRange(cursor, from, to, inheritedClass, highlighters);
|
|
2262
|
+
this.startSpan(Math.min(to, cursor.to), cls);
|
|
2263
|
+
} while (cursor.nextSibling());
|
|
2264
|
+
cursor.parent();
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
const t = Tag.define;
|
|
2269
|
+
const comment = t(), dist_name = t(), typeName = t(dist_name), propertyName = t(dist_name), literal = t(), string = t(literal), number = t(literal), content = t(), heading = t(content), keyword = t(), operator = t(), punctuation = t(), bracket = t(punctuation), meta = t();
|
|
2270
|
+
/// The default set of highlighting [tags](#highlight.Tag).
|
|
2271
|
+
///
|
|
2272
|
+
/// This collection is heavily biased towards programming languages,
|
|
2273
|
+
/// and necessarily incomplete. A full ontology of syntactic
|
|
2274
|
+
/// constructs would fill a stack of books, and be impractical to
|
|
2275
|
+
/// write themes for. So try to make do with this set. If all else
|
|
2276
|
+
/// fails, [open an
|
|
2277
|
+
/// issue](https://github.com/codemirror/codemirror.next) to propose a
|
|
2278
|
+
/// new tag, or [define](#highlight.Tag^define) a local custom tag for
|
|
2279
|
+
/// your use case.
|
|
2280
|
+
///
|
|
2281
|
+
/// Note that it is not obligatory to always attach the most specific
|
|
2282
|
+
/// tag possible to an element—if your grammar can't easily
|
|
2283
|
+
/// distinguish a certain type of element (such as a local variable),
|
|
2284
|
+
/// it is okay to style it as its more general variant (a variable).
|
|
2285
|
+
///
|
|
2286
|
+
/// For tags that extend some parent tag, the documentation links to
|
|
2287
|
+
/// the parent.
|
|
2288
|
+
const tags = {
|
|
2289
|
+
/// A comment.
|
|
2290
|
+
comment,
|
|
2291
|
+
/// A line [comment](#highlight.tags.comment).
|
|
2292
|
+
lineComment: t(comment),
|
|
2293
|
+
/// A block [comment](#highlight.tags.comment).
|
|
2294
|
+
blockComment: t(comment),
|
|
2295
|
+
/// A documentation [comment](#highlight.tags.comment).
|
|
2296
|
+
docComment: t(comment),
|
|
2297
|
+
/// Any kind of identifier.
|
|
2298
|
+
name: dist_name,
|
|
2299
|
+
/// The [name](#highlight.tags.name) of a variable.
|
|
2300
|
+
variableName: t(dist_name),
|
|
2301
|
+
/// A type [name](#highlight.tags.name).
|
|
2302
|
+
typeName: typeName,
|
|
2303
|
+
/// A tag name (subtag of [`typeName`](#highlight.tags.typeName)).
|
|
2304
|
+
tagName: t(typeName),
|
|
2305
|
+
/// A property or field [name](#highlight.tags.name).
|
|
2306
|
+
propertyName: propertyName,
|
|
2307
|
+
/// An attribute name (subtag of [`propertyName`](#highlight.tags.propertyName)).
|
|
2308
|
+
attributeName: t(propertyName),
|
|
2309
|
+
/// The [name](#highlight.tags.name) of a class.
|
|
2310
|
+
className: t(dist_name),
|
|
2311
|
+
/// A label [name](#highlight.tags.name).
|
|
2312
|
+
labelName: t(dist_name),
|
|
2313
|
+
/// A namespace [name](#highlight.tags.name).
|
|
2314
|
+
namespace: t(dist_name),
|
|
2315
|
+
/// The [name](#highlight.tags.name) of a macro.
|
|
2316
|
+
macroName: t(dist_name),
|
|
2317
|
+
/// A literal value.
|
|
2318
|
+
literal,
|
|
2319
|
+
/// A string [literal](#highlight.tags.literal).
|
|
2320
|
+
string,
|
|
2321
|
+
/// A documentation [string](#highlight.tags.string).
|
|
2322
|
+
docString: t(string),
|
|
2323
|
+
/// A character literal (subtag of [string](#highlight.tags.string)).
|
|
2324
|
+
character: t(string),
|
|
2325
|
+
/// An attribute value (subtag of [string](#highlight.tags.string)).
|
|
2326
|
+
attributeValue: t(string),
|
|
2327
|
+
/// A number [literal](#highlight.tags.literal).
|
|
2328
|
+
number,
|
|
2329
|
+
/// An integer [number](#highlight.tags.number) literal.
|
|
2330
|
+
integer: t(number),
|
|
2331
|
+
/// A floating-point [number](#highlight.tags.number) literal.
|
|
2332
|
+
float: t(number),
|
|
2333
|
+
/// A boolean [literal](#highlight.tags.literal).
|
|
2334
|
+
bool: t(literal),
|
|
2335
|
+
/// Regular expression [literal](#highlight.tags.literal).
|
|
2336
|
+
regexp: t(literal),
|
|
2337
|
+
/// An escape [literal](#highlight.tags.literal), for example a
|
|
2338
|
+
/// backslash escape in a string.
|
|
2339
|
+
escape: t(literal),
|
|
2340
|
+
/// A color [literal](#highlight.tags.literal).
|
|
2341
|
+
color: t(literal),
|
|
2342
|
+
/// A URL [literal](#highlight.tags.literal).
|
|
2343
|
+
url: t(literal),
|
|
2344
|
+
/// A language keyword.
|
|
2345
|
+
keyword,
|
|
2346
|
+
/// The [keyword](#highlight.tags.keyword) for the self or this
|
|
2347
|
+
/// object.
|
|
2348
|
+
self: t(keyword),
|
|
2349
|
+
/// The [keyword](#highlight.tags.keyword) for null.
|
|
2350
|
+
null: t(keyword),
|
|
2351
|
+
/// A [keyword](#highlight.tags.keyword) denoting some atomic value.
|
|
2352
|
+
atom: t(keyword),
|
|
2353
|
+
/// A [keyword](#highlight.tags.keyword) that represents a unit.
|
|
2354
|
+
unit: t(keyword),
|
|
2355
|
+
/// A modifier [keyword](#highlight.tags.keyword).
|
|
2356
|
+
modifier: t(keyword),
|
|
2357
|
+
/// A [keyword](#highlight.tags.keyword) that acts as an operator.
|
|
2358
|
+
operatorKeyword: t(keyword),
|
|
2359
|
+
/// A control-flow related [keyword](#highlight.tags.keyword).
|
|
2360
|
+
controlKeyword: t(keyword),
|
|
2361
|
+
/// A [keyword](#highlight.tags.keyword) that defines something.
|
|
2362
|
+
definitionKeyword: t(keyword),
|
|
2363
|
+
/// A [keyword](#highlight.tags.keyword) related to defining or
|
|
2364
|
+
/// interfacing with modules.
|
|
2365
|
+
moduleKeyword: t(keyword),
|
|
2366
|
+
/// An operator.
|
|
2367
|
+
operator,
|
|
2368
|
+
/// An [operator](#highlight.tags.operator) that defines something.
|
|
2369
|
+
derefOperator: t(operator),
|
|
2370
|
+
/// Arithmetic-related [operator](#highlight.tags.operator).
|
|
2371
|
+
arithmeticOperator: t(operator),
|
|
2372
|
+
/// Logical [operator](#highlight.tags.operator).
|
|
2373
|
+
logicOperator: t(operator),
|
|
2374
|
+
/// Bit [operator](#highlight.tags.operator).
|
|
2375
|
+
bitwiseOperator: t(operator),
|
|
2376
|
+
/// Comparison [operator](#highlight.tags.operator).
|
|
2377
|
+
compareOperator: t(operator),
|
|
2378
|
+
/// [Operator](#highlight.tags.operator) that updates its operand.
|
|
2379
|
+
updateOperator: t(operator),
|
|
2380
|
+
/// [Operator](#highlight.tags.operator) that defines something.
|
|
2381
|
+
definitionOperator: t(operator),
|
|
2382
|
+
/// Type-related [operator](#highlight.tags.operator).
|
|
2383
|
+
typeOperator: t(operator),
|
|
2384
|
+
/// Control-flow [operator](#highlight.tags.operator).
|
|
2385
|
+
controlOperator: t(operator),
|
|
2386
|
+
/// Program or markup punctuation.
|
|
2387
|
+
punctuation,
|
|
2388
|
+
/// [Punctuation](#highlight.tags.punctuation) that separates
|
|
2389
|
+
/// things.
|
|
2390
|
+
separator: t(punctuation),
|
|
2391
|
+
/// Bracket-style [punctuation](#highlight.tags.punctuation).
|
|
2392
|
+
bracket,
|
|
2393
|
+
/// Angle [brackets](#highlight.tags.bracket) (usually `<` and `>`
|
|
2394
|
+
/// tokens).
|
|
2395
|
+
angleBracket: t(bracket),
|
|
2396
|
+
/// Square [brackets](#highlight.tags.bracket) (usually `[` and `]`
|
|
2397
|
+
/// tokens).
|
|
2398
|
+
squareBracket: t(bracket),
|
|
2399
|
+
/// Parentheses (usually `(` and `)` tokens). Subtag of
|
|
2400
|
+
/// [bracket](#highlight.tags.bracket).
|
|
2401
|
+
paren: t(bracket),
|
|
2402
|
+
/// Braces (usually `{` and `}` tokens). Subtag of
|
|
2403
|
+
/// [bracket](#highlight.tags.bracket).
|
|
2404
|
+
brace: t(bracket),
|
|
2405
|
+
/// Content, for example plain text in XML or markup documents.
|
|
2406
|
+
content,
|
|
2407
|
+
/// [Content](#highlight.tags.content) that represents a heading.
|
|
2408
|
+
heading,
|
|
2409
|
+
/// A level 1 [heading](#highlight.tags.heading).
|
|
2410
|
+
heading1: t(heading),
|
|
2411
|
+
/// A level 2 [heading](#highlight.tags.heading).
|
|
2412
|
+
heading2: t(heading),
|
|
2413
|
+
/// A level 3 [heading](#highlight.tags.heading).
|
|
2414
|
+
heading3: t(heading),
|
|
2415
|
+
/// A level 4 [heading](#highlight.tags.heading).
|
|
2416
|
+
heading4: t(heading),
|
|
2417
|
+
/// A level 5 [heading](#highlight.tags.heading).
|
|
2418
|
+
heading5: t(heading),
|
|
2419
|
+
/// A level 6 [heading](#highlight.tags.heading).
|
|
2420
|
+
heading6: t(heading),
|
|
2421
|
+
/// A prose separator (such as a horizontal rule).
|
|
2422
|
+
contentSeparator: t(content),
|
|
2423
|
+
/// [Content](#highlight.tags.content) that represents a list.
|
|
2424
|
+
list: t(content),
|
|
2425
|
+
/// [Content](#highlight.tags.content) that represents a quote.
|
|
2426
|
+
quote: t(content),
|
|
2427
|
+
/// [Content](#highlight.tags.content) that is emphasized.
|
|
2428
|
+
emphasis: t(content),
|
|
2429
|
+
/// [Content](#highlight.tags.content) that is styled strong.
|
|
2430
|
+
strong: t(content),
|
|
2431
|
+
/// [Content](#highlight.tags.content) that is part of a link.
|
|
2432
|
+
link: t(content),
|
|
2433
|
+
/// [Content](#highlight.tags.content) that is styled as code or
|
|
2434
|
+
/// monospace.
|
|
2435
|
+
monospace: t(content),
|
|
2436
|
+
/// [Content](#highlight.tags.content) that has a strike-through
|
|
2437
|
+
/// style.
|
|
2438
|
+
strikethrough: t(content),
|
|
2439
|
+
/// Inserted text in a change-tracking format.
|
|
2440
|
+
inserted: t(),
|
|
2441
|
+
/// Deleted text.
|
|
2442
|
+
deleted: t(),
|
|
2443
|
+
/// Changed text.
|
|
2444
|
+
changed: t(),
|
|
2445
|
+
/// An invalid or unsyntactic element.
|
|
2446
|
+
invalid: t(),
|
|
2447
|
+
/// Metadata or meta-instruction.
|
|
2448
|
+
meta,
|
|
2449
|
+
/// [Metadata](#highlight.tags.meta) that applies to the entire
|
|
2450
|
+
/// document.
|
|
2451
|
+
documentMeta: t(meta),
|
|
2452
|
+
/// [Metadata](#highlight.tags.meta) that annotates or adds
|
|
2453
|
+
/// attributes to a given syntactic element.
|
|
2454
|
+
annotation: t(meta),
|
|
2455
|
+
/// Processing instruction or preprocessor directive. Subtag of
|
|
2456
|
+
/// [meta](#highlight.tags.meta).
|
|
2457
|
+
processingInstruction: t(meta),
|
|
2458
|
+
/// [Modifier](#highlight.Tag^defineModifier) that indicates that a
|
|
2459
|
+
/// given element is being defined. Expected to be used with the
|
|
2460
|
+
/// various [name](#highlight.tags.name) tags.
|
|
2461
|
+
definition: Tag.defineModifier(),
|
|
2462
|
+
/// [Modifier](#highlight.Tag^defineModifier) that indicates that
|
|
2463
|
+
/// something is constant. Mostly expected to be used with
|
|
2464
|
+
/// [variable names](#highlight.tags.variableName).
|
|
2465
|
+
constant: Tag.defineModifier(),
|
|
2466
|
+
/// [Modifier](#highlight.Tag^defineModifier) used to indicate that
|
|
2467
|
+
/// a [variable](#highlight.tags.variableName) or [property
|
|
2468
|
+
/// name](#highlight.tags.propertyName) is being called or defined
|
|
2469
|
+
/// as a function.
|
|
2470
|
+
function: Tag.defineModifier(),
|
|
2471
|
+
/// [Modifier](#highlight.Tag^defineModifier) that can be applied to
|
|
2472
|
+
/// [names](#highlight.tags.name) to indicate that they belong to
|
|
2473
|
+
/// the language's standard environment.
|
|
2474
|
+
standard: Tag.defineModifier(),
|
|
2475
|
+
/// [Modifier](#highlight.Tag^defineModifier) that indicates a given
|
|
2476
|
+
/// [names](#highlight.tags.name) is local to some scope.
|
|
2477
|
+
local: Tag.defineModifier(),
|
|
2478
|
+
/// A generic variant [modifier](#highlight.Tag^defineModifier) that
|
|
2479
|
+
/// can be used to tag language-specific alternative variants of
|
|
2480
|
+
/// some common tag. It is recommended for themes to define special
|
|
2481
|
+
/// forms of at least the [string](#highlight.tags.string) and
|
|
2482
|
+
/// [variable name](#highlight.tags.variableName) tags, since those
|
|
2483
|
+
/// come up a lot.
|
|
2484
|
+
special: Tag.defineModifier()
|
|
2485
|
+
};
|
|
2486
|
+
/// This is a highlighter that adds stable, predictable classes to
|
|
2487
|
+
/// tokens, for styling with external CSS.
|
|
2488
|
+
///
|
|
2489
|
+
/// The following tags are mapped to their name prefixed with `"tok-"`
|
|
2490
|
+
/// (for example `"tok-comment"`):
|
|
2491
|
+
///
|
|
2492
|
+
/// * [`link`](#highlight.tags.link)
|
|
2493
|
+
/// * [`heading`](#highlight.tags.heading)
|
|
2494
|
+
/// * [`emphasis`](#highlight.tags.emphasis)
|
|
2495
|
+
/// * [`strong`](#highlight.tags.strong)
|
|
2496
|
+
/// * [`keyword`](#highlight.tags.keyword)
|
|
2497
|
+
/// * [`atom`](#highlight.tags.atom) [`bool`](#highlight.tags.bool)
|
|
2498
|
+
/// * [`url`](#highlight.tags.url)
|
|
2499
|
+
/// * [`labelName`](#highlight.tags.labelName)
|
|
2500
|
+
/// * [`inserted`](#highlight.tags.inserted)
|
|
2501
|
+
/// * [`deleted`](#highlight.tags.deleted)
|
|
2502
|
+
/// * [`literal`](#highlight.tags.literal)
|
|
2503
|
+
/// * [`string`](#highlight.tags.string)
|
|
2504
|
+
/// * [`number`](#highlight.tags.number)
|
|
2505
|
+
/// * [`variableName`](#highlight.tags.variableName)
|
|
2506
|
+
/// * [`typeName`](#highlight.tags.typeName)
|
|
2507
|
+
/// * [`namespace`](#highlight.tags.namespace)
|
|
2508
|
+
/// * [`className`](#highlight.tags.className)
|
|
2509
|
+
/// * [`macroName`](#highlight.tags.macroName)
|
|
2510
|
+
/// * [`propertyName`](#highlight.tags.propertyName)
|
|
2511
|
+
/// * [`operator`](#highlight.tags.operator)
|
|
2512
|
+
/// * [`comment`](#highlight.tags.comment)
|
|
2513
|
+
/// * [`meta`](#highlight.tags.meta)
|
|
2514
|
+
/// * [`punctuation`](#highlight.tags.punctuation)
|
|
2515
|
+
/// * [`invalid`](#highlight.tags.invalid)
|
|
2516
|
+
///
|
|
2517
|
+
/// In addition, these mappings are provided:
|
|
2518
|
+
///
|
|
2519
|
+
/// * [`regexp`](#highlight.tags.regexp),
|
|
2520
|
+
/// [`escape`](#highlight.tags.escape), and
|
|
2521
|
+
/// [`special`](#highlight.tags.special)[`(string)`](#highlight.tags.string)
|
|
2522
|
+
/// are mapped to `"tok-string2"`
|
|
2523
|
+
/// * [`special`](#highlight.tags.special)[`(variableName)`](#highlight.tags.variableName)
|
|
2524
|
+
/// to `"tok-variableName2"`
|
|
2525
|
+
/// * [`local`](#highlight.tags.local)[`(variableName)`](#highlight.tags.variableName)
|
|
2526
|
+
/// to `"tok-variableName tok-local"`
|
|
2527
|
+
/// * [`definition`](#highlight.tags.definition)[`(variableName)`](#highlight.tags.variableName)
|
|
2528
|
+
/// to `"tok-variableName tok-definition"`
|
|
2529
|
+
/// * [`definition`](#highlight.tags.definition)[`(propertyName)`](#highlight.tags.propertyName)
|
|
2530
|
+
/// to `"tok-propertyName tok-definition"`
|
|
2531
|
+
const classHighlighter = tagHighlighter([
|
|
2532
|
+
{ tag: tags.link, class: "tok-link" },
|
|
2533
|
+
{ tag: tags.heading, class: "tok-heading" },
|
|
2534
|
+
{ tag: tags.emphasis, class: "tok-emphasis" },
|
|
2535
|
+
{ tag: tags.strong, class: "tok-strong" },
|
|
2536
|
+
{ tag: tags.keyword, class: "tok-keyword" },
|
|
2537
|
+
{ tag: tags.atom, class: "tok-atom" },
|
|
2538
|
+
{ tag: tags.bool, class: "tok-bool" },
|
|
2539
|
+
{ tag: tags.url, class: "tok-url" },
|
|
2540
|
+
{ tag: tags.labelName, class: "tok-labelName" },
|
|
2541
|
+
{ tag: tags.inserted, class: "tok-inserted" },
|
|
2542
|
+
{ tag: tags.deleted, class: "tok-deleted" },
|
|
2543
|
+
{ tag: tags.literal, class: "tok-literal" },
|
|
2544
|
+
{ tag: tags.string, class: "tok-string" },
|
|
2545
|
+
{ tag: tags.number, class: "tok-number" },
|
|
2546
|
+
{ tag: [tags.regexp, tags.escape, tags.special(tags.string)], class: "tok-string2" },
|
|
2547
|
+
{ tag: tags.variableName, class: "tok-variableName" },
|
|
2548
|
+
{ tag: tags.local(tags.variableName), class: "tok-variableName tok-local" },
|
|
2549
|
+
{ tag: tags.definition(tags.variableName), class: "tok-variableName tok-definition" },
|
|
2550
|
+
{ tag: tags.special(tags.variableName), class: "tok-variableName2" },
|
|
2551
|
+
{ tag: tags.definition(tags.propertyName), class: "tok-propertyName tok-definition" },
|
|
2552
|
+
{ tag: tags.typeName, class: "tok-typeName" },
|
|
2553
|
+
{ tag: tags.namespace, class: "tok-namespace" },
|
|
2554
|
+
{ tag: tags.className, class: "tok-className" },
|
|
2555
|
+
{ tag: tags.macroName, class: "tok-macroName" },
|
|
2556
|
+
{ tag: tags.propertyName, class: "tok-propertyName" },
|
|
2557
|
+
{ tag: tags.operator, class: "tok-operator" },
|
|
2558
|
+
{ tag: tags.comment, class: "tok-comment" },
|
|
2559
|
+
{ tag: tags.meta, class: "tok-meta" },
|
|
2560
|
+
{ tag: tags.invalid, class: "tok-invalid" },
|
|
2561
|
+
{ tag: tags.punctuation, class: "tok-punctuation" }
|
|
2562
|
+
]);
|
|
2563
|
+
|
|
2564
|
+
|
|
2565
|
+
|
|
2566
|
+
;// CONCATENATED MODULE: ./node_modules/style-mod/src/style-mod.js
|
|
2567
|
+
const C = "\u037c"
|
|
2568
|
+
const COUNT = typeof Symbol == "undefined" ? "__" + C : Symbol.for(C)
|
|
2569
|
+
const SET = typeof Symbol == "undefined" ? "__styleSet" + Math.floor(Math.random() * 1e8) : Symbol("styleSet")
|
|
2570
|
+
const style_mod_top = typeof globalThis != "undefined" ? globalThis : typeof window != "undefined" ? window : {}
|
|
2571
|
+
|
|
2572
|
+
// :: - Style modules encapsulate a set of CSS rules defined from
|
|
2573
|
+
// JavaScript. Their definitions are only available in a given DOM
|
|
2574
|
+
// root after it has been _mounted_ there with `StyleModule.mount`.
|
|
2575
|
+
//
|
|
2576
|
+
// Style modules should be created once and stored somewhere, as
|
|
2577
|
+
// opposed to re-creating them every time you need them. The amount of
|
|
2578
|
+
// CSS rules generated for a given DOM root is bounded by the amount
|
|
2579
|
+
// of style modules that were used. So to avoid leaking rules, don't
|
|
2580
|
+
// create these dynamically, but treat them as one-time allocations.
|
|
2581
|
+
class StyleModule {
|
|
2582
|
+
// :: (Object<Style>, ?{finish: ?(string) → string})
|
|
2583
|
+
// Create a style module from the given spec.
|
|
2584
|
+
//
|
|
2585
|
+
// When `finish` is given, it is called on regular (non-`@`)
|
|
2586
|
+
// selectors (after `&` expansion) to compute the final selector.
|
|
2587
|
+
constructor(spec, options) {
|
|
2588
|
+
this.rules = []
|
|
2589
|
+
let {finish} = options || {}
|
|
2590
|
+
|
|
2591
|
+
function splitSelector(selector) {
|
|
2592
|
+
return /^@/.test(selector) ? [selector] : selector.split(/,\s*/)
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
function render(selectors, spec, target, isKeyframes) {
|
|
2596
|
+
let local = [], isAt = /^@(\w+)\b/.exec(selectors[0]), keyframes = isAt && isAt[1] == "keyframes"
|
|
2597
|
+
if (isAt && spec == null) return target.push(selectors[0] + ";")
|
|
2598
|
+
for (let prop in spec) {
|
|
2599
|
+
let value = spec[prop]
|
|
2600
|
+
if (/&/.test(prop)) {
|
|
2601
|
+
render(prop.split(/,\s*/).map(part => selectors.map(sel => part.replace(/&/, sel))).reduce((a, b) => a.concat(b)),
|
|
2602
|
+
value, target)
|
|
2603
|
+
} else if (value && typeof value == "object") {
|
|
2604
|
+
if (!isAt) throw new RangeError("The value of a property (" + prop + ") should be a primitive value.")
|
|
2605
|
+
render(splitSelector(prop), value, local, keyframes)
|
|
2606
|
+
} else if (value != null) {
|
|
2607
|
+
local.push(prop.replace(/_.*/, "").replace(/[A-Z]/g, l => "-" + l.toLowerCase()) + ": " + value + ";")
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
if (local.length || keyframes) {
|
|
2611
|
+
target.push((finish && !isAt && !isKeyframes ? selectors.map(finish) : selectors).join(", ") +
|
|
2612
|
+
" {" + local.join(" ") + "}")
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
for (let prop in spec) render(splitSelector(prop), spec[prop], this.rules)
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
// :: () → string
|
|
2620
|
+
// Returns a string containing the module's CSS rules.
|
|
2621
|
+
getRules() { return this.rules.join("\n") }
|
|
2622
|
+
|
|
2623
|
+
// :: () → string
|
|
2624
|
+
// Generate a new unique CSS class name.
|
|
2625
|
+
static newName() {
|
|
2626
|
+
let id = style_mod_top[COUNT] || 1
|
|
2627
|
+
style_mod_top[COUNT] = id + 1
|
|
2628
|
+
return C + id.toString(36)
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
// :: (union<Document, ShadowRoot>, union<[StyleModule], StyleModule>)
|
|
2632
|
+
//
|
|
2633
|
+
// Mount the given set of modules in the given DOM root, which ensures
|
|
2634
|
+
// that the CSS rules defined by the module are available in that
|
|
2635
|
+
// context.
|
|
2636
|
+
//
|
|
2637
|
+
// Rules are only added to the document once per root.
|
|
2638
|
+
//
|
|
2639
|
+
// Rule order will follow the order of the modules, so that rules from
|
|
2640
|
+
// modules later in the array take precedence of those from earlier
|
|
2641
|
+
// modules. If you call this function multiple times for the same root
|
|
2642
|
+
// in a way that changes the order of already mounted modules, the old
|
|
2643
|
+
// order will be changed.
|
|
2644
|
+
static mount(root, modules) {
|
|
2645
|
+
(root[SET] || new StyleSet(root)).mount(Array.isArray(modules) ? modules : [modules])
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
let adoptedSet = null
|
|
2650
|
+
|
|
2651
|
+
class StyleSet {
|
|
2652
|
+
constructor(root) {
|
|
2653
|
+
if (!root.head && root.adoptedStyleSheets && typeof CSSStyleSheet != "undefined") {
|
|
2654
|
+
if (adoptedSet) {
|
|
2655
|
+
root.adoptedStyleSheets = [adoptedSet.sheet].concat(root.adoptedStyleSheets)
|
|
2656
|
+
return root[SET] = adoptedSet
|
|
2657
|
+
}
|
|
2658
|
+
this.sheet = new CSSStyleSheet
|
|
2659
|
+
root.adoptedStyleSheets = [this.sheet].concat(root.adoptedStyleSheets)
|
|
2660
|
+
adoptedSet = this
|
|
2661
|
+
} else {
|
|
2662
|
+
this.styleTag = (root.ownerDocument || root).createElement("style")
|
|
2663
|
+
let target = root.head || root
|
|
2664
|
+
target.insertBefore(this.styleTag, target.firstChild)
|
|
2665
|
+
}
|
|
2666
|
+
this.modules = []
|
|
2667
|
+
root[SET] = this
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
mount(modules) {
|
|
2671
|
+
let sheet = this.sheet
|
|
2672
|
+
let pos = 0 /* Current rule offset */, j = 0 /* Index into this.modules */
|
|
2673
|
+
for (let i = 0; i < modules.length; i++) {
|
|
2674
|
+
let mod = modules[i], index = this.modules.indexOf(mod)
|
|
2675
|
+
if (index < j && index > -1) { // Ordering conflict
|
|
2676
|
+
this.modules.splice(index, 1)
|
|
2677
|
+
j--
|
|
2678
|
+
index = -1
|
|
2679
|
+
}
|
|
2680
|
+
if (index == -1) {
|
|
2681
|
+
this.modules.splice(j++, 0, mod)
|
|
2682
|
+
if (sheet) for (let k = 0; k < mod.rules.length; k++)
|
|
2683
|
+
sheet.insertRule(mod.rules[k], pos++)
|
|
2684
|
+
} else {
|
|
2685
|
+
while (j < index) pos += this.modules[j++].rules.length
|
|
2686
|
+
pos += mod.rules.length
|
|
2687
|
+
j++
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
if (!sheet) {
|
|
2692
|
+
let text = ""
|
|
2693
|
+
for (let i = 0; i < this.modules.length; i++)
|
|
2694
|
+
text += this.modules[i].getRules() + "\n"
|
|
2695
|
+
this.styleTag.textContent = text
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
// Style::Object<union<Style,string>>
|
|
2701
|
+
//
|
|
2702
|
+
// A style is an object that, in the simple case, maps CSS property
|
|
2703
|
+
// names to strings holding their values, as in `{color: "red",
|
|
2704
|
+
// fontWeight: "bold"}`. The property names can be given in
|
|
2705
|
+
// camel-case—the library will insert a dash before capital letters
|
|
2706
|
+
// when converting them to CSS.
|
|
2707
|
+
//
|
|
2708
|
+
// If you include an underscore in a property name, it and everything
|
|
2709
|
+
// after it will be removed from the output, which can be useful when
|
|
2710
|
+
// providing a property multiple times, for browser compatibility
|
|
2711
|
+
// reasons.
|
|
2712
|
+
//
|
|
2713
|
+
// A property in a style object can also be a sub-selector, which
|
|
2714
|
+
// extends the current context to add a pseudo-selector or a child
|
|
2715
|
+
// selector. Such a property should contain a `&` character, which
|
|
2716
|
+
// will be replaced by the current selector. For example `{"&:before":
|
|
2717
|
+
// {content: '"hi"'}}`. Sub-selectors and regular properties can
|
|
2718
|
+
// freely be mixed in a given object. Any property containing a `&` is
|
|
2719
|
+
// assumed to be a sub-selector.
|
|
2720
|
+
//
|
|
2721
|
+
// Finally, a property can specify an @-block to be wrapped around the
|
|
2722
|
+
// styles defined inside the object that's the property's value. For
|
|
2723
|
+
// example to create a media query you can do `{"@media screen and
|
|
2724
|
+
// (min-width: 400px)": {...}}`.
|
|
2725
|
+
|
|
2726
|
+
;// CONCATENATED MODULE: ./node_modules/@codemirror/language/dist/index.js
|
|
2727
|
+
|
|
2728
|
+
|
|
2729
|
+
|
|
2730
|
+
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
var _a;
|
|
2734
|
+
/**
|
|
2735
|
+
Node prop stored in a parser's top syntax node to provide the
|
|
2736
|
+
facet that stores language-specific data for that language.
|
|
2737
|
+
*/
|
|
2738
|
+
const languageDataProp = /*@__PURE__*/new dist_NodeProp();
|
|
2739
|
+
/**
|
|
2740
|
+
Helper function to define a facet (to be added to the top syntax
|
|
2741
|
+
node(s) for a language via
|
|
2742
|
+
[`languageDataProp`](https://codemirror.net/6/docs/ref/#language.languageDataProp)), that will be
|
|
2743
|
+
used to associate language data with the language. You
|
|
2744
|
+
probably only need this when subclassing
|
|
2745
|
+
[`Language`](https://codemirror.net/6/docs/ref/#language.Language).
|
|
2500
2746
|
*/
|
|
2501
2747
|
function defineLanguageFacet(baseData) {
|
|
2502
2748
|
return Facet.define({
|
|
@@ -2506,31 +2752,27 @@ function defineLanguageFacet(baseData) {
|
|
|
2506
2752
|
/**
|
|
2507
2753
|
A language object manages parsing and per-language
|
|
2508
2754
|
[metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
|
|
2509
|
-
managed as a [Lezer](https://lezer.codemirror.net) tree.
|
|
2510
|
-
|
|
2511
|
-
[
|
|
2512
|
-
[`StreamLanguage`](https://codemirror.net/6/docs/ref/#
|
|
2513
|
-
|
|
2755
|
+
managed as a [Lezer](https://lezer.codemirror.net) tree. The class
|
|
2756
|
+
can be used directly, via the [`LRLanguage`](https://codemirror.net/6/docs/ref/#language.LRLanguage)
|
|
2757
|
+
subclass for [Lezer](https://lezer.codemirror.net/) LR parsers, or
|
|
2758
|
+
via the [`StreamLanguage`](https://codemirror.net/6/docs/ref/#language.StreamLanguage) subclass
|
|
2759
|
+
for stream parsers.
|
|
2514
2760
|
*/
|
|
2515
2761
|
class Language {
|
|
2516
2762
|
/**
|
|
2517
|
-
Construct a language object.
|
|
2518
|
-
|
|
2519
|
-
[`defineLanguageFacet`](https://codemirror.net/6/docs/ref/#language.defineLanguageFacet)
|
|
2520
|
-
|
|
2763
|
+
Construct a language object. If you need to invoke this
|
|
2764
|
+
directly, first define a data facet with
|
|
2765
|
+
[`defineLanguageFacet`](https://codemirror.net/6/docs/ref/#language.defineLanguageFacet), and then
|
|
2766
|
+
configure your parser to [attach](https://codemirror.net/6/docs/ref/#language.languageDataProp) it
|
|
2767
|
+
to the language's outer syntax node.
|
|
2521
2768
|
*/
|
|
2522
2769
|
constructor(
|
|
2523
2770
|
/**
|
|
2524
|
-
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt)
|
|
2525
|
-
|
|
2526
|
-
*/
|
|
2527
|
-
data, parser,
|
|
2528
|
-
/**
|
|
2529
|
-
The node type of the top node of trees produced by this parser.
|
|
2771
|
+
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
|
|
2772
|
+
used for this language.
|
|
2530
2773
|
*/
|
|
2531
|
-
|
|
2774
|
+
data, parser, extraExtensions = []) {
|
|
2532
2775
|
this.data = data;
|
|
2533
|
-
this.topNode = topNode;
|
|
2534
2776
|
// Kludge to define EditorState.tree as a debugging helper,
|
|
2535
2777
|
// without the EditorState package actually knowing about
|
|
2536
2778
|
// languages and lezer trees.
|
|
@@ -2584,7 +2826,7 @@ class Language {
|
|
|
2584
2826
|
}
|
|
2585
2827
|
for (let i = 0; i < tree.children.length; i++) {
|
|
2586
2828
|
let ch = tree.children[i];
|
|
2587
|
-
if (ch instanceof
|
|
2829
|
+
if (ch instanceof dist_Tree)
|
|
2588
2830
|
explore(ch, tree.positions[i] + from);
|
|
2589
2831
|
}
|
|
2590
2832
|
};
|
|
@@ -2607,7 +2849,7 @@ function languageDataFacetAt(state, pos, side) {
|
|
|
2607
2849
|
return null;
|
|
2608
2850
|
let facet = topLang.data;
|
|
2609
2851
|
if (topLang.allowsNesting) {
|
|
2610
|
-
for (let node = dist_syntaxTree(state).topNode; node; node = node.enter(pos, side,
|
|
2852
|
+
for (let node = dist_syntaxTree(state).topNode; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
|
|
2611
2853
|
facet = node.type.prop(languageDataProp) || facet;
|
|
2612
2854
|
}
|
|
2613
2855
|
return facet;
|
|
@@ -2619,7 +2861,7 @@ parsers.
|
|
|
2619
2861
|
*/
|
|
2620
2862
|
class LRLanguage extends (/* unused pure expression or super */ null && (Language)) {
|
|
2621
2863
|
constructor(data, parser) {
|
|
2622
|
-
super(data, parser
|
|
2864
|
+
super(data, parser);
|
|
2623
2865
|
this.parser = parser;
|
|
2624
2866
|
}
|
|
2625
2867
|
/**
|
|
@@ -2638,16 +2880,17 @@ class LRLanguage extends (/* unused pure expression or super */ null && (Languag
|
|
|
2638
2880
|
configure(options) {
|
|
2639
2881
|
return new LRLanguage(this.data, this.parser.configure(options));
|
|
2640
2882
|
}
|
|
2641
|
-
get allowsNesting() { return this.parser.
|
|
2883
|
+
get allowsNesting() { return this.parser.hasWrappers(); }
|
|
2642
2884
|
}
|
|
2643
2885
|
/**
|
|
2644
2886
|
Get the syntax tree for a state, which is the current (possibly
|
|
2645
|
-
incomplete) parse tree of active
|
|
2646
|
-
or the empty tree if there is no
|
|
2887
|
+
incomplete) parse tree of the active
|
|
2888
|
+
[language](https://codemirror.net/6/docs/ref/#language.Language), or the empty tree if there is no
|
|
2889
|
+
language available.
|
|
2647
2890
|
*/
|
|
2648
2891
|
function dist_syntaxTree(state) {
|
|
2649
2892
|
let field = state.field(Language.state, false);
|
|
2650
|
-
return field ? field.tree :
|
|
2893
|
+
return field ? field.tree : dist_Tree.empty;
|
|
2651
2894
|
}
|
|
2652
2895
|
/**
|
|
2653
2896
|
Try to get a parse tree that spans at least up to `upto`. The
|
|
@@ -2664,7 +2907,7 @@ Queries whether there is a full syntax tree available up to the
|
|
|
2664
2907
|
given document position. If there isn't, the background parse
|
|
2665
2908
|
process _might_ still be working and update the tree further, but
|
|
2666
2909
|
there is no guarantee of that—the parser will [stop
|
|
2667
|
-
working](https://codemirror.net/6/docs/ref/#language.
|
|
2910
|
+
working](https://codemirror.net/6/docs/ref/#language.syntaxParserRunning) when it has spent a
|
|
2668
2911
|
certain amount of time or has moved beyond the visible viewport.
|
|
2669
2912
|
Always returns false if no language has been enabled.
|
|
2670
2913
|
*/
|
|
@@ -2673,6 +2916,18 @@ function syntaxTreeAvailable(state, upto = state.doc.length) {
|
|
|
2673
2916
|
return ((_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context.isDone(upto)) || false;
|
|
2674
2917
|
}
|
|
2675
2918
|
/**
|
|
2919
|
+
Move parsing forward, and update the editor state afterwards to
|
|
2920
|
+
reflect the new tree. Will work for at most `timeout`
|
|
2921
|
+
milliseconds. Returns true if the parser managed get to the given
|
|
2922
|
+
position in that time.
|
|
2923
|
+
*/
|
|
2924
|
+
function forceParsing(view, upto = view.viewport.to, timeout = 100) {
|
|
2925
|
+
let success = ensureSyntaxTree(view.state, upto, timeout);
|
|
2926
|
+
if (success != dist_syntaxTree(view.state))
|
|
2927
|
+
view.dispatch({});
|
|
2928
|
+
return !!success;
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2676
2931
|
Tells you whether the language parser is planning to do more
|
|
2677
2932
|
parsing work (in a `requestIdleCallback` pseudo-thread) or has
|
|
2678
2933
|
stopped running, either because it parsed the entire document,
|
|
@@ -2730,7 +2985,11 @@ class ParseContext {
|
|
|
2730
2985
|
/**
|
|
2731
2986
|
@internal
|
|
2732
2987
|
*/
|
|
2733
|
-
tree,
|
|
2988
|
+
tree,
|
|
2989
|
+
/**
|
|
2990
|
+
@internal
|
|
2991
|
+
*/
|
|
2992
|
+
treeLen,
|
|
2734
2993
|
/**
|
|
2735
2994
|
The current editor viewport (or some overapproximation
|
|
2736
2995
|
thereof). Intended to be used for opportunistically avoiding
|
|
@@ -2773,7 +3032,7 @@ class ParseContext {
|
|
|
2773
3032
|
work(until, upto) {
|
|
2774
3033
|
if (upto != null && upto >= this.state.doc.length)
|
|
2775
3034
|
upto = undefined;
|
|
2776
|
-
if (this.tree !=
|
|
3035
|
+
if (this.tree != dist_Tree.empty && this.isDone(upto !== null && upto !== void 0 ? upto : this.state.doc.length)) {
|
|
2777
3036
|
this.takeTree();
|
|
2778
3037
|
return true;
|
|
2779
3038
|
}
|
|
@@ -2845,7 +3104,7 @@ class ParseContext {
|
|
|
2845
3104
|
let ranges = [];
|
|
2846
3105
|
changes.iterChangedRanges((fromA, toA, fromB, toB) => ranges.push({ fromA, toA, fromB, toB }));
|
|
2847
3106
|
fragments = TreeFragment.applyChanges(fragments, ranges);
|
|
2848
|
-
tree =
|
|
3107
|
+
tree = dist_Tree.empty;
|
|
2849
3108
|
treeLen = 0;
|
|
2850
3109
|
viewport = { from: changes.mapPos(viewport.from, -1), to: changes.mapPos(viewport.to, 1) };
|
|
2851
3110
|
if (this.skipped.length) {
|
|
@@ -2906,7 +3165,7 @@ class ParseContext {
|
|
|
2906
3165
|
promise resolves.
|
|
2907
3166
|
*/
|
|
2908
3167
|
static getSkippingParser(until) {
|
|
2909
|
-
return new class extends
|
|
3168
|
+
return new class extends dist_Parser {
|
|
2910
3169
|
createParse(input, fragments, ranges) {
|
|
2911
3170
|
let from = ranges[0].from, to = ranges[ranges.length - 1].to;
|
|
2912
3171
|
let parser = {
|
|
@@ -2920,7 +3179,7 @@ class ParseContext {
|
|
|
2920
3179
|
cx.scheduleOn = cx.scheduleOn ? Promise.all([cx.scheduleOn, until]) : until;
|
|
2921
3180
|
}
|
|
2922
3181
|
this.parsedPos = to;
|
|
2923
|
-
return new
|
|
3182
|
+
return new dist_Tree(dist_NodeType.none, [], [], to - from);
|
|
2924
3183
|
},
|
|
2925
3184
|
stoppedAt: null,
|
|
2926
3185
|
stopAt() { }
|
|
@@ -2969,7 +3228,7 @@ class LanguageState {
|
|
|
2969
3228
|
}
|
|
2970
3229
|
static init(state) {
|
|
2971
3230
|
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
2972
|
-
let parseState = new ParseContext(state.facet(language).parser, state, [],
|
|
3231
|
+
let parseState = new ParseContext(state.facet(language).parser, state, [], dist_Tree.empty, 0, { from: 0, to: vpTo }, [], null);
|
|
2973
3232
|
if (!parseState.work(20 /* Apply */, vpTo))
|
|
2974
3233
|
parseState.takeTree();
|
|
2975
3234
|
return new LanguageState(parseState);
|
|
@@ -3083,7 +3342,7 @@ const language = /*@__PURE__*/state_.Facet.define({
|
|
|
3083
3342
|
enables: [Language.state, parseWorker]
|
|
3084
3343
|
});
|
|
3085
3344
|
/**
|
|
3086
|
-
This class bundles a [language
|
|
3345
|
+
This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
|
|
3087
3346
|
optional set of supporting extensions. Language packages are
|
|
3088
3347
|
encouraged to export a function that optionally takes a
|
|
3089
3348
|
configuration object and returns a `LanguageSupport` instance, as
|
|
@@ -3091,7 +3350,7 @@ the main way for client code to use the package.
|
|
|
3091
3350
|
*/
|
|
3092
3351
|
class LanguageSupport {
|
|
3093
3352
|
/**
|
|
3094
|
-
Create a support object.
|
|
3353
|
+
Create a language support object.
|
|
3095
3354
|
*/
|
|
3096
3355
|
constructor(
|
|
3097
3356
|
/**
|
|
@@ -3404,7 +3663,7 @@ function indentFrom(node, pos, base) {
|
|
|
3404
3663
|
function topIndent() { return 0; }
|
|
3405
3664
|
/**
|
|
3406
3665
|
Objects of this type provide context information and helper
|
|
3407
|
-
methods to indentation functions.
|
|
3666
|
+
methods to indentation functions registered on syntax nodes.
|
|
3408
3667
|
*/
|
|
3409
3668
|
class TreeIndentContext extends (/* unused pure expression or super */ null && (dist_IndentContext)) {
|
|
3410
3669
|
/**
|
|
@@ -3579,7 +3838,7 @@ the extent of a line, such a function should return a foldable
|
|
|
3579
3838
|
range that starts on that line (but continues beyond it), if one
|
|
3580
3839
|
can be found.
|
|
3581
3840
|
*/
|
|
3582
|
-
const foldService = /*@__PURE__*/
|
|
3841
|
+
const foldService = /*@__PURE__*/state_.Facet.define();
|
|
3583
3842
|
/**
|
|
3584
3843
|
This node prop is used to associate folding information with
|
|
3585
3844
|
syntax node types. Given a syntax node, it should check whether
|
|
@@ -3598,7 +3857,7 @@ function foldInside(node) {
|
|
|
3598
3857
|
}
|
|
3599
3858
|
function syntaxFolding(state, start, end) {
|
|
3600
3859
|
let tree = dist_syntaxTree(state);
|
|
3601
|
-
if (tree.length
|
|
3860
|
+
if (tree.length < end)
|
|
3602
3861
|
return null;
|
|
3603
3862
|
let inner = tree.resolveInner(end);
|
|
3604
3863
|
let found = null;
|
|
@@ -3636,116 +3895,1791 @@ function foldable(state, lineStart, lineEnd) {
|
|
|
3636
3895
|
}
|
|
3637
3896
|
return syntaxFolding(state, lineStart, lineEnd);
|
|
3638
3897
|
}
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
;// CONCATENATED MODULE: ./node_modules/@codemirror/commands/dist/index.js
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
function updateSel(sel, by) {
|
|
3651
|
-
return state_.EditorSelection.create(sel.ranges.map(by), sel.mainIndex);
|
|
3652
|
-
}
|
|
3653
|
-
function setSel(state, selection) {
|
|
3654
|
-
return state.update({ selection, scrollIntoView: true, userEvent: "select" });
|
|
3655
|
-
}
|
|
3656
|
-
function moveSel({ state, dispatch }, how) {
|
|
3657
|
-
let selection = updateSel(state.selection, how);
|
|
3658
|
-
if (selection.eq(state.selection))
|
|
3659
|
-
return false;
|
|
3660
|
-
dispatch(setSel(state, selection));
|
|
3661
|
-
return true;
|
|
3662
|
-
}
|
|
3663
|
-
function rangeEnd(range, forward) {
|
|
3664
|
-
return state_.EditorSelection.cursor(forward ? range.to : range.from);
|
|
3665
|
-
}
|
|
3666
|
-
function cursorByChar(view, forward) {
|
|
3667
|
-
return moveSel(view, range => range.empty ? view.moveByChar(range, forward) : rangeEnd(range, forward));
|
|
3898
|
+
function mapRange(range, mapping) {
|
|
3899
|
+
let from = mapping.mapPos(range.from, 1), to = mapping.mapPos(range.to, -1);
|
|
3900
|
+
return from >= to ? undefined : { from, to };
|
|
3668
3901
|
}
|
|
3669
3902
|
/**
|
|
3670
|
-
|
|
3671
|
-
|
|
3903
|
+
State effect that can be attached to a transaction to fold the
|
|
3904
|
+
given range. (You probably only need this in exceptional
|
|
3905
|
+
circumstances—usually you'll just want to let
|
|
3906
|
+
[`foldCode`](https://codemirror.net/6/docs/ref/#language.foldCode) and the [fold
|
|
3907
|
+
gutter](https://codemirror.net/6/docs/ref/#language.foldGutter) create the transactions.)
|
|
3672
3908
|
*/
|
|
3673
|
-
const
|
|
3909
|
+
const foldEffect = /*@__PURE__*/state_.StateEffect.define({ map: mapRange });
|
|
3674
3910
|
/**
|
|
3675
|
-
|
|
3911
|
+
State effect that unfolds the given range (if it was folded).
|
|
3676
3912
|
*/
|
|
3677
|
-
const
|
|
3913
|
+
const unfoldEffect = /*@__PURE__*/state_.StateEffect.define({ map: mapRange });
|
|
3914
|
+
function selectedLines(view) {
|
|
3915
|
+
let lines = [];
|
|
3916
|
+
for (let { head } of view.state.selection.ranges) {
|
|
3917
|
+
if (lines.some(l => l.from <= head && l.to >= head))
|
|
3918
|
+
continue;
|
|
3919
|
+
lines.push(view.lineBlockAt(head));
|
|
3920
|
+
}
|
|
3921
|
+
return lines;
|
|
3922
|
+
}
|
|
3923
|
+
const foldState = /*@__PURE__*/state_.StateField.define({
|
|
3924
|
+
create() {
|
|
3925
|
+
return view_.Decoration.none;
|
|
3926
|
+
},
|
|
3927
|
+
update(folded, tr) {
|
|
3928
|
+
folded = folded.map(tr.changes);
|
|
3929
|
+
for (let e of tr.effects) {
|
|
3930
|
+
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to))
|
|
3931
|
+
folded = folded.update({ add: [foldWidget.range(e.value.from, e.value.to)] });
|
|
3932
|
+
else if (e.is(unfoldEffect))
|
|
3933
|
+
folded = folded.update({ filter: (from, to) => e.value.from != from || e.value.to != to,
|
|
3934
|
+
filterFrom: e.value.from, filterTo: e.value.to });
|
|
3935
|
+
}
|
|
3936
|
+
// Clear folded ranges that cover the selection head
|
|
3937
|
+
if (tr.selection) {
|
|
3938
|
+
let onSelection = false, { head } = tr.selection.main;
|
|
3939
|
+
folded.between(head, head, (a, b) => { if (a < head && b > head)
|
|
3940
|
+
onSelection = true; });
|
|
3941
|
+
if (onSelection)
|
|
3942
|
+
folded = folded.update({
|
|
3943
|
+
filterFrom: head,
|
|
3944
|
+
filterTo: head,
|
|
3945
|
+
filter: (a, b) => b <= head || a >= head
|
|
3946
|
+
});
|
|
3947
|
+
}
|
|
3948
|
+
return folded;
|
|
3949
|
+
},
|
|
3950
|
+
provide: f => view_.EditorView.decorations.from(f)
|
|
3951
|
+
});
|
|
3678
3952
|
/**
|
|
3679
|
-
|
|
3953
|
+
Get a [range set](https://codemirror.net/6/docs/ref/#state.RangeSet) containing the folded ranges
|
|
3954
|
+
in the given state.
|
|
3680
3955
|
*/
|
|
3681
|
-
|
|
3956
|
+
function foldedRanges(state) {
|
|
3957
|
+
return state.field(foldState, false) || RangeSet.empty;
|
|
3958
|
+
}
|
|
3959
|
+
function findFold(state, from, to) {
|
|
3960
|
+
var _a;
|
|
3961
|
+
let found = null;
|
|
3962
|
+
(_a = state.field(foldState, false)) === null || _a === void 0 ? void 0 : _a.between(from, to, (from, to) => {
|
|
3963
|
+
if (!found || found.from > from)
|
|
3964
|
+
found = { from, to };
|
|
3965
|
+
});
|
|
3966
|
+
return found;
|
|
3967
|
+
}
|
|
3968
|
+
function foldExists(folded, from, to) {
|
|
3969
|
+
let found = false;
|
|
3970
|
+
folded.between(from, from, (a, b) => { if (a == from && b == to)
|
|
3971
|
+
found = true; });
|
|
3972
|
+
return found;
|
|
3973
|
+
}
|
|
3974
|
+
function maybeEnable(state, other) {
|
|
3975
|
+
return state.field(foldState, false) ? other : other.concat(state_.StateEffect.appendConfig.of(codeFolding()));
|
|
3976
|
+
}
|
|
3682
3977
|
/**
|
|
3683
|
-
|
|
3978
|
+
Fold the lines that are selected, if possible.
|
|
3684
3979
|
*/
|
|
3685
|
-
const
|
|
3686
|
-
|
|
3687
|
-
|
|
3980
|
+
const foldCode = view => {
|
|
3981
|
+
for (let line of selectedLines(view)) {
|
|
3982
|
+
let range = foldable(view.state, line.from, line.to);
|
|
3983
|
+
if (range) {
|
|
3984
|
+
view.dispatch({ effects: maybeEnable(view.state, [foldEffect.of(range), announceFold(view, range)]) });
|
|
3985
|
+
return true;
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3988
|
+
return false;
|
|
3989
|
+
};
|
|
3990
|
+
/**
|
|
3991
|
+
Unfold folded ranges on selected lines.
|
|
3992
|
+
*/
|
|
3993
|
+
const unfoldCode = view => {
|
|
3994
|
+
if (!view.state.field(foldState, false))
|
|
3995
|
+
return false;
|
|
3996
|
+
let effects = [];
|
|
3997
|
+
for (let line of selectedLines(view)) {
|
|
3998
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
3999
|
+
if (folded)
|
|
4000
|
+
effects.push(unfoldEffect.of(folded), announceFold(view, folded, false));
|
|
4001
|
+
}
|
|
4002
|
+
if (effects.length)
|
|
4003
|
+
view.dispatch({ effects });
|
|
4004
|
+
return effects.length > 0;
|
|
4005
|
+
};
|
|
4006
|
+
function announceFold(view, range, fold = true) {
|
|
4007
|
+
let lineFrom = view.state.doc.lineAt(range.from).number, lineTo = view.state.doc.lineAt(range.to).number;
|
|
4008
|
+
return view_.EditorView.announce.of(`${view.state.phrase(fold ? "Folded lines" : "Unfolded lines")} ${lineFrom} ${view.state.phrase("to")} ${lineTo}.`);
|
|
3688
4009
|
}
|
|
3689
4010
|
/**
|
|
3690
|
-
|
|
3691
|
-
|
|
4011
|
+
Fold all top-level foldable ranges. Note that, in most cases,
|
|
4012
|
+
folding information will depend on the [syntax
|
|
4013
|
+
tree](https://codemirror.net/6/docs/ref/#language.syntaxTree), and folding everything may not work
|
|
4014
|
+
reliably when the document hasn't been fully parsed (either
|
|
4015
|
+
because the editor state was only just initialized, or because the
|
|
4016
|
+
document is so big that the parser decided not to parse it
|
|
4017
|
+
entirely).
|
|
3692
4018
|
*/
|
|
3693
|
-
const
|
|
4019
|
+
const foldAll = view => {
|
|
4020
|
+
let { state } = view, effects = [];
|
|
4021
|
+
for (let pos = 0; pos < state.doc.length;) {
|
|
4022
|
+
let line = view.lineBlockAt(pos), range = foldable(state, line.from, line.to);
|
|
4023
|
+
if (range)
|
|
4024
|
+
effects.push(foldEffect.of(range));
|
|
4025
|
+
pos = (range ? view.lineBlockAt(range.to) : line).to + 1;
|
|
4026
|
+
}
|
|
4027
|
+
if (effects.length)
|
|
4028
|
+
view.dispatch({ effects: maybeEnable(view.state, effects) });
|
|
4029
|
+
return !!effects.length;
|
|
4030
|
+
};
|
|
3694
4031
|
/**
|
|
3695
|
-
|
|
4032
|
+
Unfold all folded code.
|
|
3696
4033
|
*/
|
|
3697
|
-
const
|
|
4034
|
+
const unfoldAll = view => {
|
|
4035
|
+
let field = view.state.field(foldState, false);
|
|
4036
|
+
if (!field || !field.size)
|
|
4037
|
+
return false;
|
|
4038
|
+
let effects = [];
|
|
4039
|
+
field.between(0, view.state.doc.length, (from, to) => { effects.push(unfoldEffect.of({ from, to })); });
|
|
4040
|
+
view.dispatch({ effects });
|
|
4041
|
+
return true;
|
|
4042
|
+
};
|
|
3698
4043
|
/**
|
|
3699
|
-
|
|
4044
|
+
Default fold-related key bindings.
|
|
4045
|
+
|
|
4046
|
+
- Ctrl-Shift-[ (Cmd-Alt-[ on macOS): [`foldCode`](https://codemirror.net/6/docs/ref/#language.foldCode).
|
|
4047
|
+
- Ctrl-Shift-] (Cmd-Alt-] on macOS): [`unfoldCode`](https://codemirror.net/6/docs/ref/#language.unfoldCode).
|
|
4048
|
+
- Ctrl-Alt-[: [`foldAll`](https://codemirror.net/6/docs/ref/#language.foldAll).
|
|
4049
|
+
- Ctrl-Alt-]: [`unfoldAll`](https://codemirror.net/6/docs/ref/#language.unfoldAll).
|
|
3700
4050
|
*/
|
|
3701
|
-
const
|
|
4051
|
+
const foldKeymap = [
|
|
4052
|
+
{ key: "Ctrl-Shift-[", mac: "Cmd-Alt-[", run: foldCode },
|
|
4053
|
+
{ key: "Ctrl-Shift-]", mac: "Cmd-Alt-]", run: unfoldCode },
|
|
4054
|
+
{ key: "Ctrl-Alt-[", run: foldAll },
|
|
4055
|
+
{ key: "Ctrl-Alt-]", run: unfoldAll }
|
|
4056
|
+
];
|
|
4057
|
+
const defaultConfig = {
|
|
4058
|
+
placeholderDOM: null,
|
|
4059
|
+
placeholderText: "…"
|
|
4060
|
+
};
|
|
4061
|
+
const foldConfig = /*@__PURE__*/state_.Facet.define({
|
|
4062
|
+
combine(values) { return (0,state_.combineConfig)(values, defaultConfig); }
|
|
4063
|
+
});
|
|
3702
4064
|
/**
|
|
3703
|
-
|
|
4065
|
+
Create an extension that configures code folding.
|
|
3704
4066
|
*/
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
let done = false, sawUpper = false, sawLower = false;
|
|
3711
|
-
let step = (next) => {
|
|
3712
|
-
if (done)
|
|
3713
|
-
return false;
|
|
3714
|
-
pos += forward ? next.length : -next.length;
|
|
3715
|
-
let nextCat = categorize(next), ahead;
|
|
3716
|
-
if (cat == CharCategory.Space)
|
|
3717
|
-
cat = nextCat;
|
|
3718
|
-
if (cat != nextCat)
|
|
3719
|
-
return false;
|
|
3720
|
-
if (cat == CharCategory.Word) {
|
|
3721
|
-
if (next.toLowerCase() == next) {
|
|
3722
|
-
if (!forward && sawUpper)
|
|
3723
|
-
return false;
|
|
3724
|
-
sawLower = true;
|
|
3725
|
-
}
|
|
3726
|
-
else if (sawLower) {
|
|
3727
|
-
if (forward)
|
|
3728
|
-
return false;
|
|
3729
|
-
done = true;
|
|
3730
|
-
}
|
|
3731
|
-
else {
|
|
3732
|
-
if (sawUpper && forward && categorize(ahead = view.state.sliceDoc(pos, pos + 1)) == CharCategory.Word &&
|
|
3733
|
-
ahead.toLowerCase() == ahead)
|
|
3734
|
-
return false;
|
|
3735
|
-
sawUpper = true;
|
|
3736
|
-
}
|
|
3737
|
-
}
|
|
3738
|
-
return true;
|
|
3739
|
-
};
|
|
3740
|
-
step(start);
|
|
3741
|
-
return step;
|
|
3742
|
-
});
|
|
4067
|
+
function codeFolding(config) {
|
|
4068
|
+
let result = [foldState, baseTheme$1];
|
|
4069
|
+
if (config)
|
|
4070
|
+
result.push(foldConfig.of(config));
|
|
4071
|
+
return result;
|
|
3743
4072
|
}
|
|
3744
|
-
|
|
3745
|
-
|
|
4073
|
+
const foldWidget = /*@__PURE__*/view_.Decoration.replace({ widget: /*@__PURE__*/new class extends view_.WidgetType {
|
|
4074
|
+
toDOM(view) {
|
|
4075
|
+
let { state } = view, conf = state.facet(foldConfig);
|
|
4076
|
+
let onclick = (event) => {
|
|
4077
|
+
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
4078
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
4079
|
+
if (folded)
|
|
4080
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
4081
|
+
event.preventDefault();
|
|
4082
|
+
};
|
|
4083
|
+
if (conf.placeholderDOM)
|
|
4084
|
+
return conf.placeholderDOM(view, onclick);
|
|
4085
|
+
let element = document.createElement("span");
|
|
4086
|
+
element.textContent = conf.placeholderText;
|
|
4087
|
+
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
4088
|
+
element.title = state.phrase("unfold");
|
|
4089
|
+
element.className = "cm-foldPlaceholder";
|
|
4090
|
+
element.onclick = onclick;
|
|
4091
|
+
return element;
|
|
4092
|
+
}
|
|
4093
|
+
} });
|
|
4094
|
+
const foldGutterDefaults = {
|
|
4095
|
+
openText: "⌄",
|
|
4096
|
+
closedText: "›",
|
|
4097
|
+
markerDOM: null,
|
|
4098
|
+
domEventHandlers: {},
|
|
4099
|
+
};
|
|
4100
|
+
class FoldMarker extends (/* unused pure expression or super */ null && (GutterMarker)) {
|
|
4101
|
+
constructor(config, open) {
|
|
4102
|
+
super();
|
|
4103
|
+
this.config = config;
|
|
4104
|
+
this.open = open;
|
|
4105
|
+
}
|
|
4106
|
+
eq(other) { return this.config == other.config && this.open == other.open; }
|
|
4107
|
+
toDOM(view) {
|
|
4108
|
+
if (this.config.markerDOM)
|
|
4109
|
+
return this.config.markerDOM(this.open);
|
|
4110
|
+
let span = document.createElement("span");
|
|
4111
|
+
span.textContent = this.open ? this.config.openText : this.config.closedText;
|
|
4112
|
+
span.title = view.state.phrase(this.open ? "Fold line" : "Unfold line");
|
|
4113
|
+
return span;
|
|
4114
|
+
}
|
|
3746
4115
|
}
|
|
3747
4116
|
/**
|
|
3748
|
-
|
|
4117
|
+
Create an extension that registers a fold gutter, which shows a
|
|
4118
|
+
fold status indicator before foldable lines (which can be clicked
|
|
4119
|
+
to fold or unfold the line).
|
|
4120
|
+
*/
|
|
4121
|
+
function foldGutter(config = {}) {
|
|
4122
|
+
let fullConfig = Object.assign(Object.assign({}, foldGutterDefaults), config);
|
|
4123
|
+
let canFold = new FoldMarker(fullConfig, true), canUnfold = new FoldMarker(fullConfig, false);
|
|
4124
|
+
let markers = ViewPlugin.fromClass(class {
|
|
4125
|
+
constructor(view) {
|
|
4126
|
+
this.from = view.viewport.from;
|
|
4127
|
+
this.markers = this.buildMarkers(view);
|
|
4128
|
+
}
|
|
4129
|
+
update(update) {
|
|
4130
|
+
if (update.docChanged || update.viewportChanged ||
|
|
4131
|
+
update.startState.facet(language) != update.state.facet(language) ||
|
|
4132
|
+
update.startState.field(foldState, false) != update.state.field(foldState, false) ||
|
|
4133
|
+
dist_syntaxTree(update.startState) != dist_syntaxTree(update.state))
|
|
4134
|
+
this.markers = this.buildMarkers(update.view);
|
|
4135
|
+
}
|
|
4136
|
+
buildMarkers(view) {
|
|
4137
|
+
let builder = new RangeSetBuilder();
|
|
4138
|
+
for (let line of view.viewportLineBlocks) {
|
|
4139
|
+
let mark = findFold(view.state, line.from, line.to) ? canUnfold
|
|
4140
|
+
: foldable(view.state, line.from, line.to) ? canFold : null;
|
|
4141
|
+
if (mark)
|
|
4142
|
+
builder.add(line.from, line.from, mark);
|
|
4143
|
+
}
|
|
4144
|
+
return builder.finish();
|
|
4145
|
+
}
|
|
4146
|
+
});
|
|
4147
|
+
let { domEventHandlers } = fullConfig;
|
|
4148
|
+
return [
|
|
4149
|
+
markers,
|
|
4150
|
+
gutter({
|
|
4151
|
+
class: "cm-foldGutter",
|
|
4152
|
+
markers(view) { var _a; return ((_a = view.plugin(markers)) === null || _a === void 0 ? void 0 : _a.markers) || RangeSet.empty; },
|
|
4153
|
+
initialSpacer() {
|
|
4154
|
+
return new FoldMarker(fullConfig, false);
|
|
4155
|
+
},
|
|
4156
|
+
domEventHandlers: Object.assign(Object.assign({}, domEventHandlers), { click: (view, line, event) => {
|
|
4157
|
+
if (domEventHandlers.click && domEventHandlers.click(view, line, event))
|
|
4158
|
+
return true;
|
|
4159
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
4160
|
+
if (folded) {
|
|
4161
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
4162
|
+
return true;
|
|
4163
|
+
}
|
|
4164
|
+
let range = foldable(view.state, line.from, line.to);
|
|
4165
|
+
if (range) {
|
|
4166
|
+
view.dispatch({ effects: foldEffect.of(range) });
|
|
4167
|
+
return true;
|
|
4168
|
+
}
|
|
4169
|
+
return false;
|
|
4170
|
+
} })
|
|
4171
|
+
}),
|
|
4172
|
+
codeFolding()
|
|
4173
|
+
];
|
|
4174
|
+
}
|
|
4175
|
+
const baseTheme$1 = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
4176
|
+
".cm-foldPlaceholder": {
|
|
4177
|
+
backgroundColor: "#eee",
|
|
4178
|
+
border: "1px solid #ddd",
|
|
4179
|
+
color: "#888",
|
|
4180
|
+
borderRadius: ".2em",
|
|
4181
|
+
margin: "0 1px",
|
|
4182
|
+
padding: "0 1px",
|
|
4183
|
+
cursor: "pointer"
|
|
4184
|
+
},
|
|
4185
|
+
".cm-foldGutter span": {
|
|
4186
|
+
padding: "0 1px",
|
|
4187
|
+
cursor: "pointer"
|
|
4188
|
+
}
|
|
4189
|
+
});
|
|
4190
|
+
|
|
4191
|
+
/**
|
|
4192
|
+
A highlight style associates CSS styles with higlighting
|
|
4193
|
+
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
|
4194
|
+
*/
|
|
4195
|
+
class HighlightStyle {
|
|
4196
|
+
constructor(spec, options) {
|
|
4197
|
+
let modSpec;
|
|
4198
|
+
function def(spec) {
|
|
4199
|
+
let cls = StyleModule.newName();
|
|
4200
|
+
(modSpec || (modSpec = Object.create(null)))["." + cls] = spec;
|
|
4201
|
+
return cls;
|
|
4202
|
+
}
|
|
4203
|
+
const scopeOpt = options.scope;
|
|
4204
|
+
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
|
4205
|
+
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
|
4206
|
+
this.style = tagHighlighter(spec.map(style => ({
|
|
4207
|
+
tag: style.tag,
|
|
4208
|
+
class: style.class || def(Object.assign({}, style, { tag: null }))
|
|
4209
|
+
})), {
|
|
4210
|
+
all: typeof options.all == "string" ? options.all : options.all ? def(options.all) : undefined,
|
|
4211
|
+
}).style;
|
|
4212
|
+
this.module = modSpec ? new StyleModule(modSpec) : null;
|
|
4213
|
+
this.themeType = options.themeType;
|
|
4214
|
+
}
|
|
4215
|
+
/**
|
|
4216
|
+
Create a highlighter style that associates the given styles to
|
|
4217
|
+
the given tags. The specs must be objects that hold a style tag
|
|
4218
|
+
or array of tags in their `tag` property, and either a single
|
|
4219
|
+
`class` property providing a static CSS class (for highlighter
|
|
4220
|
+
that rely on external styling), or a
|
|
4221
|
+
[`style-mod`](https://github.com/marijnh/style-mod#documentation)-style
|
|
4222
|
+
set of CSS properties (which define the styling for those tags).
|
|
4223
|
+
|
|
4224
|
+
The CSS rules created for a highlighter will be emitted in the
|
|
4225
|
+
order of the spec's properties. That means that for elements that
|
|
4226
|
+
have multiple tags associated with them, styles defined further
|
|
4227
|
+
down in the list will have a higher CSS precedence than styles
|
|
4228
|
+
defined earlier.
|
|
4229
|
+
*/
|
|
4230
|
+
static define(specs, options) {
|
|
4231
|
+
return new HighlightStyle(specs, options || {});
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
const highlighterFacet = /*@__PURE__*/state_.Facet.define();
|
|
4235
|
+
const fallbackHighlighter = /*@__PURE__*/state_.Facet.define({
|
|
4236
|
+
combine(values) { return values.length ? [values[0]] : null; }
|
|
4237
|
+
});
|
|
4238
|
+
function getHighlighters(state) {
|
|
4239
|
+
let main = state.facet(highlighterFacet);
|
|
4240
|
+
return main.length ? main : state.facet(fallbackHighlighter);
|
|
4241
|
+
}
|
|
4242
|
+
/**
|
|
4243
|
+
Wrap a highlighter in an editor extension that uses it to apply
|
|
4244
|
+
syntax highlighting to the editor content.
|
|
4245
|
+
|
|
4246
|
+
When multiple (non-fallback) styles are provided, the styling
|
|
4247
|
+
applied is the union of the classes they emit.
|
|
4248
|
+
*/
|
|
4249
|
+
function syntaxHighlighting(highlighter, options) {
|
|
4250
|
+
let ext = [treeHighlighter], themeType;
|
|
4251
|
+
if (highlighter instanceof HighlightStyle) {
|
|
4252
|
+
if (highlighter.module)
|
|
4253
|
+
ext.push(EditorView.styleModule.of(highlighter.module));
|
|
4254
|
+
themeType = highlighter.themeType;
|
|
4255
|
+
}
|
|
4256
|
+
if (options === null || options === void 0 ? void 0 : options.fallback)
|
|
4257
|
+
ext.push(fallbackHighlighter.of(highlighter));
|
|
4258
|
+
else if (themeType)
|
|
4259
|
+
ext.push(highlighterFacet.computeN([EditorView.darkTheme], state => {
|
|
4260
|
+
return state.facet(EditorView.darkTheme) == (themeType == "dark") ? [highlighter] : [];
|
|
4261
|
+
}));
|
|
4262
|
+
else
|
|
4263
|
+
ext.push(highlighterFacet.of(highlighter));
|
|
4264
|
+
return ext;
|
|
4265
|
+
}
|
|
4266
|
+
/**
|
|
4267
|
+
Returns the CSS classes (if any) that the highlighters active in
|
|
4268
|
+
the state would assign to the given style
|
|
4269
|
+
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag) and
|
|
4270
|
+
(optional) language
|
|
4271
|
+
[scope](https://codemirror.net/6/docs/ref/#language.HighlightStyle^define^options.scope).
|
|
4272
|
+
*/
|
|
4273
|
+
function highlightingFor(state, tags, scope) {
|
|
4274
|
+
let highlighters = getHighlighters(state);
|
|
4275
|
+
let result = null;
|
|
4276
|
+
if (highlighters)
|
|
4277
|
+
for (let highlighter of highlighters) {
|
|
4278
|
+
if (!highlighter.scope || scope && highlighter.scope(scope)) {
|
|
4279
|
+
let cls = highlighter.style(tags);
|
|
4280
|
+
if (cls)
|
|
4281
|
+
result = result ? result + " " + cls : cls;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
return result;
|
|
4285
|
+
}
|
|
4286
|
+
class TreeHighlighter {
|
|
4287
|
+
constructor(view) {
|
|
4288
|
+
this.markCache = Object.create(null);
|
|
4289
|
+
this.tree = dist_syntaxTree(view.state);
|
|
4290
|
+
this.decorations = this.buildDeco(view, getHighlighters(view.state));
|
|
4291
|
+
}
|
|
4292
|
+
update(update) {
|
|
4293
|
+
let tree = dist_syntaxTree(update.state), highlighters = getHighlighters(update.state);
|
|
4294
|
+
let styleChange = highlighters != getHighlighters(update.startState);
|
|
4295
|
+
if (tree.length < update.view.viewport.to && !styleChange && tree.type == this.tree.type) {
|
|
4296
|
+
this.decorations = this.decorations.map(update.changes);
|
|
4297
|
+
}
|
|
4298
|
+
else if (tree != this.tree || update.viewportChanged || styleChange) {
|
|
4299
|
+
this.tree = tree;
|
|
4300
|
+
this.decorations = this.buildDeco(update.view, highlighters);
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
buildDeco(view, highlighters) {
|
|
4304
|
+
if (!highlighters || !this.tree.length)
|
|
4305
|
+
return view_.Decoration.none;
|
|
4306
|
+
let builder = new state_.RangeSetBuilder();
|
|
4307
|
+
for (let { from, to } of view.visibleRanges) {
|
|
4308
|
+
highlightTree(this.tree, highlighters, (from, to, style) => {
|
|
4309
|
+
builder.add(from, to, this.markCache[style] || (this.markCache[style] = view_.Decoration.mark({ class: style })));
|
|
4310
|
+
}, from, to);
|
|
4311
|
+
}
|
|
4312
|
+
return builder.finish();
|
|
4313
|
+
}
|
|
4314
|
+
}
|
|
4315
|
+
const treeHighlighter = /*@__PURE__*/state_.Prec.high(/*@__PURE__*/view_.ViewPlugin.fromClass(TreeHighlighter, {
|
|
4316
|
+
decorations: v => v.decorations
|
|
4317
|
+
}));
|
|
4318
|
+
/**
|
|
4319
|
+
A default highlight style (works well with light themes).
|
|
4320
|
+
*/
|
|
4321
|
+
const defaultHighlightStyle = /*@__PURE__*/HighlightStyle.define([
|
|
4322
|
+
{ tag: tags.meta,
|
|
4323
|
+
color: "#7a757a" },
|
|
4324
|
+
{ tag: tags.link,
|
|
4325
|
+
textDecoration: "underline" },
|
|
4326
|
+
{ tag: tags.heading,
|
|
4327
|
+
textDecoration: "underline",
|
|
4328
|
+
fontWeight: "bold" },
|
|
4329
|
+
{ tag: tags.emphasis,
|
|
4330
|
+
fontStyle: "italic" },
|
|
4331
|
+
{ tag: tags.strong,
|
|
4332
|
+
fontWeight: "bold" },
|
|
4333
|
+
{ tag: tags.strikethrough,
|
|
4334
|
+
textDecoration: "line-through" },
|
|
4335
|
+
{ tag: tags.keyword,
|
|
4336
|
+
color: "#708" },
|
|
4337
|
+
{ tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName],
|
|
4338
|
+
color: "#219" },
|
|
4339
|
+
{ tag: [tags.literal, tags.inserted],
|
|
4340
|
+
color: "#164" },
|
|
4341
|
+
{ tag: [tags.string, tags.deleted],
|
|
4342
|
+
color: "#a11" },
|
|
4343
|
+
{ tag: [tags.regexp, tags.escape, /*@__PURE__*/tags.special(tags.string)],
|
|
4344
|
+
color: "#e40" },
|
|
4345
|
+
{ tag: /*@__PURE__*/tags.definition(tags.variableName),
|
|
4346
|
+
color: "#00f" },
|
|
4347
|
+
{ tag: /*@__PURE__*/tags.local(tags.variableName),
|
|
4348
|
+
color: "#30a" },
|
|
4349
|
+
{ tag: [tags.typeName, tags.namespace],
|
|
4350
|
+
color: "#085" },
|
|
4351
|
+
{ tag: tags.className,
|
|
4352
|
+
color: "#167" },
|
|
4353
|
+
{ tag: [/*@__PURE__*/tags.special(tags.variableName), tags.macroName],
|
|
4354
|
+
color: "#256" },
|
|
4355
|
+
{ tag: /*@__PURE__*/tags.definition(tags.propertyName),
|
|
4356
|
+
color: "#00c" },
|
|
4357
|
+
{ tag: tags.comment,
|
|
4358
|
+
color: "#940" },
|
|
4359
|
+
{ tag: tags.invalid,
|
|
4360
|
+
color: "#f00" }
|
|
4361
|
+
]);
|
|
4362
|
+
|
|
4363
|
+
const baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
4364
|
+
"&.cm-focused .cm-matchingBracket": { backgroundColor: "#328c8252" },
|
|
4365
|
+
"&.cm-focused .cm-nonmatchingBracket": { backgroundColor: "#bb555544" }
|
|
4366
|
+
});
|
|
4367
|
+
const DefaultScanDist = 10000, DefaultBrackets = "()[]{}";
|
|
4368
|
+
const bracketMatchingConfig = /*@__PURE__*/state_.Facet.define({
|
|
4369
|
+
combine(configs) {
|
|
4370
|
+
return (0,state_.combineConfig)(configs, {
|
|
4371
|
+
afterCursor: true,
|
|
4372
|
+
brackets: DefaultBrackets,
|
|
4373
|
+
maxScanDistance: DefaultScanDist,
|
|
4374
|
+
renderMatch: defaultRenderMatch
|
|
4375
|
+
});
|
|
4376
|
+
}
|
|
4377
|
+
});
|
|
4378
|
+
const matchingMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-matchingBracket" }), nonmatchingMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-nonmatchingBracket" });
|
|
4379
|
+
function defaultRenderMatch(match) {
|
|
4380
|
+
let decorations = [];
|
|
4381
|
+
let mark = match.matched ? matchingMark : nonmatchingMark;
|
|
4382
|
+
decorations.push(mark.range(match.start.from, match.start.to));
|
|
4383
|
+
if (match.end)
|
|
4384
|
+
decorations.push(mark.range(match.end.from, match.end.to));
|
|
4385
|
+
return decorations;
|
|
4386
|
+
}
|
|
4387
|
+
const bracketMatchingState = /*@__PURE__*/state_.StateField.define({
|
|
4388
|
+
create() { return view_.Decoration.none; },
|
|
4389
|
+
update(deco, tr) {
|
|
4390
|
+
if (!tr.docChanged && !tr.selection)
|
|
4391
|
+
return deco;
|
|
4392
|
+
let decorations = [];
|
|
4393
|
+
let config = tr.state.facet(bracketMatchingConfig);
|
|
4394
|
+
for (let range of tr.state.selection.ranges) {
|
|
4395
|
+
if (!range.empty)
|
|
4396
|
+
continue;
|
|
4397
|
+
let match = dist_matchBrackets(tr.state, range.head, -1, config)
|
|
4398
|
+
|| (range.head > 0 && dist_matchBrackets(tr.state, range.head - 1, 1, config))
|
|
4399
|
+
|| (config.afterCursor &&
|
|
4400
|
+
(dist_matchBrackets(tr.state, range.head, 1, config) ||
|
|
4401
|
+
(range.head < tr.state.doc.length && dist_matchBrackets(tr.state, range.head + 1, -1, config))));
|
|
4402
|
+
if (match)
|
|
4403
|
+
decorations = decorations.concat(config.renderMatch(match, tr.state));
|
|
4404
|
+
}
|
|
4405
|
+
return view_.Decoration.set(decorations, true);
|
|
4406
|
+
},
|
|
4407
|
+
provide: f => view_.EditorView.decorations.from(f)
|
|
4408
|
+
});
|
|
4409
|
+
const bracketMatchingUnique = [
|
|
4410
|
+
bracketMatchingState,
|
|
4411
|
+
baseTheme
|
|
4412
|
+
];
|
|
4413
|
+
/**
|
|
4414
|
+
Create an extension that enables bracket matching. Whenever the
|
|
4415
|
+
cursor is next to a bracket, that bracket and the one it matches
|
|
4416
|
+
are highlighted. Or, when no matching bracket is found, another
|
|
4417
|
+
highlighting style is used to indicate this.
|
|
4418
|
+
*/
|
|
4419
|
+
function bracketMatching(config = {}) {
|
|
4420
|
+
return [bracketMatchingConfig.of(config), bracketMatchingUnique];
|
|
4421
|
+
}
|
|
4422
|
+
function matchingNodes(node, dir, brackets) {
|
|
4423
|
+
let byProp = node.prop(dir < 0 ? dist_NodeProp.openedBy : dist_NodeProp.closedBy);
|
|
4424
|
+
if (byProp)
|
|
4425
|
+
return byProp;
|
|
4426
|
+
if (node.name.length == 1) {
|
|
4427
|
+
let index = brackets.indexOf(node.name);
|
|
4428
|
+
if (index > -1 && index % 2 == (dir < 0 ? 1 : 0))
|
|
4429
|
+
return [brackets[index + dir]];
|
|
4430
|
+
}
|
|
4431
|
+
return null;
|
|
4432
|
+
}
|
|
4433
|
+
/**
|
|
4434
|
+
Find the matching bracket for the token at `pos`, scanning
|
|
4435
|
+
direction `dir`. Only the `brackets` and `maxScanDistance`
|
|
4436
|
+
properties are used from `config`, if given. Returns null if no
|
|
4437
|
+
bracket was found at `pos`, or a match result otherwise.
|
|
4438
|
+
*/
|
|
4439
|
+
function dist_matchBrackets(state, pos, dir, config = {}) {
|
|
4440
|
+
let maxScanDistance = config.maxScanDistance || DefaultScanDist, brackets = config.brackets || DefaultBrackets;
|
|
4441
|
+
let tree = dist_syntaxTree(state), node = tree.resolveInner(pos, dir);
|
|
4442
|
+
for (let cur = node; cur; cur = cur.parent) {
|
|
4443
|
+
let matches = matchingNodes(cur.type, dir, brackets);
|
|
4444
|
+
if (matches && cur.from < cur.to)
|
|
4445
|
+
return matchMarkedBrackets(state, pos, dir, cur, matches, brackets);
|
|
4446
|
+
}
|
|
4447
|
+
return matchPlainBrackets(state, pos, dir, tree, node.type, maxScanDistance, brackets);
|
|
4448
|
+
}
|
|
4449
|
+
function matchMarkedBrackets(_state, _pos, dir, token, matching, brackets) {
|
|
4450
|
+
let parent = token.parent, firstToken = { from: token.from, to: token.to };
|
|
4451
|
+
let depth = 0, cursor = parent === null || parent === void 0 ? void 0 : parent.cursor();
|
|
4452
|
+
if (cursor && (dir < 0 ? cursor.childBefore(token.from) : cursor.childAfter(token.to)))
|
|
4453
|
+
do {
|
|
4454
|
+
if (dir < 0 ? cursor.to <= token.from : cursor.from >= token.to) {
|
|
4455
|
+
if (depth == 0 && matching.indexOf(cursor.type.name) > -1 && cursor.from < cursor.to) {
|
|
4456
|
+
return { start: firstToken, end: { from: cursor.from, to: cursor.to }, matched: true };
|
|
4457
|
+
}
|
|
4458
|
+
else if (matchingNodes(cursor.type, dir, brackets)) {
|
|
4459
|
+
depth++;
|
|
4460
|
+
}
|
|
4461
|
+
else if (matchingNodes(cursor.type, -dir, brackets)) {
|
|
4462
|
+
depth--;
|
|
4463
|
+
if (depth == 0)
|
|
4464
|
+
return {
|
|
4465
|
+
start: firstToken,
|
|
4466
|
+
end: cursor.from == cursor.to ? undefined : { from: cursor.from, to: cursor.to },
|
|
4467
|
+
matched: false
|
|
4468
|
+
};
|
|
4469
|
+
}
|
|
4470
|
+
}
|
|
4471
|
+
} while (dir < 0 ? cursor.prevSibling() : cursor.nextSibling());
|
|
4472
|
+
return { start: firstToken, matched: false };
|
|
4473
|
+
}
|
|
4474
|
+
function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, brackets) {
|
|
4475
|
+
let startCh = dir < 0 ? state.sliceDoc(pos - 1, pos) : state.sliceDoc(pos, pos + 1);
|
|
4476
|
+
let bracket = brackets.indexOf(startCh);
|
|
4477
|
+
if (bracket < 0 || (bracket % 2 == 0) != (dir > 0))
|
|
4478
|
+
return null;
|
|
4479
|
+
let startToken = { from: dir < 0 ? pos - 1 : pos, to: dir > 0 ? pos + 1 : pos };
|
|
4480
|
+
let iter = state.doc.iterRange(pos, dir > 0 ? state.doc.length : 0), depth = 0;
|
|
4481
|
+
for (let distance = 0; !(iter.next()).done && distance <= maxScanDistance;) {
|
|
4482
|
+
let text = iter.value;
|
|
4483
|
+
if (dir < 0)
|
|
4484
|
+
distance += text.length;
|
|
4485
|
+
let basePos = pos + distance * dir;
|
|
4486
|
+
for (let pos = dir > 0 ? 0 : text.length - 1, end = dir > 0 ? text.length : -1; pos != end; pos += dir) {
|
|
4487
|
+
let found = brackets.indexOf(text[pos]);
|
|
4488
|
+
if (found < 0 || tree.resolve(basePos + pos, 1).type != tokenType)
|
|
4489
|
+
continue;
|
|
4490
|
+
if ((found % 2 == 0) == (dir > 0)) {
|
|
4491
|
+
depth++;
|
|
4492
|
+
}
|
|
4493
|
+
else if (depth == 1) { // Closing
|
|
4494
|
+
return { start: startToken, end: { from: basePos + pos, to: basePos + pos + 1 }, matched: (found >> 1) == (bracket >> 1) };
|
|
4495
|
+
}
|
|
4496
|
+
else {
|
|
4497
|
+
depth--;
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4500
|
+
if (dir > 0)
|
|
4501
|
+
distance += text.length;
|
|
4502
|
+
}
|
|
4503
|
+
return iter.done ? { start: startToken, matched: false } : null;
|
|
4504
|
+
}
|
|
4505
|
+
|
|
4506
|
+
// Counts the column offset in a string, taking tabs into account.
|
|
4507
|
+
// Used mostly to find indentation.
|
|
4508
|
+
function countCol(string, end, tabSize, startIndex = 0, startValue = 0) {
|
|
4509
|
+
if (end == null) {
|
|
4510
|
+
end = string.search(/[^\s\u00a0]/);
|
|
4511
|
+
if (end == -1)
|
|
4512
|
+
end = string.length;
|
|
4513
|
+
}
|
|
4514
|
+
let n = startValue;
|
|
4515
|
+
for (let i = startIndex; i < end; i++) {
|
|
4516
|
+
if (string.charCodeAt(i) == 9)
|
|
4517
|
+
n += tabSize - (n % tabSize);
|
|
4518
|
+
else
|
|
4519
|
+
n++;
|
|
4520
|
+
}
|
|
4521
|
+
return n;
|
|
4522
|
+
}
|
|
4523
|
+
/**
|
|
4524
|
+
Encapsulates a single line of input. Given to stream syntax code,
|
|
4525
|
+
which uses it to tokenize the content.
|
|
4526
|
+
*/
|
|
4527
|
+
class StringStream {
|
|
4528
|
+
/**
|
|
4529
|
+
@internal
|
|
4530
|
+
*/
|
|
4531
|
+
constructor(
|
|
4532
|
+
/**
|
|
4533
|
+
The line.
|
|
4534
|
+
*/
|
|
4535
|
+
string, tabSize,
|
|
4536
|
+
/**
|
|
4537
|
+
The current indent unit size.
|
|
4538
|
+
*/
|
|
4539
|
+
indentUnit) {
|
|
4540
|
+
this.string = string;
|
|
4541
|
+
this.tabSize = tabSize;
|
|
4542
|
+
this.indentUnit = indentUnit;
|
|
4543
|
+
/**
|
|
4544
|
+
The current position on the line.
|
|
4545
|
+
*/
|
|
4546
|
+
this.pos = 0;
|
|
4547
|
+
/**
|
|
4548
|
+
The start position of the current token.
|
|
4549
|
+
*/
|
|
4550
|
+
this.start = 0;
|
|
4551
|
+
this.lastColumnPos = 0;
|
|
4552
|
+
this.lastColumnValue = 0;
|
|
4553
|
+
}
|
|
4554
|
+
/**
|
|
4555
|
+
True if we are at the end of the line.
|
|
4556
|
+
*/
|
|
4557
|
+
eol() { return this.pos >= this.string.length; }
|
|
4558
|
+
/**
|
|
4559
|
+
True if we are at the start of the line.
|
|
4560
|
+
*/
|
|
4561
|
+
sol() { return this.pos == 0; }
|
|
4562
|
+
/**
|
|
4563
|
+
Get the next code unit after the current position, or undefined
|
|
4564
|
+
if we're at the end of the line.
|
|
4565
|
+
*/
|
|
4566
|
+
peek() { return this.string.charAt(this.pos) || undefined; }
|
|
4567
|
+
/**
|
|
4568
|
+
Read the next code unit and advance `this.pos`.
|
|
4569
|
+
*/
|
|
4570
|
+
next() {
|
|
4571
|
+
if (this.pos < this.string.length)
|
|
4572
|
+
return this.string.charAt(this.pos++);
|
|
4573
|
+
}
|
|
4574
|
+
/**
|
|
4575
|
+
Match the next character against the given string, regular
|
|
4576
|
+
expression, or predicate. Consume and return it if it matches.
|
|
4577
|
+
*/
|
|
4578
|
+
eat(match) {
|
|
4579
|
+
let ch = this.string.charAt(this.pos);
|
|
4580
|
+
let ok;
|
|
4581
|
+
if (typeof match == "string")
|
|
4582
|
+
ok = ch == match;
|
|
4583
|
+
else
|
|
4584
|
+
ok = ch && (match instanceof RegExp ? match.test(ch) : match(ch));
|
|
4585
|
+
if (ok) {
|
|
4586
|
+
++this.pos;
|
|
4587
|
+
return ch;
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4590
|
+
/**
|
|
4591
|
+
Continue matching characters that match the given string,
|
|
4592
|
+
regular expression, or predicate function. Return true if any
|
|
4593
|
+
characters were consumed.
|
|
4594
|
+
*/
|
|
4595
|
+
eatWhile(match) {
|
|
4596
|
+
let start = this.pos;
|
|
4597
|
+
while (this.eat(match)) { }
|
|
4598
|
+
return this.pos > start;
|
|
4599
|
+
}
|
|
4600
|
+
/**
|
|
4601
|
+
Consume whitespace ahead of `this.pos`. Return true if any was
|
|
4602
|
+
found.
|
|
4603
|
+
*/
|
|
4604
|
+
eatSpace() {
|
|
4605
|
+
let start = this.pos;
|
|
4606
|
+
while (/[\s\u00a0]/.test(this.string.charAt(this.pos)))
|
|
4607
|
+
++this.pos;
|
|
4608
|
+
return this.pos > start;
|
|
4609
|
+
}
|
|
4610
|
+
/**
|
|
4611
|
+
Move to the end of the line.
|
|
4612
|
+
*/
|
|
4613
|
+
skipToEnd() { this.pos = this.string.length; }
|
|
4614
|
+
/**
|
|
4615
|
+
Move to directly before the given character, if found on the
|
|
4616
|
+
current line.
|
|
4617
|
+
*/
|
|
4618
|
+
skipTo(ch) {
|
|
4619
|
+
let found = this.string.indexOf(ch, this.pos);
|
|
4620
|
+
if (found > -1) {
|
|
4621
|
+
this.pos = found;
|
|
4622
|
+
return true;
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
/**
|
|
4626
|
+
Move back `n` characters.
|
|
4627
|
+
*/
|
|
4628
|
+
backUp(n) { this.pos -= n; }
|
|
4629
|
+
/**
|
|
4630
|
+
Get the column position at `this.pos`.
|
|
4631
|
+
*/
|
|
4632
|
+
column() {
|
|
4633
|
+
if (this.lastColumnPos < this.start) {
|
|
4634
|
+
this.lastColumnValue = countCol(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
|
|
4635
|
+
this.lastColumnPos = this.start;
|
|
4636
|
+
}
|
|
4637
|
+
return this.lastColumnValue;
|
|
4638
|
+
}
|
|
4639
|
+
/**
|
|
4640
|
+
Get the indentation column of the current line.
|
|
4641
|
+
*/
|
|
4642
|
+
indentation() {
|
|
4643
|
+
return countCol(this.string, null, this.tabSize);
|
|
4644
|
+
}
|
|
4645
|
+
/**
|
|
4646
|
+
Match the input against the given string or regular expression
|
|
4647
|
+
(which should start with a `^`). Return true or the regexp match
|
|
4648
|
+
if it matches.
|
|
4649
|
+
|
|
4650
|
+
Unless `consume` is set to `false`, this will move `this.pos`
|
|
4651
|
+
past the matched text.
|
|
4652
|
+
|
|
4653
|
+
When matching a string `caseInsensitive` can be set to true to
|
|
4654
|
+
make the match case-insensitive.
|
|
4655
|
+
*/
|
|
4656
|
+
match(pattern, consume, caseInsensitive) {
|
|
4657
|
+
if (typeof pattern == "string") {
|
|
4658
|
+
let cased = (str) => caseInsensitive ? str.toLowerCase() : str;
|
|
4659
|
+
let substr = this.string.substr(this.pos, pattern.length);
|
|
4660
|
+
if (cased(substr) == cased(pattern)) {
|
|
4661
|
+
if (consume !== false)
|
|
4662
|
+
this.pos += pattern.length;
|
|
4663
|
+
return true;
|
|
4664
|
+
}
|
|
4665
|
+
else
|
|
4666
|
+
return null;
|
|
4667
|
+
}
|
|
4668
|
+
else {
|
|
4669
|
+
let match = this.string.slice(this.pos).match(pattern);
|
|
4670
|
+
if (match && match.index > 0)
|
|
4671
|
+
return null;
|
|
4672
|
+
if (match && consume !== false)
|
|
4673
|
+
this.pos += match[0].length;
|
|
4674
|
+
return match;
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
/**
|
|
4678
|
+
Get the current token.
|
|
4679
|
+
*/
|
|
4680
|
+
current() { return this.string.slice(this.start, this.pos); }
|
|
4681
|
+
}
|
|
4682
|
+
|
|
4683
|
+
function fullParser(spec) {
|
|
4684
|
+
return {
|
|
4685
|
+
token: spec.token,
|
|
4686
|
+
blankLine: spec.blankLine || (() => { }),
|
|
4687
|
+
startState: spec.startState || (() => true),
|
|
4688
|
+
copyState: spec.copyState || defaultCopyState,
|
|
4689
|
+
indent: spec.indent || (() => null),
|
|
4690
|
+
languageData: spec.languageData || {},
|
|
4691
|
+
tokenTable: spec.tokenTable || noTokens
|
|
4692
|
+
};
|
|
4693
|
+
}
|
|
4694
|
+
function defaultCopyState(state) {
|
|
4695
|
+
if (typeof state != "object")
|
|
4696
|
+
return state;
|
|
4697
|
+
let newState = {};
|
|
4698
|
+
for (let prop in state) {
|
|
4699
|
+
let val = state[prop];
|
|
4700
|
+
newState[prop] = (val instanceof Array ? val.slice() : val);
|
|
4701
|
+
}
|
|
4702
|
+
return newState;
|
|
4703
|
+
}
|
|
4704
|
+
/**
|
|
4705
|
+
A [language](https://codemirror.net/6/docs/ref/#language.Language) class based on a CodeMirror
|
|
4706
|
+
5-style [streaming parser](https://codemirror.net/6/docs/ref/#language.StreamParser).
|
|
4707
|
+
*/
|
|
4708
|
+
class StreamLanguage extends (/* unused pure expression or super */ null && (Language)) {
|
|
4709
|
+
constructor(parser) {
|
|
4710
|
+
let data = defineLanguageFacet(parser.languageData);
|
|
4711
|
+
let p = fullParser(parser), self;
|
|
4712
|
+
let impl = new class extends Parser {
|
|
4713
|
+
createParse(input, fragments, ranges) {
|
|
4714
|
+
return new Parse(self, input, fragments, ranges);
|
|
4715
|
+
}
|
|
4716
|
+
};
|
|
4717
|
+
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))]);
|
|
4718
|
+
this.topNode = docID(data);
|
|
4719
|
+
self = this;
|
|
4720
|
+
this.streamParser = p;
|
|
4721
|
+
this.stateAfter = new NodeProp({ perNode: true });
|
|
4722
|
+
this.tokenTable = parser.tokenTable ? new TokenTable(p.tokenTable) : defaultTokenTable;
|
|
4723
|
+
}
|
|
4724
|
+
/**
|
|
4725
|
+
Define a stream language.
|
|
4726
|
+
*/
|
|
4727
|
+
static define(spec) { return new StreamLanguage(spec); }
|
|
4728
|
+
getIndent(cx, pos) {
|
|
4729
|
+
let tree = dist_syntaxTree(cx.state), at = tree.resolve(pos);
|
|
4730
|
+
while (at && at.type != this.topNode)
|
|
4731
|
+
at = at.parent;
|
|
4732
|
+
if (!at)
|
|
4733
|
+
return null;
|
|
4734
|
+
let start = findState(this, tree, 0, at.from, pos), statePos, state;
|
|
4735
|
+
if (start) {
|
|
4736
|
+
state = start.state;
|
|
4737
|
+
statePos = start.pos + 1;
|
|
4738
|
+
}
|
|
4739
|
+
else {
|
|
4740
|
+
state = this.streamParser.startState(cx.unit);
|
|
4741
|
+
statePos = 0;
|
|
4742
|
+
}
|
|
4743
|
+
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
|
4744
|
+
return null;
|
|
4745
|
+
while (statePos < pos) {
|
|
4746
|
+
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
|
4747
|
+
if (line.length) {
|
|
4748
|
+
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit);
|
|
4749
|
+
while (stream.pos < end - line.from)
|
|
4750
|
+
readToken(this.streamParser.token, stream, state);
|
|
4751
|
+
}
|
|
4752
|
+
else {
|
|
4753
|
+
this.streamParser.blankLine(state, cx.unit);
|
|
4754
|
+
}
|
|
4755
|
+
if (end == pos)
|
|
4756
|
+
break;
|
|
4757
|
+
statePos = line.to + 1;
|
|
4758
|
+
}
|
|
4759
|
+
let { text } = cx.lineAt(pos);
|
|
4760
|
+
return this.streamParser.indent(state, /^\s*(.*)/.exec(text)[1], cx);
|
|
4761
|
+
}
|
|
4762
|
+
get allowsNesting() { return false; }
|
|
4763
|
+
}
|
|
4764
|
+
function findState(lang, tree, off, startPos, before) {
|
|
4765
|
+
let state = off >= startPos && off + tree.length <= before && tree.prop(lang.stateAfter);
|
|
4766
|
+
if (state)
|
|
4767
|
+
return { state: lang.streamParser.copyState(state), pos: off + tree.length };
|
|
4768
|
+
for (let i = tree.children.length - 1; i >= 0; i--) {
|
|
4769
|
+
let child = tree.children[i], pos = off + tree.positions[i];
|
|
4770
|
+
let found = child instanceof Tree && pos < before && findState(lang, child, pos, startPos, before);
|
|
4771
|
+
if (found)
|
|
4772
|
+
return found;
|
|
4773
|
+
}
|
|
4774
|
+
return null;
|
|
4775
|
+
}
|
|
4776
|
+
function cutTree(lang, tree, from, to, inside) {
|
|
4777
|
+
if (inside && from <= 0 && to >= tree.length)
|
|
4778
|
+
return tree;
|
|
4779
|
+
if (!inside && tree.type == lang.topNode)
|
|
4780
|
+
inside = true;
|
|
4781
|
+
for (let i = tree.children.length - 1; i >= 0; i--) {
|
|
4782
|
+
let pos = tree.positions[i], child = tree.children[i], inner;
|
|
4783
|
+
if (pos < to && child instanceof Tree) {
|
|
4784
|
+
if (!(inner = cutTree(lang, child, from - pos, to - pos, inside)))
|
|
4785
|
+
break;
|
|
4786
|
+
return !inside ? inner
|
|
4787
|
+
: new Tree(tree.type, tree.children.slice(0, i).concat(inner), tree.positions.slice(0, i + 1), pos + inner.length);
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
return null;
|
|
4791
|
+
}
|
|
4792
|
+
function findStartInFragments(lang, fragments, startPos, editorState) {
|
|
4793
|
+
for (let f of fragments) {
|
|
4794
|
+
let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
|
|
4795
|
+
let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
|
|
4796
|
+
if (found && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
|
|
4797
|
+
return { state: found.state, tree };
|
|
4798
|
+
}
|
|
4799
|
+
return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: Tree.empty };
|
|
4800
|
+
}
|
|
4801
|
+
class Parse {
|
|
4802
|
+
constructor(lang, input, fragments, ranges) {
|
|
4803
|
+
this.lang = lang;
|
|
4804
|
+
this.input = input;
|
|
4805
|
+
this.fragments = fragments;
|
|
4806
|
+
this.ranges = ranges;
|
|
4807
|
+
this.stoppedAt = null;
|
|
4808
|
+
this.chunks = [];
|
|
4809
|
+
this.chunkPos = [];
|
|
4810
|
+
this.chunk = [];
|
|
4811
|
+
this.chunkReused = undefined;
|
|
4812
|
+
this.rangeIndex = 0;
|
|
4813
|
+
this.to = ranges[ranges.length - 1].to;
|
|
4814
|
+
let context = ParseContext.get(), from = ranges[0].from;
|
|
4815
|
+
let { state, tree } = findStartInFragments(lang, fragments, from, context === null || context === void 0 ? void 0 : context.state);
|
|
4816
|
+
this.state = state;
|
|
4817
|
+
this.parsedPos = this.chunkStart = from + tree.length;
|
|
4818
|
+
for (let i = 0; i < tree.children.length; i++) {
|
|
4819
|
+
this.chunks.push(tree.children[i]);
|
|
4820
|
+
this.chunkPos.push(tree.positions[i]);
|
|
4821
|
+
}
|
|
4822
|
+
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
|
4823
|
+
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
|
4824
|
+
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
|
4825
|
+
this.parsedPos = context.viewport.from;
|
|
4826
|
+
}
|
|
4827
|
+
this.moveRangeIndex();
|
|
4828
|
+
}
|
|
4829
|
+
advance() {
|
|
4830
|
+
let context = ParseContext.get();
|
|
4831
|
+
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
|
4832
|
+
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
|
4833
|
+
if (context)
|
|
4834
|
+
end = Math.min(end, context.viewport.to);
|
|
4835
|
+
while (this.parsedPos < end)
|
|
4836
|
+
this.parseLine(context);
|
|
4837
|
+
if (this.chunkStart < this.parsedPos)
|
|
4838
|
+
this.finishChunk();
|
|
4839
|
+
if (this.parsedPos >= parseEnd)
|
|
4840
|
+
return this.finish();
|
|
4841
|
+
if (context && this.parsedPos >= context.viewport.to) {
|
|
4842
|
+
context.skipUntilInView(this.parsedPos, parseEnd);
|
|
4843
|
+
return this.finish();
|
|
4844
|
+
}
|
|
4845
|
+
return null;
|
|
4846
|
+
}
|
|
4847
|
+
stopAt(pos) {
|
|
4848
|
+
this.stoppedAt = pos;
|
|
4849
|
+
}
|
|
4850
|
+
lineAfter(pos) {
|
|
4851
|
+
let chunk = this.input.chunk(pos);
|
|
4852
|
+
if (!this.input.lineChunks) {
|
|
4853
|
+
let eol = chunk.indexOf("\n");
|
|
4854
|
+
if (eol > -1)
|
|
4855
|
+
chunk = chunk.slice(0, eol);
|
|
4856
|
+
}
|
|
4857
|
+
else if (chunk == "\n") {
|
|
4858
|
+
chunk = "";
|
|
4859
|
+
}
|
|
4860
|
+
return pos + chunk.length <= this.to ? chunk : chunk.slice(0, this.to - pos);
|
|
4861
|
+
}
|
|
4862
|
+
nextLine() {
|
|
4863
|
+
let from = this.parsedPos, line = this.lineAfter(from), end = from + line.length;
|
|
4864
|
+
for (let index = this.rangeIndex;;) {
|
|
4865
|
+
let rangeEnd = this.ranges[index].to;
|
|
4866
|
+
if (rangeEnd >= end)
|
|
4867
|
+
break;
|
|
4868
|
+
line = line.slice(0, rangeEnd - (end - line.length));
|
|
4869
|
+
index++;
|
|
4870
|
+
if (index == this.ranges.length)
|
|
4871
|
+
break;
|
|
4872
|
+
let rangeStart = this.ranges[index].from;
|
|
4873
|
+
let after = this.lineAfter(rangeStart);
|
|
4874
|
+
line += after;
|
|
4875
|
+
end = rangeStart + after.length;
|
|
4876
|
+
}
|
|
4877
|
+
return { line, end };
|
|
4878
|
+
}
|
|
4879
|
+
skipGapsTo(pos, offset, side) {
|
|
4880
|
+
for (;;) {
|
|
4881
|
+
let end = this.ranges[this.rangeIndex].to, offPos = pos + offset;
|
|
4882
|
+
if (side > 0 ? end > offPos : end >= offPos)
|
|
4883
|
+
break;
|
|
4884
|
+
let start = this.ranges[++this.rangeIndex].from;
|
|
4885
|
+
offset += start - end;
|
|
4886
|
+
}
|
|
4887
|
+
return offset;
|
|
4888
|
+
}
|
|
4889
|
+
moveRangeIndex() {
|
|
4890
|
+
while (this.ranges[this.rangeIndex].to < this.parsedPos)
|
|
4891
|
+
this.rangeIndex++;
|
|
4892
|
+
}
|
|
4893
|
+
emitToken(id, from, to, size, offset) {
|
|
4894
|
+
if (this.ranges.length > 1) {
|
|
4895
|
+
offset = this.skipGapsTo(from, offset, 1);
|
|
4896
|
+
from += offset;
|
|
4897
|
+
let len0 = this.chunk.length;
|
|
4898
|
+
offset = this.skipGapsTo(to, offset, -1);
|
|
4899
|
+
to += offset;
|
|
4900
|
+
size += this.chunk.length - len0;
|
|
4901
|
+
}
|
|
4902
|
+
this.chunk.push(id, from, to, size);
|
|
4903
|
+
return offset;
|
|
4904
|
+
}
|
|
4905
|
+
parseLine(context) {
|
|
4906
|
+
let { line, end } = this.nextLine(), offset = 0, { streamParser } = this.lang;
|
|
4907
|
+
let stream = new StringStream(line, context ? context.state.tabSize : 4, context ? getIndentUnit(context.state) : 2);
|
|
4908
|
+
if (stream.eol()) {
|
|
4909
|
+
streamParser.blankLine(this.state, stream.indentUnit);
|
|
4910
|
+
}
|
|
4911
|
+
else {
|
|
4912
|
+
while (!stream.eol()) {
|
|
4913
|
+
let token = readToken(streamParser.token, stream, this.state);
|
|
4914
|
+
if (token)
|
|
4915
|
+
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
|
4916
|
+
if (stream.start > 10000 /* MaxLineLength */)
|
|
4917
|
+
break;
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
this.parsedPos = end;
|
|
4921
|
+
this.moveRangeIndex();
|
|
4922
|
+
if (this.parsedPos < this.to)
|
|
4923
|
+
this.parsedPos++;
|
|
4924
|
+
}
|
|
4925
|
+
finishChunk() {
|
|
4926
|
+
let tree = Tree.build({
|
|
4927
|
+
buffer: this.chunk,
|
|
4928
|
+
start: this.chunkStart,
|
|
4929
|
+
length: this.parsedPos - this.chunkStart,
|
|
4930
|
+
nodeSet,
|
|
4931
|
+
topID: 0,
|
|
4932
|
+
maxBufferLength: 2048 /* ChunkSize */,
|
|
4933
|
+
reused: this.chunkReused
|
|
4934
|
+
});
|
|
4935
|
+
tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
|
4936
|
+
this.chunks.push(tree);
|
|
4937
|
+
this.chunkPos.push(this.chunkStart - this.ranges[0].from);
|
|
4938
|
+
this.chunk = [];
|
|
4939
|
+
this.chunkReused = undefined;
|
|
4940
|
+
this.chunkStart = this.parsedPos;
|
|
4941
|
+
}
|
|
4942
|
+
finish() {
|
|
4943
|
+
return new Tree(this.lang.topNode, this.chunks, this.chunkPos, this.parsedPos - this.ranges[0].from).balance();
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
function readToken(token, stream, state) {
|
|
4947
|
+
stream.start = stream.pos;
|
|
4948
|
+
for (let i = 0; i < 10; i++) {
|
|
4949
|
+
let result = token(stream, state);
|
|
4950
|
+
if (stream.pos > stream.start)
|
|
4951
|
+
return result;
|
|
4952
|
+
}
|
|
4953
|
+
throw new Error("Stream parser failed to advance stream.");
|
|
4954
|
+
}
|
|
4955
|
+
const noTokens = /*@__PURE__*/Object.create(null);
|
|
4956
|
+
const typeArray = [dist_NodeType.none];
|
|
4957
|
+
const nodeSet = /*@__PURE__*/new NodeSet(typeArray);
|
|
4958
|
+
const warned = [];
|
|
4959
|
+
const defaultTable = /*@__PURE__*/Object.create(null);
|
|
4960
|
+
for (let [legacyName, name] of [
|
|
4961
|
+
["variable", "variableName"],
|
|
4962
|
+
["variable-2", "variableName.special"],
|
|
4963
|
+
["string-2", "string.special"],
|
|
4964
|
+
["def", "variableName.definition"],
|
|
4965
|
+
["tag", "typeName"],
|
|
4966
|
+
["attribute", "propertyName"],
|
|
4967
|
+
["type", "typeName"],
|
|
4968
|
+
["builtin", "variableName.standard"],
|
|
4969
|
+
["qualifier", "modifier"],
|
|
4970
|
+
["error", "invalid"],
|
|
4971
|
+
["header", "heading"],
|
|
4972
|
+
["property", "propertyName"]
|
|
4973
|
+
])
|
|
4974
|
+
defaultTable[legacyName] = /*@__PURE__*/createTokenType(noTokens, name);
|
|
4975
|
+
class TokenTable {
|
|
4976
|
+
constructor(extra) {
|
|
4977
|
+
this.extra = extra;
|
|
4978
|
+
this.table = Object.assign(Object.create(null), defaultTable);
|
|
4979
|
+
}
|
|
4980
|
+
resolve(tag) {
|
|
4981
|
+
return !tag ? 0 : this.table[tag] || (this.table[tag] = createTokenType(this.extra, tag));
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
const defaultTokenTable = /*@__PURE__*/new TokenTable(noTokens);
|
|
4985
|
+
function warnForPart(part, msg) {
|
|
4986
|
+
if (warned.indexOf(part) > -1)
|
|
4987
|
+
return;
|
|
4988
|
+
warned.push(part);
|
|
4989
|
+
console.warn(msg);
|
|
4990
|
+
}
|
|
4991
|
+
function createTokenType(extra, tagStr) {
|
|
4992
|
+
let tag = null;
|
|
4993
|
+
for (let part of tagStr.split(".")) {
|
|
4994
|
+
let value = (extra[part] || tags[part]);
|
|
4995
|
+
if (!value) {
|
|
4996
|
+
warnForPart(part, `Unknown highlighting tag ${part}`);
|
|
4997
|
+
}
|
|
4998
|
+
else if (typeof value == "function") {
|
|
4999
|
+
if (!tag)
|
|
5000
|
+
warnForPart(part, `Modifier ${part} used at start of tag`);
|
|
5001
|
+
else
|
|
5002
|
+
tag = value(tag);
|
|
5003
|
+
}
|
|
5004
|
+
else {
|
|
5005
|
+
if (tag)
|
|
5006
|
+
warnForPart(part, `Tag ${part} used as modifier`);
|
|
5007
|
+
else
|
|
5008
|
+
tag = value;
|
|
5009
|
+
}
|
|
5010
|
+
}
|
|
5011
|
+
if (!tag)
|
|
5012
|
+
return 0;
|
|
5013
|
+
let name = tagStr.replace(/ /g, "_"), type = dist_NodeType.define({
|
|
5014
|
+
id: typeArray.length,
|
|
5015
|
+
name,
|
|
5016
|
+
props: [styleTags({ [name]: tag })]
|
|
5017
|
+
});
|
|
5018
|
+
typeArray.push(type);
|
|
5019
|
+
return type.id;
|
|
5020
|
+
}
|
|
5021
|
+
function docID(data) {
|
|
5022
|
+
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
|
|
5023
|
+
typeArray.push(type);
|
|
5024
|
+
return type;
|
|
5025
|
+
}
|
|
5026
|
+
|
|
5027
|
+
|
|
5028
|
+
|
|
5029
|
+
;// CONCATENATED MODULE: ./node_modules/@codemirror/commands/dist/index.js
|
|
5030
|
+
|
|
5031
|
+
|
|
5032
|
+
|
|
5033
|
+
|
|
5034
|
+
|
|
5035
|
+
/**
|
|
5036
|
+
Comment or uncomment the current selection. Will use line comments
|
|
5037
|
+
if available, otherwise falling back to block comments.
|
|
5038
|
+
*/
|
|
5039
|
+
const toggleComment = target => {
|
|
5040
|
+
let config = getConfig(target.state);
|
|
5041
|
+
return config.line ? toggleLineComment(target) : config.block ? toggleBlockCommentByLine(target) : false;
|
|
5042
|
+
};
|
|
5043
|
+
function command(f, option) {
|
|
5044
|
+
return ({ state, dispatch }) => {
|
|
5045
|
+
if (state.readOnly)
|
|
5046
|
+
return false;
|
|
5047
|
+
let tr = f(option, state);
|
|
5048
|
+
if (!tr)
|
|
5049
|
+
return false;
|
|
5050
|
+
dispatch(state.update(tr));
|
|
5051
|
+
return true;
|
|
5052
|
+
};
|
|
5053
|
+
}
|
|
5054
|
+
/**
|
|
5055
|
+
Comment or uncomment the current selection using line comments.
|
|
5056
|
+
The line comment syntax is taken from the
|
|
5057
|
+
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
|
5058
|
+
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
|
5059
|
+
*/
|
|
5060
|
+
const toggleLineComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeLineComment, 0 /* Toggle */)));
|
|
5061
|
+
/**
|
|
5062
|
+
Comment the current selection using line comments.
|
|
5063
|
+
*/
|
|
5064
|
+
const lineComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeLineComment, 1 /* Comment */)));
|
|
5065
|
+
/**
|
|
5066
|
+
Uncomment the current selection using line comments.
|
|
5067
|
+
*/
|
|
5068
|
+
const lineUncomment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeLineComment, 2 /* Uncomment */)));
|
|
5069
|
+
/**
|
|
5070
|
+
Comment or uncomment the current selection using block comments.
|
|
5071
|
+
The block comment syntax is taken from the
|
|
5072
|
+
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
|
5073
|
+
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
|
5074
|
+
*/
|
|
5075
|
+
const toggleBlockComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeBlockComment, 0 /* Toggle */)));
|
|
5076
|
+
/**
|
|
5077
|
+
Comment the current selection using block comments.
|
|
5078
|
+
*/
|
|
5079
|
+
const blockComment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeBlockComment, 1 /* Comment */)));
|
|
5080
|
+
/**
|
|
5081
|
+
Uncomment the current selection using block comments.
|
|
5082
|
+
*/
|
|
5083
|
+
const blockUncomment = /*@__PURE__*/(/* unused pure expression or super */ null && (command(changeBlockComment, 2 /* Uncomment */)));
|
|
5084
|
+
/**
|
|
5085
|
+
Comment or uncomment the lines around the current selection using
|
|
5086
|
+
block comments.
|
|
5087
|
+
*/
|
|
5088
|
+
const toggleBlockCommentByLine = /*@__PURE__*/(/* unused pure expression or super */ null && (command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* Toggle */)));
|
|
5089
|
+
function getConfig(state, pos = state.selection.main.head) {
|
|
5090
|
+
let data = state.languageDataAt("commentTokens", pos);
|
|
5091
|
+
return data.length ? data[0] : {};
|
|
5092
|
+
}
|
|
5093
|
+
const SearchMargin = 50;
|
|
5094
|
+
/**
|
|
5095
|
+
Determines if the given range is block-commented in the given
|
|
5096
|
+
state.
|
|
5097
|
+
*/
|
|
5098
|
+
function findBlockComment(state, { open, close }, from, to) {
|
|
5099
|
+
let textBefore = state.sliceDoc(from - SearchMargin, from);
|
|
5100
|
+
let textAfter = state.sliceDoc(to, to + SearchMargin);
|
|
5101
|
+
let spaceBefore = /\s*$/.exec(textBefore)[0].length, spaceAfter = /^\s*/.exec(textAfter)[0].length;
|
|
5102
|
+
let beforeOff = textBefore.length - spaceBefore;
|
|
5103
|
+
if (textBefore.slice(beforeOff - open.length, beforeOff) == open &&
|
|
5104
|
+
textAfter.slice(spaceAfter, spaceAfter + close.length) == close) {
|
|
5105
|
+
return { open: { pos: from - spaceBefore, margin: spaceBefore && 1 },
|
|
5106
|
+
close: { pos: to + spaceAfter, margin: spaceAfter && 1 } };
|
|
5107
|
+
}
|
|
5108
|
+
let startText, endText;
|
|
5109
|
+
if (to - from <= 2 * SearchMargin) {
|
|
5110
|
+
startText = endText = state.sliceDoc(from, to);
|
|
5111
|
+
}
|
|
5112
|
+
else {
|
|
5113
|
+
startText = state.sliceDoc(from, from + SearchMargin);
|
|
5114
|
+
endText = state.sliceDoc(to - SearchMargin, to);
|
|
5115
|
+
}
|
|
5116
|
+
let startSpace = /^\s*/.exec(startText)[0].length, endSpace = /\s*$/.exec(endText)[0].length;
|
|
5117
|
+
let endOff = endText.length - endSpace - close.length;
|
|
5118
|
+
if (startText.slice(startSpace, startSpace + open.length) == open &&
|
|
5119
|
+
endText.slice(endOff, endOff + close.length) == close) {
|
|
5120
|
+
return { open: { pos: from + startSpace + open.length,
|
|
5121
|
+
margin: /\s/.test(startText.charAt(startSpace + open.length)) ? 1 : 0 },
|
|
5122
|
+
close: { pos: to - endSpace - close.length,
|
|
5123
|
+
margin: /\s/.test(endText.charAt(endOff - 1)) ? 1 : 0 } };
|
|
5124
|
+
}
|
|
5125
|
+
return null;
|
|
5126
|
+
}
|
|
5127
|
+
function selectedLineRanges(state) {
|
|
5128
|
+
let ranges = [];
|
|
5129
|
+
for (let r of state.selection.ranges) {
|
|
5130
|
+
let fromLine = state.doc.lineAt(r.from);
|
|
5131
|
+
let toLine = r.to <= fromLine.to ? fromLine : state.doc.lineAt(r.to);
|
|
5132
|
+
let last = ranges.length - 1;
|
|
5133
|
+
if (last >= 0 && ranges[last].to > fromLine.from)
|
|
5134
|
+
ranges[last].to = toLine.to;
|
|
5135
|
+
else
|
|
5136
|
+
ranges.push({ from: fromLine.from, to: toLine.to });
|
|
5137
|
+
}
|
|
5138
|
+
return ranges;
|
|
5139
|
+
}
|
|
5140
|
+
// Performs toggle, comment and uncomment of block comments in
|
|
5141
|
+
// languages that support them.
|
|
5142
|
+
function changeBlockComment(option, state, ranges = state.selection.ranges) {
|
|
5143
|
+
let tokens = ranges.map(r => getConfig(state, r.from).block);
|
|
5144
|
+
if (!tokens.every(c => c))
|
|
5145
|
+
return null;
|
|
5146
|
+
let comments = ranges.map((r, i) => findBlockComment(state, tokens[i], r.from, r.to));
|
|
5147
|
+
if (option != 2 /* Uncomment */ && !comments.every(c => c)) {
|
|
5148
|
+
return { changes: state.changes(ranges.map((range, i) => {
|
|
5149
|
+
if (comments[i])
|
|
5150
|
+
return [];
|
|
5151
|
+
return [{ from: range.from, insert: tokens[i].open + " " }, { from: range.to, insert: " " + tokens[i].close }];
|
|
5152
|
+
})) };
|
|
5153
|
+
}
|
|
5154
|
+
else if (option != 1 /* Comment */ && comments.some(c => c)) {
|
|
5155
|
+
let changes = [];
|
|
5156
|
+
for (let i = 0, comment; i < comments.length; i++)
|
|
5157
|
+
if (comment = comments[i]) {
|
|
5158
|
+
let token = tokens[i], { open, close } = comment;
|
|
5159
|
+
changes.push({ from: open.pos - token.open.length, to: open.pos + open.margin }, { from: close.pos - close.margin, to: close.pos + token.close.length });
|
|
5160
|
+
}
|
|
5161
|
+
return { changes };
|
|
5162
|
+
}
|
|
5163
|
+
return null;
|
|
5164
|
+
}
|
|
5165
|
+
// Performs toggle, comment and uncomment of line comments.
|
|
5166
|
+
function changeLineComment(option, state, ranges = state.selection.ranges) {
|
|
5167
|
+
let lines = [];
|
|
5168
|
+
let prevLine = -1;
|
|
5169
|
+
for (let { from, to } of ranges) {
|
|
5170
|
+
let startI = lines.length, minIndent = 1e9;
|
|
5171
|
+
for (let pos = from; pos <= to;) {
|
|
5172
|
+
let line = state.doc.lineAt(pos);
|
|
5173
|
+
if (line.from > prevLine && (from == to || to > line.from)) {
|
|
5174
|
+
prevLine = line.from;
|
|
5175
|
+
let token = getConfig(state, pos).line;
|
|
5176
|
+
if (!token)
|
|
5177
|
+
continue;
|
|
5178
|
+
let indent = /^\s*/.exec(line.text)[0].length;
|
|
5179
|
+
let empty = indent == line.length;
|
|
5180
|
+
let comment = line.text.slice(indent, indent + token.length) == token ? indent : -1;
|
|
5181
|
+
if (indent < line.text.length && indent < minIndent)
|
|
5182
|
+
minIndent = indent;
|
|
5183
|
+
lines.push({ line, comment, token, indent, empty, single: false });
|
|
5184
|
+
}
|
|
5185
|
+
pos = line.to + 1;
|
|
5186
|
+
}
|
|
5187
|
+
if (minIndent < 1e9)
|
|
5188
|
+
for (let i = startI; i < lines.length; i++)
|
|
5189
|
+
if (lines[i].indent < lines[i].line.text.length)
|
|
5190
|
+
lines[i].indent = minIndent;
|
|
5191
|
+
if (lines.length == startI + 1)
|
|
5192
|
+
lines[startI].single = true;
|
|
5193
|
+
}
|
|
5194
|
+
if (option != 2 /* Uncomment */ && lines.some(l => l.comment < 0 && (!l.empty || l.single))) {
|
|
5195
|
+
let changes = [];
|
|
5196
|
+
for (let { line, token, indent, empty, single } of lines)
|
|
5197
|
+
if (single || !empty)
|
|
5198
|
+
changes.push({ from: line.from + indent, insert: token + " " });
|
|
5199
|
+
let changeSet = state.changes(changes);
|
|
5200
|
+
return { changes: changeSet, selection: state.selection.map(changeSet, 1) };
|
|
5201
|
+
}
|
|
5202
|
+
else if (option != 1 /* Comment */ && lines.some(l => l.comment >= 0)) {
|
|
5203
|
+
let changes = [];
|
|
5204
|
+
for (let { line, comment, token } of lines)
|
|
5205
|
+
if (comment >= 0) {
|
|
5206
|
+
let from = line.from + comment, to = from + token.length;
|
|
5207
|
+
if (line.text[to - line.from] == " ")
|
|
5208
|
+
to++;
|
|
5209
|
+
changes.push({ from, to });
|
|
5210
|
+
}
|
|
5211
|
+
return { changes };
|
|
5212
|
+
}
|
|
5213
|
+
return null;
|
|
5214
|
+
}
|
|
5215
|
+
|
|
5216
|
+
const fromHistory = /*@__PURE__*/state_.Annotation.define();
|
|
5217
|
+
/**
|
|
5218
|
+
Transaction annotation that will prevent that transaction from
|
|
5219
|
+
being combined with other transactions in the undo history. Given
|
|
5220
|
+
`"before"`, it'll prevent merging with previous transactions. With
|
|
5221
|
+
`"after"`, subsequent transactions won't be combined with this
|
|
5222
|
+
one. With `"full"`, the transaction is isolated on both sides.
|
|
5223
|
+
*/
|
|
5224
|
+
const isolateHistory = /*@__PURE__*/state_.Annotation.define();
|
|
5225
|
+
/**
|
|
5226
|
+
This facet provides a way to register functions that, given a
|
|
5227
|
+
transaction, provide a set of effects that the history should
|
|
5228
|
+
store when inverting the transaction. This can be used to
|
|
5229
|
+
integrate some kinds of effects in the history, so that they can
|
|
5230
|
+
be undone (and redone again).
|
|
5231
|
+
*/
|
|
5232
|
+
const invertedEffects = /*@__PURE__*/state_.Facet.define();
|
|
5233
|
+
const historyConfig = /*@__PURE__*/state_.Facet.define({
|
|
5234
|
+
combine(configs) {
|
|
5235
|
+
return (0,state_.combineConfig)(configs, {
|
|
5236
|
+
minDepth: 100,
|
|
5237
|
+
newGroupDelay: 500
|
|
5238
|
+
}, { minDepth: Math.max, newGroupDelay: Math.min });
|
|
5239
|
+
}
|
|
5240
|
+
});
|
|
5241
|
+
function changeEnd(changes) {
|
|
5242
|
+
let end = 0;
|
|
5243
|
+
changes.iterChangedRanges((_, to) => end = to);
|
|
5244
|
+
return end;
|
|
5245
|
+
}
|
|
5246
|
+
const historyField_ = /*@__PURE__*/state_.StateField.define({
|
|
5247
|
+
create() {
|
|
5248
|
+
return HistoryState.empty;
|
|
5249
|
+
},
|
|
5250
|
+
update(state, tr) {
|
|
5251
|
+
let config = tr.state.facet(historyConfig);
|
|
5252
|
+
let fromHist = tr.annotation(fromHistory);
|
|
5253
|
+
if (fromHist) {
|
|
5254
|
+
let selection = tr.docChanged ? state_.EditorSelection.single(changeEnd(tr.changes)) : undefined;
|
|
5255
|
+
let item = HistEvent.fromTransaction(tr, selection), from = fromHist.side;
|
|
5256
|
+
let other = from == 0 /* Done */ ? state.undone : state.done;
|
|
5257
|
+
if (item)
|
|
5258
|
+
other = updateBranch(other, other.length, config.minDepth, item);
|
|
5259
|
+
else
|
|
5260
|
+
other = addSelection(other, tr.startState.selection);
|
|
5261
|
+
return new HistoryState(from == 0 /* Done */ ? fromHist.rest : other, from == 0 /* Done */ ? other : fromHist.rest);
|
|
5262
|
+
}
|
|
5263
|
+
let isolate = tr.annotation(isolateHistory);
|
|
5264
|
+
if (isolate == "full" || isolate == "before")
|
|
5265
|
+
state = state.isolate();
|
|
5266
|
+
if (tr.annotation(state_.Transaction.addToHistory) === false)
|
|
5267
|
+
return !tr.changes.empty ? state.addMapping(tr.changes.desc) : state;
|
|
5268
|
+
let event = HistEvent.fromTransaction(tr);
|
|
5269
|
+
let time = tr.annotation(state_.Transaction.time), userEvent = tr.annotation(state_.Transaction.userEvent);
|
|
5270
|
+
if (event)
|
|
5271
|
+
state = state.addChanges(event, time, userEvent, config.newGroupDelay, config.minDepth);
|
|
5272
|
+
else if (tr.selection)
|
|
5273
|
+
state = state.addSelection(tr.startState.selection, time, userEvent, config.newGroupDelay);
|
|
5274
|
+
if (isolate == "full" || isolate == "after")
|
|
5275
|
+
state = state.isolate();
|
|
5276
|
+
return state;
|
|
5277
|
+
},
|
|
5278
|
+
toJSON(value) {
|
|
5279
|
+
return { done: value.done.map(e => e.toJSON()), undone: value.undone.map(e => e.toJSON()) };
|
|
5280
|
+
},
|
|
5281
|
+
fromJSON(json) {
|
|
5282
|
+
return new HistoryState(json.done.map(HistEvent.fromJSON), json.undone.map(HistEvent.fromJSON));
|
|
5283
|
+
}
|
|
5284
|
+
});
|
|
5285
|
+
/**
|
|
5286
|
+
Create a history extension with the given configuration.
|
|
5287
|
+
*/
|
|
5288
|
+
function dist_history(config = {}) {
|
|
5289
|
+
return [
|
|
5290
|
+
historyField_,
|
|
5291
|
+
historyConfig.of(config),
|
|
5292
|
+
EditorView.domEventHandlers({
|
|
5293
|
+
beforeinput(e, view) {
|
|
5294
|
+
let command = e.inputType == "historyUndo" ? undo : e.inputType == "historyRedo" ? redo : null;
|
|
5295
|
+
if (!command)
|
|
5296
|
+
return false;
|
|
5297
|
+
e.preventDefault();
|
|
5298
|
+
return command(view);
|
|
5299
|
+
}
|
|
5300
|
+
})
|
|
5301
|
+
];
|
|
5302
|
+
}
|
|
5303
|
+
/**
|
|
5304
|
+
The state field used to store the history data. Should probably
|
|
5305
|
+
only be used when you want to
|
|
5306
|
+
[serialize](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) or
|
|
5307
|
+
[deserialize](https://codemirror.net/6/docs/ref/#state.EditorState^fromJSON) state objects in a way
|
|
5308
|
+
that preserves history.
|
|
5309
|
+
*/
|
|
5310
|
+
const historyField = (/* unused pure expression or super */ null && (historyField_));
|
|
5311
|
+
function cmd(side, selection) {
|
|
5312
|
+
return function ({ state, dispatch }) {
|
|
5313
|
+
if (!selection && state.readOnly)
|
|
5314
|
+
return false;
|
|
5315
|
+
let historyState = state.field(historyField_, false);
|
|
5316
|
+
if (!historyState)
|
|
5317
|
+
return false;
|
|
5318
|
+
let tr = historyState.pop(side, state, selection);
|
|
5319
|
+
if (!tr)
|
|
5320
|
+
return false;
|
|
5321
|
+
dispatch(tr);
|
|
5322
|
+
return true;
|
|
5323
|
+
};
|
|
5324
|
+
}
|
|
5325
|
+
/**
|
|
5326
|
+
Undo a single group of history events. Returns false if no group
|
|
5327
|
+
was available.
|
|
5328
|
+
*/
|
|
5329
|
+
const undo = /*@__PURE__*/cmd(0 /* Done */, false);
|
|
5330
|
+
/**
|
|
5331
|
+
Redo a group of history events. Returns false if no group was
|
|
5332
|
+
available.
|
|
5333
|
+
*/
|
|
5334
|
+
const redo = /*@__PURE__*/cmd(1 /* Undone */, false);
|
|
5335
|
+
/**
|
|
5336
|
+
Undo a change or selection change.
|
|
5337
|
+
*/
|
|
5338
|
+
const undoSelection = /*@__PURE__*/cmd(0 /* Done */, true);
|
|
5339
|
+
/**
|
|
5340
|
+
Redo a change or selection change.
|
|
5341
|
+
*/
|
|
5342
|
+
const redoSelection = /*@__PURE__*/cmd(1 /* Undone */, true);
|
|
5343
|
+
function depth(side) {
|
|
5344
|
+
return function (state) {
|
|
5345
|
+
let histState = state.field(historyField_, false);
|
|
5346
|
+
if (!histState)
|
|
5347
|
+
return 0;
|
|
5348
|
+
let branch = side == 0 /* Done */ ? histState.done : histState.undone;
|
|
5349
|
+
return branch.length - (branch.length && !branch[0].changes ? 1 : 0);
|
|
5350
|
+
};
|
|
5351
|
+
}
|
|
5352
|
+
/**
|
|
5353
|
+
The amount of undoable change events available in a given state.
|
|
5354
|
+
*/
|
|
5355
|
+
const undoDepth = /*@__PURE__*/(/* unused pure expression or super */ null && (depth(0 /* Done */)));
|
|
5356
|
+
/**
|
|
5357
|
+
The amount of redoable change events available in a given state.
|
|
5358
|
+
*/
|
|
5359
|
+
const redoDepth = /*@__PURE__*/(/* unused pure expression or super */ null && (depth(1 /* Undone */)));
|
|
5360
|
+
// History events store groups of changes or effects that need to be
|
|
5361
|
+
// undone/redone together.
|
|
5362
|
+
class HistEvent {
|
|
5363
|
+
constructor(
|
|
5364
|
+
// The changes in this event. Normal events hold at least one
|
|
5365
|
+
// change or effect. But it may be necessary to store selection
|
|
5366
|
+
// events before the first change, in which case a special type of
|
|
5367
|
+
// instance is created which doesn't hold any changes, with
|
|
5368
|
+
// changes == startSelection == undefined
|
|
5369
|
+
changes,
|
|
5370
|
+
// The effects associated with this event
|
|
5371
|
+
effects, mapped,
|
|
5372
|
+
// The selection before this event
|
|
5373
|
+
startSelection,
|
|
5374
|
+
// Stores selection changes after this event, to be used for
|
|
5375
|
+
// selection undo/redo.
|
|
5376
|
+
selectionsAfter) {
|
|
5377
|
+
this.changes = changes;
|
|
5378
|
+
this.effects = effects;
|
|
5379
|
+
this.mapped = mapped;
|
|
5380
|
+
this.startSelection = startSelection;
|
|
5381
|
+
this.selectionsAfter = selectionsAfter;
|
|
5382
|
+
}
|
|
5383
|
+
setSelAfter(after) {
|
|
5384
|
+
return new HistEvent(this.changes, this.effects, this.mapped, this.startSelection, after);
|
|
5385
|
+
}
|
|
5386
|
+
toJSON() {
|
|
5387
|
+
var _a, _b, _c;
|
|
5388
|
+
return {
|
|
5389
|
+
changes: (_a = this.changes) === null || _a === void 0 ? void 0 : _a.toJSON(),
|
|
5390
|
+
mapped: (_b = this.mapped) === null || _b === void 0 ? void 0 : _b.toJSON(),
|
|
5391
|
+
startSelection: (_c = this.startSelection) === null || _c === void 0 ? void 0 : _c.toJSON(),
|
|
5392
|
+
selectionsAfter: this.selectionsAfter.map(s => s.toJSON())
|
|
5393
|
+
};
|
|
5394
|
+
}
|
|
5395
|
+
static fromJSON(json) {
|
|
5396
|
+
return new HistEvent(json.changes && state_.ChangeSet.fromJSON(json.changes), [], json.mapped && state_.ChangeDesc.fromJSON(json.mapped), json.startSelection && state_.EditorSelection.fromJSON(json.startSelection), json.selectionsAfter.map(state_.EditorSelection.fromJSON));
|
|
5397
|
+
}
|
|
5398
|
+
// This does not check `addToHistory` and such, it assumes the
|
|
5399
|
+
// transaction needs to be converted to an item. Returns null when
|
|
5400
|
+
// there are no changes or effects in the transaction.
|
|
5401
|
+
static fromTransaction(tr, selection) {
|
|
5402
|
+
let effects = none;
|
|
5403
|
+
for (let invert of tr.startState.facet(invertedEffects)) {
|
|
5404
|
+
let result = invert(tr);
|
|
5405
|
+
if (result.length)
|
|
5406
|
+
effects = effects.concat(result);
|
|
5407
|
+
}
|
|
5408
|
+
if (!effects.length && tr.changes.empty)
|
|
5409
|
+
return null;
|
|
5410
|
+
return new HistEvent(tr.changes.invert(tr.startState.doc), effects, undefined, selection || tr.startState.selection, none);
|
|
5411
|
+
}
|
|
5412
|
+
static selection(selections) {
|
|
5413
|
+
return new HistEvent(undefined, none, undefined, undefined, selections);
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
function updateBranch(branch, to, maxLen, newEvent) {
|
|
5417
|
+
let start = to + 1 > maxLen + 20 ? to - maxLen - 1 : 0;
|
|
5418
|
+
let newBranch = branch.slice(start, to);
|
|
5419
|
+
newBranch.push(newEvent);
|
|
5420
|
+
return newBranch;
|
|
5421
|
+
}
|
|
5422
|
+
function isAdjacent(a, b) {
|
|
5423
|
+
let ranges = [], isAdjacent = false;
|
|
5424
|
+
a.iterChangedRanges((f, t) => ranges.push(f, t));
|
|
5425
|
+
b.iterChangedRanges((_f, _t, f, t) => {
|
|
5426
|
+
for (let i = 0; i < ranges.length;) {
|
|
5427
|
+
let from = ranges[i++], to = ranges[i++];
|
|
5428
|
+
if (t >= from && f <= to)
|
|
5429
|
+
isAdjacent = true;
|
|
5430
|
+
}
|
|
5431
|
+
});
|
|
5432
|
+
return isAdjacent;
|
|
5433
|
+
}
|
|
5434
|
+
function eqSelectionShape(a, b) {
|
|
5435
|
+
return a.ranges.length == b.ranges.length &&
|
|
5436
|
+
a.ranges.filter((r, i) => r.empty != b.ranges[i].empty).length === 0;
|
|
5437
|
+
}
|
|
5438
|
+
function conc(a, b) {
|
|
5439
|
+
return !a.length ? b : !b.length ? a : a.concat(b);
|
|
5440
|
+
}
|
|
5441
|
+
const none = [];
|
|
5442
|
+
const MaxSelectionsPerEvent = 200;
|
|
5443
|
+
function addSelection(branch, selection) {
|
|
5444
|
+
if (!branch.length) {
|
|
5445
|
+
return [HistEvent.selection([selection])];
|
|
5446
|
+
}
|
|
5447
|
+
else {
|
|
5448
|
+
let lastEvent = branch[branch.length - 1];
|
|
5449
|
+
let sels = lastEvent.selectionsAfter.slice(Math.max(0, lastEvent.selectionsAfter.length - MaxSelectionsPerEvent));
|
|
5450
|
+
if (sels.length && sels[sels.length - 1].eq(selection))
|
|
5451
|
+
return branch;
|
|
5452
|
+
sels.push(selection);
|
|
5453
|
+
return updateBranch(branch, branch.length - 1, 1e9, lastEvent.setSelAfter(sels));
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
// Assumes the top item has one or more selectionAfter values
|
|
5457
|
+
function popSelection(branch) {
|
|
5458
|
+
let last = branch[branch.length - 1];
|
|
5459
|
+
let newBranch = branch.slice();
|
|
5460
|
+
newBranch[branch.length - 1] = last.setSelAfter(last.selectionsAfter.slice(0, last.selectionsAfter.length - 1));
|
|
5461
|
+
return newBranch;
|
|
5462
|
+
}
|
|
5463
|
+
// Add a mapping to the top event in the given branch. If this maps
|
|
5464
|
+
// away all the changes and effects in that item, drop it and
|
|
5465
|
+
// propagate the mapping to the next item.
|
|
5466
|
+
function addMappingToBranch(branch, mapping) {
|
|
5467
|
+
if (!branch.length)
|
|
5468
|
+
return branch;
|
|
5469
|
+
let length = branch.length, selections = none;
|
|
5470
|
+
while (length) {
|
|
5471
|
+
let event = mapEvent(branch[length - 1], mapping, selections);
|
|
5472
|
+
if (event.changes && !event.changes.empty || event.effects.length) { // Event survived mapping
|
|
5473
|
+
let result = branch.slice(0, length);
|
|
5474
|
+
result[length - 1] = event;
|
|
5475
|
+
return result;
|
|
5476
|
+
}
|
|
5477
|
+
else { // Drop this event, since there's no changes or effects left
|
|
5478
|
+
mapping = event.mapped;
|
|
5479
|
+
length--;
|
|
5480
|
+
selections = event.selectionsAfter;
|
|
5481
|
+
}
|
|
5482
|
+
}
|
|
5483
|
+
return selections.length ? [HistEvent.selection(selections)] : none;
|
|
5484
|
+
}
|
|
5485
|
+
function mapEvent(event, mapping, extraSelections) {
|
|
5486
|
+
let selections = conc(event.selectionsAfter.length ? event.selectionsAfter.map(s => s.map(mapping)) : none, extraSelections);
|
|
5487
|
+
// Change-less events don't store mappings (they are always the last event in a branch)
|
|
5488
|
+
if (!event.changes)
|
|
5489
|
+
return HistEvent.selection(selections);
|
|
5490
|
+
let mappedChanges = event.changes.map(mapping), before = mapping.mapDesc(event.changes, true);
|
|
5491
|
+
let fullMapping = event.mapped ? event.mapped.composeDesc(before) : before;
|
|
5492
|
+
return new HistEvent(mappedChanges, state_.StateEffect.mapEffects(event.effects, mapping), fullMapping, event.startSelection.map(before), selections);
|
|
5493
|
+
}
|
|
5494
|
+
const joinableUserEvent = /^(input\.type|delete)($|\.)/;
|
|
5495
|
+
class HistoryState {
|
|
5496
|
+
constructor(done, undone, prevTime = 0, prevUserEvent = undefined) {
|
|
5497
|
+
this.done = done;
|
|
5498
|
+
this.undone = undone;
|
|
5499
|
+
this.prevTime = prevTime;
|
|
5500
|
+
this.prevUserEvent = prevUserEvent;
|
|
5501
|
+
}
|
|
5502
|
+
isolate() {
|
|
5503
|
+
return this.prevTime ? new HistoryState(this.done, this.undone) : this;
|
|
5504
|
+
}
|
|
5505
|
+
addChanges(event, time, userEvent, newGroupDelay, maxLen) {
|
|
5506
|
+
let done = this.done, lastEvent = done[done.length - 1];
|
|
5507
|
+
if (lastEvent && lastEvent.changes && !lastEvent.changes.empty && event.changes &&
|
|
5508
|
+
(!userEvent || joinableUserEvent.test(userEvent)) &&
|
|
5509
|
+
((!lastEvent.selectionsAfter.length &&
|
|
5510
|
+
time - this.prevTime < newGroupDelay &&
|
|
5511
|
+
isAdjacent(lastEvent.changes, event.changes)) ||
|
|
5512
|
+
// For compose (but not compose.start) events, always join with previous event
|
|
5513
|
+
userEvent == "input.type.compose")) {
|
|
5514
|
+
done = updateBranch(done, done.length - 1, maxLen, new HistEvent(event.changes.compose(lastEvent.changes), conc(event.effects, lastEvent.effects), lastEvent.mapped, lastEvent.startSelection, none));
|
|
5515
|
+
}
|
|
5516
|
+
else {
|
|
5517
|
+
done = updateBranch(done, done.length, maxLen, event);
|
|
5518
|
+
}
|
|
5519
|
+
return new HistoryState(done, none, time, userEvent);
|
|
5520
|
+
}
|
|
5521
|
+
addSelection(selection, time, userEvent, newGroupDelay) {
|
|
5522
|
+
let last = this.done.length ? this.done[this.done.length - 1].selectionsAfter : none;
|
|
5523
|
+
if (last.length > 0 &&
|
|
5524
|
+
time - this.prevTime < newGroupDelay &&
|
|
5525
|
+
userEvent == this.prevUserEvent && userEvent && /^select($|\.)/.test(userEvent) &&
|
|
5526
|
+
eqSelectionShape(last[last.length - 1], selection))
|
|
5527
|
+
return this;
|
|
5528
|
+
return new HistoryState(addSelection(this.done, selection), this.undone, time, userEvent);
|
|
5529
|
+
}
|
|
5530
|
+
addMapping(mapping) {
|
|
5531
|
+
return new HistoryState(addMappingToBranch(this.done, mapping), addMappingToBranch(this.undone, mapping), this.prevTime, this.prevUserEvent);
|
|
5532
|
+
}
|
|
5533
|
+
pop(side, state, selection) {
|
|
5534
|
+
let branch = side == 0 /* Done */ ? this.done : this.undone;
|
|
5535
|
+
if (branch.length == 0)
|
|
5536
|
+
return null;
|
|
5537
|
+
let event = branch[branch.length - 1];
|
|
5538
|
+
if (selection && event.selectionsAfter.length) {
|
|
5539
|
+
return state.update({
|
|
5540
|
+
selection: event.selectionsAfter[event.selectionsAfter.length - 1],
|
|
5541
|
+
annotations: fromHistory.of({ side, rest: popSelection(branch) }),
|
|
5542
|
+
userEvent: side == 0 /* Done */ ? "select.undo" : "select.redo",
|
|
5543
|
+
scrollIntoView: true
|
|
5544
|
+
});
|
|
5545
|
+
}
|
|
5546
|
+
else if (!event.changes) {
|
|
5547
|
+
return null;
|
|
5548
|
+
}
|
|
5549
|
+
else {
|
|
5550
|
+
let rest = branch.length == 1 ? none : branch.slice(0, branch.length - 1);
|
|
5551
|
+
if (event.mapped)
|
|
5552
|
+
rest = addMappingToBranch(rest, event.mapped);
|
|
5553
|
+
return state.update({
|
|
5554
|
+
changes: event.changes,
|
|
5555
|
+
selection: event.startSelection,
|
|
5556
|
+
effects: event.effects,
|
|
5557
|
+
annotations: fromHistory.of({ side, rest }),
|
|
5558
|
+
filter: false,
|
|
5559
|
+
userEvent: side == 0 /* Done */ ? "undo" : "redo",
|
|
5560
|
+
scrollIntoView: true
|
|
5561
|
+
});
|
|
5562
|
+
}
|
|
5563
|
+
}
|
|
5564
|
+
}
|
|
5565
|
+
HistoryState.empty = /*@__PURE__*/new HistoryState(none, none);
|
|
5566
|
+
/**
|
|
5567
|
+
Default key bindings for the undo history.
|
|
5568
|
+
|
|
5569
|
+
- Mod-z: [`undo`](https://codemirror.net/6/docs/ref/#commands.undo).
|
|
5570
|
+
- Mod-y (Mod-Shift-z on macOS): [`redo`](https://codemirror.net/6/docs/ref/#commands.redo).
|
|
5571
|
+
- Mod-u: [`undoSelection`](https://codemirror.net/6/docs/ref/#commands.undoSelection).
|
|
5572
|
+
- Alt-u (Mod-Shift-u on macOS): [`redoSelection`](https://codemirror.net/6/docs/ref/#commands.redoSelection).
|
|
5573
|
+
*/
|
|
5574
|
+
const historyKeymap = [
|
|
5575
|
+
{ key: "Mod-z", run: undo, preventDefault: true },
|
|
5576
|
+
{ key: "Mod-y", mac: "Mod-Shift-z", run: redo, preventDefault: true },
|
|
5577
|
+
{ key: "Mod-u", run: undoSelection, preventDefault: true },
|
|
5578
|
+
{ key: "Alt-u", mac: "Mod-Shift-u", run: redoSelection, preventDefault: true }
|
|
5579
|
+
];
|
|
5580
|
+
|
|
5581
|
+
function updateSel(sel, by) {
|
|
5582
|
+
return state_.EditorSelection.create(sel.ranges.map(by), sel.mainIndex);
|
|
5583
|
+
}
|
|
5584
|
+
function setSel(state, selection) {
|
|
5585
|
+
return state.update({ selection, scrollIntoView: true, userEvent: "select" });
|
|
5586
|
+
}
|
|
5587
|
+
function moveSel({ state, dispatch }, how) {
|
|
5588
|
+
let selection = updateSel(state.selection, how);
|
|
5589
|
+
if (selection.eq(state.selection))
|
|
5590
|
+
return false;
|
|
5591
|
+
dispatch(setSel(state, selection));
|
|
5592
|
+
return true;
|
|
5593
|
+
}
|
|
5594
|
+
function rangeEnd(range, forward) {
|
|
5595
|
+
return state_.EditorSelection.cursor(forward ? range.to : range.from);
|
|
5596
|
+
}
|
|
5597
|
+
function cursorByChar(view, forward) {
|
|
5598
|
+
return moveSel(view, range => range.empty ? view.moveByChar(range, forward) : rangeEnd(range, forward));
|
|
5599
|
+
}
|
|
5600
|
+
function ltrAtCursor(view) {
|
|
5601
|
+
return view.textDirectionAt(view.state.selection.main.head) == view_.Direction.LTR;
|
|
5602
|
+
}
|
|
5603
|
+
/**
|
|
5604
|
+
Move the selection one character to the left (which is backward in
|
|
5605
|
+
left-to-right text, forward in right-to-left text).
|
|
5606
|
+
*/
|
|
5607
|
+
const cursorCharLeft = view => cursorByChar(view, !ltrAtCursor(view));
|
|
5608
|
+
/**
|
|
5609
|
+
Move the selection one character to the right.
|
|
5610
|
+
*/
|
|
5611
|
+
const cursorCharRight = view => cursorByChar(view, ltrAtCursor(view));
|
|
5612
|
+
/**
|
|
5613
|
+
Move the selection one character forward.
|
|
5614
|
+
*/
|
|
5615
|
+
const cursorCharForward = view => cursorByChar(view, true);
|
|
5616
|
+
/**
|
|
5617
|
+
Move the selection one character backward.
|
|
5618
|
+
*/
|
|
5619
|
+
const cursorCharBackward = view => cursorByChar(view, false);
|
|
5620
|
+
function cursorByGroup(view, forward) {
|
|
5621
|
+
return moveSel(view, range => range.empty ? view.moveByGroup(range, forward) : rangeEnd(range, forward));
|
|
5622
|
+
}
|
|
5623
|
+
/**
|
|
5624
|
+
Move the selection to the left across one group of word or
|
|
5625
|
+
non-word (but also non-space) characters.
|
|
5626
|
+
*/
|
|
5627
|
+
const cursorGroupLeft = view => cursorByGroup(view, !ltrAtCursor(view));
|
|
5628
|
+
/**
|
|
5629
|
+
Move the selection one group to the right.
|
|
5630
|
+
*/
|
|
5631
|
+
const cursorGroupRight = view => cursorByGroup(view, ltrAtCursor(view));
|
|
5632
|
+
/**
|
|
5633
|
+
Move the selection one group forward.
|
|
5634
|
+
*/
|
|
5635
|
+
const cursorGroupForward = view => cursorByGroup(view, true);
|
|
5636
|
+
/**
|
|
5637
|
+
Move the selection one group backward.
|
|
5638
|
+
*/
|
|
5639
|
+
const cursorGroupBackward = view => cursorByGroup(view, false);
|
|
5640
|
+
function moveBySubword(view, range, forward) {
|
|
5641
|
+
let categorize = view.state.charCategorizer(range.from);
|
|
5642
|
+
return view.moveByChar(range, forward, start => {
|
|
5643
|
+
let cat = CharCategory.Space, pos = range.from;
|
|
5644
|
+
let done = false, sawUpper = false, sawLower = false;
|
|
5645
|
+
let step = (next) => {
|
|
5646
|
+
if (done)
|
|
5647
|
+
return false;
|
|
5648
|
+
pos += forward ? next.length : -next.length;
|
|
5649
|
+
let nextCat = categorize(next), ahead;
|
|
5650
|
+
if (cat == CharCategory.Space)
|
|
5651
|
+
cat = nextCat;
|
|
5652
|
+
if (cat != nextCat)
|
|
5653
|
+
return false;
|
|
5654
|
+
if (cat == CharCategory.Word) {
|
|
5655
|
+
if (next.toLowerCase() == next) {
|
|
5656
|
+
if (!forward && sawUpper)
|
|
5657
|
+
return false;
|
|
5658
|
+
sawLower = true;
|
|
5659
|
+
}
|
|
5660
|
+
else if (sawLower) {
|
|
5661
|
+
if (forward)
|
|
5662
|
+
return false;
|
|
5663
|
+
done = true;
|
|
5664
|
+
}
|
|
5665
|
+
else {
|
|
5666
|
+
if (sawUpper && forward && categorize(ahead = view.state.sliceDoc(pos, pos + 1)) == CharCategory.Word &&
|
|
5667
|
+
ahead.toLowerCase() == ahead)
|
|
5668
|
+
return false;
|
|
5669
|
+
sawUpper = true;
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
return true;
|
|
5673
|
+
};
|
|
5674
|
+
step(start);
|
|
5675
|
+
return step;
|
|
5676
|
+
});
|
|
5677
|
+
}
|
|
5678
|
+
function cursorBySubword(view, forward) {
|
|
5679
|
+
return moveSel(view, range => range.empty ? moveBySubword(view, range, forward) : rangeEnd(range, forward));
|
|
5680
|
+
}
|
|
5681
|
+
/**
|
|
5682
|
+
Move the selection one group or camel-case subword forward.
|
|
3749
5683
|
*/
|
|
3750
5684
|
const cursorSubwordForward = view => cursorBySubword(view, true);
|
|
3751
5685
|
/**
|
|
@@ -3782,11 +5716,11 @@ function moveBySyntax(state, start, forward) {
|
|
|
3782
5716
|
/**
|
|
3783
5717
|
Move the cursor over the next syntactic element to the left.
|
|
3784
5718
|
*/
|
|
3785
|
-
const cursorSyntaxLeft = view => moveSel(view, range => moveBySyntax(view.state, range, view
|
|
5719
|
+
const cursorSyntaxLeft = view => moveSel(view, range => moveBySyntax(view.state, range, !ltrAtCursor(view)));
|
|
3786
5720
|
/**
|
|
3787
5721
|
Move the cursor over the next syntactic element to the right.
|
|
3788
5722
|
*/
|
|
3789
|
-
const cursorSyntaxRight = view => moveSel(view, range => moveBySyntax(view.state, range, view
|
|
5723
|
+
const cursorSyntaxRight = view => moveSel(view, range => moveBySyntax(view.state, range, ltrAtCursor(view)));
|
|
3790
5724
|
function cursorByLine(view, forward) {
|
|
3791
5725
|
return moveSel(view, range => {
|
|
3792
5726
|
if (!range.empty)
|
|
@@ -3805,17 +5739,18 @@ Move the selection one line down.
|
|
|
3805
5739
|
const cursorLineDown = view => cursorByLine(view, true);
|
|
3806
5740
|
function cursorByPage(view, forward) {
|
|
3807
5741
|
let { state } = view, selection = updateSel(state.selection, range => {
|
|
3808
|
-
return range.empty ? view.moveVertically(range, forward, view.dom.clientHeight
|
|
5742
|
+
return range.empty ? view.moveVertically(range, forward, Math.min(view.dom.clientHeight, innerHeight))
|
|
5743
|
+
: rangeEnd(range, forward);
|
|
3809
5744
|
});
|
|
3810
5745
|
if (selection.eq(state.selection))
|
|
3811
5746
|
return false;
|
|
3812
5747
|
let startPos = view.coordsAtPos(state.selection.main.head);
|
|
3813
5748
|
let scrollRect = view.scrollDOM.getBoundingClientRect();
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
});
|
|
5749
|
+
let effect;
|
|
5750
|
+
if (startPos && startPos.top > scrollRect.top && startPos.bottom < scrollRect.bottom &&
|
|
5751
|
+
startPos.top - scrollRect.top <= view.scrollDOM.scrollHeight - view.scrollDOM.scrollTop - view.scrollDOM.clientHeight)
|
|
5752
|
+
effect = view_.EditorView.scrollIntoView(selection.main.head, { y: "start", yMargin: startPos.top - scrollRect.top });
|
|
5753
|
+
view.dispatch(setSel(state, selection), { effects: effect });
|
|
3819
5754
|
return true;
|
|
3820
5755
|
}
|
|
3821
5756
|
/**
|
|
@@ -3901,11 +5836,11 @@ function selectByChar(view, forward) {
|
|
|
3901
5836
|
Move the selection head one character to the left, while leaving
|
|
3902
5837
|
the anchor in place.
|
|
3903
5838
|
*/
|
|
3904
|
-
const selectCharLeft = view => selectByChar(view, view
|
|
5839
|
+
const selectCharLeft = view => selectByChar(view, !ltrAtCursor(view));
|
|
3905
5840
|
/**
|
|
3906
5841
|
Move the selection head one character to the right.
|
|
3907
5842
|
*/
|
|
3908
|
-
const selectCharRight = view => selectByChar(view, view
|
|
5843
|
+
const selectCharRight = view => selectByChar(view, ltrAtCursor(view));
|
|
3909
5844
|
/**
|
|
3910
5845
|
Move the selection head one character forward.
|
|
3911
5846
|
*/
|
|
@@ -3921,11 +5856,11 @@ function selectByGroup(view, forward) {
|
|
|
3921
5856
|
Move the selection head one [group](https://codemirror.net/6/docs/ref/#commands.cursorGroupLeft) to
|
|
3922
5857
|
the left.
|
|
3923
5858
|
*/
|
|
3924
|
-
const selectGroupLeft = view => selectByGroup(view, view
|
|
5859
|
+
const selectGroupLeft = view => selectByGroup(view, !ltrAtCursor(view));
|
|
3925
5860
|
/**
|
|
3926
5861
|
Move the selection head one group to the right.
|
|
3927
5862
|
*/
|
|
3928
|
-
const selectGroupRight = view => selectByGroup(view, view
|
|
5863
|
+
const selectGroupRight = view => selectByGroup(view, ltrAtCursor(view));
|
|
3929
5864
|
/**
|
|
3930
5865
|
Move the selection head one group forward.
|
|
3931
5866
|
*/
|
|
@@ -3948,11 +5883,11 @@ const selectSubwordBackward = view => selectBySubword(view, false);
|
|
|
3948
5883
|
/**
|
|
3949
5884
|
Move the selection head over the next syntactic element to the left.
|
|
3950
5885
|
*/
|
|
3951
|
-
const selectSyntaxLeft = view => extendSel(view, range => moveBySyntax(view.state, range, view
|
|
5886
|
+
const selectSyntaxLeft = view => extendSel(view, range => moveBySyntax(view.state, range, !ltrAtCursor(view)));
|
|
3952
5887
|
/**
|
|
3953
5888
|
Move the selection head over the next syntactic element to the right.
|
|
3954
5889
|
*/
|
|
3955
|
-
const selectSyntaxRight = view => extendSel(view, range => moveBySyntax(view.state, range, view
|
|
5890
|
+
const selectSyntaxRight = view => extendSel(view, range => moveBySyntax(view.state, range, ltrAtCursor(view)));
|
|
3956
5891
|
function selectByLine(view, forward) {
|
|
3957
5892
|
return extendSel(view, range => view.moveVertically(range, forward));
|
|
3958
5893
|
}
|
|
@@ -3965,7 +5900,7 @@ Move the selection head one line down.
|
|
|
3965
5900
|
*/
|
|
3966
5901
|
const selectLineDown = view => selectByLine(view, true);
|
|
3967
5902
|
function selectByPage(view, forward) {
|
|
3968
|
-
return extendSel(view, range => view.moveVertically(range, forward, view.dom.clientHeight));
|
|
5903
|
+
return extendSel(view, range => view.moveVertically(range, forward, Math.min(view.dom.clientHeight, innerHeight)));
|
|
3969
5904
|
}
|
|
3970
5905
|
/**
|
|
3971
5906
|
Move the selection head one page up.
|
|
@@ -4093,7 +6028,7 @@ function deleteBy({ state, dispatch }, by) {
|
|
|
4093
6028
|
}
|
|
4094
6029
|
function skipAtomic(target, pos, forward) {
|
|
4095
6030
|
if (target instanceof view_.EditorView)
|
|
4096
|
-
for (let ranges of target.
|
|
6031
|
+
for (let ranges of target.state.facet(view_.EditorView.atomicRanges).map(f => f(target)))
|
|
4097
6032
|
ranges.between(pos, pos, (from, to) => {
|
|
4098
6033
|
if (from < pos && to > pos)
|
|
4099
6034
|
pos = forward ? to : from;
|
|
@@ -4106,13 +6041,13 @@ const deleteByChar = (target, forward) => deleteBy(target, pos => {
|
|
|
4106
6041
|
!/[^ \t]/.test(before = line.text.slice(0, pos - line.from))) {
|
|
4107
6042
|
if (before[before.length - 1] == "\t")
|
|
4108
6043
|
return pos - 1;
|
|
4109
|
-
let col =
|
|
6044
|
+
let col = (0,state_.countColumn)(before, state.tabSize), drop = col % getIndentUnit(state) || getIndentUnit(state);
|
|
4110
6045
|
for (let i = 0; i < drop && before[before.length - 1 - i] == " "; i++)
|
|
4111
6046
|
pos--;
|
|
4112
6047
|
targetPos = pos;
|
|
4113
6048
|
}
|
|
4114
6049
|
else {
|
|
4115
|
-
targetPos = findClusterBreak(line.text, pos - line.from, forward, forward) + line.from;
|
|
6050
|
+
targetPos = (0,state_.findClusterBreak)(line.text, pos - line.from, forward, forward) + line.from;
|
|
4116
6051
|
if (targetPos == pos && line.number != (forward ? state.doc.lines : 1))
|
|
4117
6052
|
targetPos += forward ? 1 : -1;
|
|
4118
6053
|
}
|
|
@@ -4136,7 +6071,7 @@ const deleteByGroup = (target, forward) => deleteBy(target, start => {
|
|
|
4136
6071
|
pos += forward ? 1 : -1;
|
|
4137
6072
|
break;
|
|
4138
6073
|
}
|
|
4139
|
-
let next = findClusterBreak(line.text, pos - line.from, forward) + line.from;
|
|
6074
|
+
let next = (0,state_.findClusterBreak)(line.text, pos - line.from, forward) + line.from;
|
|
4140
6075
|
let nextChar = line.text.slice(Math.min(pos, next) - line.from, Math.max(pos, next) - line.from);
|
|
4141
6076
|
let nextCat = categorize(nextChar);
|
|
4142
6077
|
if (cat != null && nextCat != cat)
|
|
@@ -4211,7 +6146,7 @@ const splitLine = ({ state, dispatch }) => {
|
|
|
4211
6146
|
if (state.readOnly)
|
|
4212
6147
|
return false;
|
|
4213
6148
|
let changes = state.changeByRange(range => {
|
|
4214
|
-
return { changes: { from: range.from, to: range.to, insert:
|
|
6149
|
+
return { changes: { from: range.from, to: range.to, insert: state_.Text.of(["", ""]) },
|
|
4215
6150
|
range: state_.EditorSelection.cursor(range.from) };
|
|
4216
6151
|
});
|
|
4217
6152
|
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "input" }));
|
|
@@ -4227,8 +6162,8 @@ const transposeChars = ({ state, dispatch }) => {
|
|
|
4227
6162
|
if (!range.empty || range.from == 0 || range.from == state.doc.length)
|
|
4228
6163
|
return { range };
|
|
4229
6164
|
let pos = range.from, line = state.doc.lineAt(pos);
|
|
4230
|
-
let from = pos == line.from ? pos - 1 : findClusterBreak(line.text, pos - line.from, false) + line.from;
|
|
4231
|
-
let to = pos == line.to ? pos + 1 : findClusterBreak(line.text, pos - line.from, true) + line.from;
|
|
6165
|
+
let from = pos == line.from ? pos - 1 : (0,state_.findClusterBreak)(line.text, pos - line.from, false) + line.from;
|
|
6166
|
+
let to = pos == line.to ? pos + 1 : (0,state_.findClusterBreak)(line.text, pos - line.from, true) + line.from;
|
|
4232
6167
|
return { changes: { from, to, insert: state.doc.slice(pos, to).append(state.doc.slice(from, pos)) },
|
|
4233
6168
|
range: state_.EditorSelection.cursor(to) };
|
|
4234
6169
|
});
|
|
@@ -4460,7 +6395,7 @@ const indentLess = ({ state, dispatch }) => {
|
|
|
4460
6395
|
let space = /^\s*/.exec(line.text)[0];
|
|
4461
6396
|
if (!space)
|
|
4462
6397
|
return;
|
|
4463
|
-
let col =
|
|
6398
|
+
let col = (0,state_.countColumn)(space, state.tabSize), keep = 0;
|
|
4464
6399
|
let insert = dist_indentString(state, Math.max(0, col - getIndentUnit(state)));
|
|
4465
6400
|
while (keep < space.length && keep < insert.length && space.charCodeAt(keep) == insert.charCodeAt(keep))
|
|
4466
6401
|
keep++;
|
|
@@ -4561,9 +6496,9 @@ const standardKeymap = /*@__PURE__*/(/* unused pure expression or super */ null
|
|
|
4561
6496
|
{ mac: "Ctrl-ArrowDown", run: cursorPageDown, shift: selectPageDown },
|
|
4562
6497
|
{ key: "PageUp", run: cursorPageUp, shift: selectPageUp },
|
|
4563
6498
|
{ key: "PageDown", run: cursorPageDown, shift: selectPageDown },
|
|
4564
|
-
{ key: "Home", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward },
|
|
6499
|
+
{ key: "Home", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward, preventDefault: true },
|
|
4565
6500
|
{ key: "Mod-Home", run: cursorDocStart, shift: selectDocStart },
|
|
4566
|
-
{ key: "End", run: cursorLineBoundaryForward, shift: selectLineBoundaryForward },
|
|
6501
|
+
{ key: "End", run: cursorLineBoundaryForward, shift: selectLineBoundaryForward, preventDefault: true },
|
|
4567
6502
|
{ key: "Mod-End", run: cursorDocEnd, shift: selectDocEnd },
|
|
4568
6503
|
{ key: "Enter", run: insertNewlineAndIndent },
|
|
4569
6504
|
{ key: "Mod-a", run: selectAll },
|
|
@@ -4593,6 +6528,8 @@ The default keymap. Includes all bindings from
|
|
|
4593
6528
|
- Ctrl-Alt-\\ (Cmd-Alt-\\ on macOS): [`indentSelection`](https://codemirror.net/6/docs/ref/#commands.indentSelection)
|
|
4594
6529
|
- Shift-Ctrl-k (Shift-Cmd-k on macOS): [`deleteLine`](https://codemirror.net/6/docs/ref/#commands.deleteLine)
|
|
4595
6530
|
- Shift-Ctrl-\\ (Shift-Cmd-\\ on macOS): [`cursorMatchingBracket`](https://codemirror.net/6/docs/ref/#commands.cursorMatchingBracket)
|
|
6531
|
+
- Ctrl-/ (Cmd-/ on macOS): [`toggleComment`](https://codemirror.net/6/docs/ref/#commands.toggleComment).
|
|
6532
|
+
- Shift-Alt-a: [`toggleBlockComment`](https://codemirror.net/6/docs/ref/#commands.toggleBlockComment).
|
|
4596
6533
|
*/
|
|
4597
6534
|
const defaultKeymap = /*@__PURE__*/(/* unused pure expression or super */ null && ([
|
|
4598
6535
|
{ key: "Alt-ArrowLeft", mac: "Ctrl-ArrowLeft", run: cursorSyntaxLeft, shift: selectSyntaxLeft },
|
|
@@ -4609,7 +6546,9 @@ const defaultKeymap = /*@__PURE__*/(/* unused pure expression or super */ null &
|
|
|
4609
6546
|
{ key: "Mod-]", run: indentMore },
|
|
4610
6547
|
{ key: "Mod-Alt-\\", run: indentSelection },
|
|
4611
6548
|
{ key: "Shift-Mod-k", run: deleteLine },
|
|
4612
|
-
{ key: "Shift-Mod-\\", run: cursorMatchingBracket }
|
|
6549
|
+
{ key: "Shift-Mod-\\", run: cursorMatchingBracket },
|
|
6550
|
+
{ key: "Mod-/", run: toggleComment },
|
|
6551
|
+
{ key: "Alt-A", run: toggleBlockComment }
|
|
4613
6552
|
].concat(standardKeymap)));
|
|
4614
6553
|
/**
|
|
4615
6554
|
A binding that binds Tab to [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) and
|
|
@@ -4880,7 +6819,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
4880
6819
|
/* harmony import */ var _home_runner_work_react_codemirror_react_codemirror_node_modules_babel_runtime_helpers_esm_objectWithoutProperties_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(925);
|
|
4881
6820
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(787);
|
|
4882
6821
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
4883
|
-
/* harmony import */ var _useCodeMirror__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
|
|
6822
|
+
/* harmony import */ var _useCodeMirror__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(963);
|
|
4884
6823
|
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(724);
|
|
4885
6824
|
/* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(105);
|
|
4886
6825
|
/* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_codemirror_view__WEBPACK_IMPORTED_MODULE_3__);
|