@codemirror/language 6.8.0 → 6.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/index.cjs +89 -63
- package/dist/index.d.cts +19 -6
- package/dist/index.d.ts +19 -6
- package/dist/index.js +90 -62
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.9.1 (2023-09-20)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Indentation now works a lot better in mixed-language documents that interleave the languages in a complex way.
|
|
6
|
+
|
|
7
|
+
Code folding is now able to pick the right foldable syntax node when the line end falls in a mixed-parsing language that doesn't match the target node.
|
|
8
|
+
|
|
9
|
+
## 6.9.0 (2023-08-16)
|
|
10
|
+
|
|
11
|
+
### Bug fixes
|
|
12
|
+
|
|
13
|
+
Make `getIndentation` return null, rather than 0, when there is no syntax tree available.
|
|
14
|
+
|
|
15
|
+
### New features
|
|
16
|
+
|
|
17
|
+
The new `preparePlaceholder` option to `codeFolding` makes it possible to display contextual information in a folded range placeholder widget.
|
|
18
|
+
|
|
1
19
|
## 6.8.0 (2023-06-12)
|
|
2
20
|
|
|
3
21
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var common = require('@lezer/common');
|
|
6
4
|
var state = require('@codemirror/state');
|
|
7
5
|
var view = require('@codemirror/view');
|
|
@@ -538,14 +536,14 @@ class LanguageState {
|
|
|
538
536
|
// state updates with parse work beyond the viewport.
|
|
539
537
|
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
|
540
538
|
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
|
541
|
-
if (!newCx.work(20 /* Apply */, upto))
|
|
539
|
+
if (!newCx.work(20 /* Work.Apply */, upto))
|
|
542
540
|
newCx.takeTree();
|
|
543
541
|
return new LanguageState(newCx);
|
|
544
542
|
}
|
|
545
543
|
static init(state) {
|
|
546
|
-
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
544
|
+
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
|
547
545
|
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
|
548
|
-
if (!parseState.work(20 /* Apply */, vpTo))
|
|
546
|
+
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
|
549
547
|
parseState.takeTree();
|
|
550
548
|
return new LanguageState(parseState);
|
|
551
549
|
}
|
|
@@ -562,14 +560,14 @@ Language.state = state.StateField.define({
|
|
|
562
560
|
}
|
|
563
561
|
});
|
|
564
562
|
let requestIdle = (callback) => {
|
|
565
|
-
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
|
563
|
+
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
|
566
564
|
return () => clearTimeout(timeout);
|
|
567
565
|
};
|
|
568
566
|
if (typeof requestIdleCallback != "undefined")
|
|
569
567
|
requestIdle = (callback) => {
|
|
570
568
|
let idle = -1, timeout = setTimeout(() => {
|
|
571
|
-
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
|
572
|
-
}, 100 /* MinPause */);
|
|
569
|
+
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
|
570
|
+
}, 100 /* Work.MinPause */);
|
|
573
571
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
574
572
|
};
|
|
575
573
|
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
@@ -590,9 +588,9 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
590
588
|
let cx = this.view.state.field(Language.state).context;
|
|
591
589
|
if (cx.updateViewport(update.view.viewport) || this.view.viewport.to > cx.treeLen)
|
|
592
590
|
this.scheduleWork();
|
|
593
|
-
if (update.docChanged) {
|
|
591
|
+
if (update.docChanged || update.selectionSet) {
|
|
594
592
|
if (this.view.hasFocus)
|
|
595
|
-
this.chunkBudget += 50 /* ChangeBonus */;
|
|
593
|
+
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
|
596
594
|
this.scheduleWork();
|
|
597
595
|
}
|
|
598
596
|
this.checkAsyncSchedule(cx);
|
|
@@ -608,19 +606,19 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
608
606
|
this.working = null;
|
|
609
607
|
let now = Date.now();
|
|
610
608
|
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
|
611
|
-
this.chunkEnd = now + 30000 /* ChunkTime */;
|
|
612
|
-
this.chunkBudget = 3000 /* ChunkBudget */;
|
|
609
|
+
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
|
610
|
+
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
|
613
611
|
}
|
|
614
612
|
if (this.chunkBudget <= 0)
|
|
615
613
|
return; // No more budget
|
|
616
614
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
617
|
-
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
615
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
|
618
616
|
return;
|
|
619
|
-
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
617
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
620
618
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
621
619
|
let done = field.context.work(() => {
|
|
622
620
|
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
623
|
-
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
621
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
|
624
622
|
this.chunkBudget -= Date.now() - now;
|
|
625
623
|
if (done || this.chunkBudget <= 0) {
|
|
626
624
|
field.context.takeTree();
|
|
@@ -865,7 +863,7 @@ function getIndentation(context, pos) {
|
|
|
865
863
|
return result;
|
|
866
864
|
}
|
|
867
865
|
let tree = syntaxTree(context.state);
|
|
868
|
-
return tree ? syntaxIndentation(context, tree, pos) : null;
|
|
866
|
+
return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;
|
|
869
867
|
}
|
|
870
868
|
/**
|
|
871
869
|
Create a change set that auto-indents all lines touched by the
|
|
@@ -996,7 +994,24 @@ indicates that no definitive indentation can be determined.
|
|
|
996
994
|
const indentNodeProp = new common.NodeProp();
|
|
997
995
|
// Compute the indentation for a given position from the syntax tree.
|
|
998
996
|
function syntaxIndentation(cx, ast, pos) {
|
|
999
|
-
|
|
997
|
+
let stack = ast.resolveStack(pos);
|
|
998
|
+
let inner = stack.node.enterUnfinishedNodesBefore(pos);
|
|
999
|
+
if (inner != stack.node) {
|
|
1000
|
+
let add = [];
|
|
1001
|
+
for (let cur = inner; cur != stack.node; cur = cur.parent)
|
|
1002
|
+
add.push(cur);
|
|
1003
|
+
for (let i = add.length - 1; i >= 0; i--)
|
|
1004
|
+
stack = { node: add[i], next: stack };
|
|
1005
|
+
}
|
|
1006
|
+
return indentFor(stack, cx, pos);
|
|
1007
|
+
}
|
|
1008
|
+
function indentFor(stack, cx, pos) {
|
|
1009
|
+
for (let cur = stack; cur; cur = cur.next) {
|
|
1010
|
+
let strategy = indentStrategy(cur.node);
|
|
1011
|
+
if (strategy)
|
|
1012
|
+
return strategy(TreeIndentContext.create(cx, pos, cur));
|
|
1013
|
+
}
|
|
1014
|
+
return 0;
|
|
1000
1015
|
}
|
|
1001
1016
|
function ignoreClosed(cx) {
|
|
1002
1017
|
return cx.pos == cx.options.simulateBreak && cx.options.simulateDoubleBreak;
|
|
@@ -1012,14 +1027,6 @@ function indentStrategy(tree) {
|
|
|
1012
1027
|
}
|
|
1013
1028
|
return tree.parent == null ? topIndent : null;
|
|
1014
1029
|
}
|
|
1015
|
-
function indentFrom(node, pos, base) {
|
|
1016
|
-
for (; node; node = node.parent) {
|
|
1017
|
-
let strategy = indentStrategy(node);
|
|
1018
|
-
if (strategy)
|
|
1019
|
-
return strategy(TreeIndentContext.create(base, pos, node));
|
|
1020
|
-
}
|
|
1021
|
-
return null;
|
|
1022
|
-
}
|
|
1023
1030
|
function topIndent() { return 0; }
|
|
1024
1031
|
/**
|
|
1025
1032
|
Objects of this type provide context information and helper
|
|
@@ -1032,20 +1039,24 @@ class TreeIndentContext extends IndentContext {
|
|
|
1032
1039
|
*/
|
|
1033
1040
|
pos,
|
|
1034
1041
|
/**
|
|
1035
|
-
|
|
1036
|
-
applies.
|
|
1042
|
+
@internal
|
|
1037
1043
|
*/
|
|
1038
|
-
|
|
1044
|
+
context) {
|
|
1039
1045
|
super(base.state, base.options);
|
|
1040
1046
|
this.base = base;
|
|
1041
1047
|
this.pos = pos;
|
|
1042
|
-
this.
|
|
1048
|
+
this.context = context;
|
|
1043
1049
|
}
|
|
1044
1050
|
/**
|
|
1051
|
+
The syntax tree node to which the indentation strategy
|
|
1052
|
+
applies.
|
|
1053
|
+
*/
|
|
1054
|
+
get node() { return this.context.node; }
|
|
1055
|
+
/**
|
|
1045
1056
|
@internal
|
|
1046
1057
|
*/
|
|
1047
|
-
static create(base, pos,
|
|
1048
|
-
return new TreeIndentContext(base, pos,
|
|
1058
|
+
static create(base, pos, context) {
|
|
1059
|
+
return new TreeIndentContext(base, pos, context);
|
|
1049
1060
|
}
|
|
1050
1061
|
/**
|
|
1051
1062
|
Get the text directly after `this.pos`, either the entire line
|
|
@@ -1086,8 +1097,7 @@ class TreeIndentContext extends IndentContext {
|
|
|
1086
1097
|
and return the result of that.
|
|
1087
1098
|
*/
|
|
1088
1099
|
continue() {
|
|
1089
|
-
|
|
1090
|
-
return parent ? indentFrom(parent, this.pos, this.base) : 0;
|
|
1100
|
+
return indentFor(this.context.next, this.base, this.pos);
|
|
1091
1101
|
}
|
|
1092
1102
|
}
|
|
1093
1103
|
function isParent(parent, of) {
|
|
@@ -1229,9 +1239,10 @@ function syntaxFolding(state, start, end) {
|
|
|
1229
1239
|
let tree = syntaxTree(state);
|
|
1230
1240
|
if (tree.length < end)
|
|
1231
1241
|
return null;
|
|
1232
|
-
let
|
|
1242
|
+
let stack = tree.resolveStack(end, 1);
|
|
1233
1243
|
let found = null;
|
|
1234
|
-
for (let
|
|
1244
|
+
for (let iter = stack; iter; iter = iter.next) {
|
|
1245
|
+
let cur = iter.node;
|
|
1235
1246
|
if (cur.to <= end || cur.from > end)
|
|
1236
1247
|
continue;
|
|
1237
1248
|
if (found && cur.from < start)
|
|
@@ -1304,11 +1315,16 @@ const foldState = state.StateField.define({
|
|
|
1304
1315
|
update(folded, tr) {
|
|
1305
1316
|
folded = folded.map(tr.changes);
|
|
1306
1317
|
for (let e of tr.effects) {
|
|
1307
|
-
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to))
|
|
1308
|
-
|
|
1309
|
-
|
|
1318
|
+
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to)) {
|
|
1319
|
+
let { preparePlaceholder } = tr.state.facet(foldConfig);
|
|
1320
|
+
let widget = !preparePlaceholder ? foldWidget :
|
|
1321
|
+
view.Decoration.replace({ widget: new PreparedFoldWidget(preparePlaceholder(tr.state, e.value)) });
|
|
1322
|
+
folded = folded.update({ add: [widget.range(e.value.from, e.value.to)] });
|
|
1323
|
+
}
|
|
1324
|
+
else if (e.is(unfoldEffect)) {
|
|
1310
1325
|
folded = folded.update({ filter: (from, to) => e.value.from != from || e.value.to != to,
|
|
1311
1326
|
filterFrom: e.value.from, filterTo: e.value.to });
|
|
1327
|
+
}
|
|
1312
1328
|
}
|
|
1313
1329
|
// Clear folded ranges that cover the selection head
|
|
1314
1330
|
if (tr.selection) {
|
|
@@ -1485,6 +1501,7 @@ const foldKeymap = [
|
|
|
1485
1501
|
];
|
|
1486
1502
|
const defaultConfig = {
|
|
1487
1503
|
placeholderDOM: null,
|
|
1504
|
+
preparePlaceholder: null,
|
|
1488
1505
|
placeholderText: "…"
|
|
1489
1506
|
};
|
|
1490
1507
|
const foldConfig = state.Facet.define({
|
|
@@ -1499,27 +1516,36 @@ function codeFolding(config) {
|
|
|
1499
1516
|
result.push(foldConfig.of(config));
|
|
1500
1517
|
return result;
|
|
1501
1518
|
}
|
|
1519
|
+
function widgetToDOM(view, prepared) {
|
|
1520
|
+
let { state } = view, conf = state.facet(foldConfig);
|
|
1521
|
+
let onclick = (event) => {
|
|
1522
|
+
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1523
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
1524
|
+
if (folded)
|
|
1525
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1526
|
+
event.preventDefault();
|
|
1527
|
+
};
|
|
1528
|
+
if (conf.placeholderDOM)
|
|
1529
|
+
return conf.placeholderDOM(view, onclick, prepared);
|
|
1530
|
+
let element = document.createElement("span");
|
|
1531
|
+
element.textContent = conf.placeholderText;
|
|
1532
|
+
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1533
|
+
element.title = state.phrase("unfold");
|
|
1534
|
+
element.className = "cm-foldPlaceholder";
|
|
1535
|
+
element.onclick = onclick;
|
|
1536
|
+
return element;
|
|
1537
|
+
}
|
|
1502
1538
|
const foldWidget = view.Decoration.replace({ widget: new class extends view.WidgetType {
|
|
1503
|
-
toDOM(view) {
|
|
1504
|
-
let { state } = view, conf = state.facet(foldConfig);
|
|
1505
|
-
let onclick = (event) => {
|
|
1506
|
-
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1507
|
-
let folded = findFold(view.state, line.from, line.to);
|
|
1508
|
-
if (folded)
|
|
1509
|
-
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1510
|
-
event.preventDefault();
|
|
1511
|
-
};
|
|
1512
|
-
if (conf.placeholderDOM)
|
|
1513
|
-
return conf.placeholderDOM(view, onclick);
|
|
1514
|
-
let element = document.createElement("span");
|
|
1515
|
-
element.textContent = conf.placeholderText;
|
|
1516
|
-
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1517
|
-
element.title = state.phrase("unfold");
|
|
1518
|
-
element.className = "cm-foldPlaceholder";
|
|
1519
|
-
element.onclick = onclick;
|
|
1520
|
-
return element;
|
|
1521
|
-
}
|
|
1539
|
+
toDOM(view) { return widgetToDOM(view, null); }
|
|
1522
1540
|
} });
|
|
1541
|
+
class PreparedFoldWidget extends view.WidgetType {
|
|
1542
|
+
constructor(value) {
|
|
1543
|
+
super();
|
|
1544
|
+
this.value = value;
|
|
1545
|
+
}
|
|
1546
|
+
eq(other) { return this.value == other.value; }
|
|
1547
|
+
toDOM(view) { return widgetToDOM(view, this.value); }
|
|
1548
|
+
}
|
|
1523
1549
|
const foldGutterDefaults = {
|
|
1524
1550
|
openText: "⌄",
|
|
1525
1551
|
closedText: "›",
|
|
@@ -2207,7 +2233,7 @@ class StreamLanguage extends Language {
|
|
|
2207
2233
|
state = this.streamParser.startState(cx.unit);
|
|
2208
2234
|
statePos = 0;
|
|
2209
2235
|
}
|
|
2210
|
-
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
|
2236
|
+
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
|
2211
2237
|
return null;
|
|
2212
2238
|
while (statePos < pos) {
|
|
2213
2239
|
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
|
@@ -2289,7 +2315,7 @@ class Parse {
|
|
|
2289
2315
|
this.chunks.push(tree.children[i]);
|
|
2290
2316
|
this.chunkPos.push(tree.positions[i]);
|
|
2291
2317
|
}
|
|
2292
|
-
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
|
2318
|
+
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
|
2293
2319
|
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
|
2294
2320
|
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
|
2295
2321
|
this.parsedPos = context.viewport.from;
|
|
@@ -2299,7 +2325,7 @@ class Parse {
|
|
|
2299
2325
|
advance() {
|
|
2300
2326
|
let context = ParseContext.get();
|
|
2301
2327
|
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
|
2302
|
-
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
|
2328
|
+
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
|
2303
2329
|
if (context)
|
|
2304
2330
|
end = Math.min(end, context.viewport.to);
|
|
2305
2331
|
while (this.parsedPos < end)
|
|
@@ -2383,7 +2409,7 @@ class Parse {
|
|
|
2383
2409
|
let token = readToken(streamParser.token, stream, this.state);
|
|
2384
2410
|
if (token)
|
|
2385
2411
|
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
|
2386
|
-
if (stream.start > 10000 /* MaxLineLength */)
|
|
2412
|
+
if (stream.start > 10000 /* C.MaxLineLength */)
|
|
2387
2413
|
break;
|
|
2388
2414
|
}
|
|
2389
2415
|
}
|
|
@@ -2399,7 +2425,7 @@ class Parse {
|
|
|
2399
2425
|
length: this.parsedPos - this.chunkStart,
|
|
2400
2426
|
nodeSet,
|
|
2401
2427
|
topID: 0,
|
|
2402
|
-
maxBufferLength: 2048 /* ChunkSize */,
|
|
2428
|
+
maxBufferLength: 2048 /* C.ChunkSize */,
|
|
2403
2429
|
reused: this.chunkReused
|
|
2404
2430
|
});
|
|
2405
2431
|
tree = new common.Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
|
@@ -2489,7 +2515,7 @@ function createTokenType(extra, tagStr) {
|
|
|
2489
2515
|
return type.id;
|
|
2490
2516
|
}
|
|
2491
2517
|
function docID(data) {
|
|
2492
|
-
let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
|
|
2518
|
+
let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
|
|
2493
2519
|
typeArray.push(type);
|
|
2494
2520
|
return type;
|
|
2495
2521
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -567,12 +567,12 @@ declare class TreeIndentContext extends IndentContext {
|
|
|
567
567
|
The position at which indentation is being computed.
|
|
568
568
|
*/
|
|
569
569
|
readonly pos: number;
|
|
570
|
+
private constructor();
|
|
570
571
|
/**
|
|
571
572
|
The syntax tree node to which the indentation strategy
|
|
572
573
|
applies.
|
|
573
574
|
*/
|
|
574
|
-
|
|
575
|
-
private constructor();
|
|
575
|
+
get node(): SyntaxNode;
|
|
576
576
|
/**
|
|
577
577
|
Get the text directly after `this.pos`, either the entire line
|
|
578
578
|
or the next 100 characters, whichever is shorter.
|
|
@@ -689,7 +689,7 @@ declare function foldable(state: EditorState, lineStart: number, lineEnd: number
|
|
|
689
689
|
from: number;
|
|
690
690
|
to: number;
|
|
691
691
|
} | null;
|
|
692
|
-
|
|
692
|
+
type DocRange = {
|
|
693
693
|
from: number;
|
|
694
694
|
to: number;
|
|
695
695
|
};
|
|
@@ -761,23 +761,36 @@ interface FoldConfig {
|
|
|
761
761
|
position of folded code. The `onclick` argument is the default
|
|
762
762
|
click event handler, which toggles folding on the line that
|
|
763
763
|
holds the element, and should probably be added as an event
|
|
764
|
-
handler to the returned element.
|
|
764
|
+
handler to the returned element. If
|
|
765
|
+
[`preparePlaceholder`](https://codemirror.net/6/docs/ref/#language.FoldConfig.preparePlaceholder)
|
|
766
|
+
is given, its result will be passed as 3rd argument. Otherwise,
|
|
767
|
+
this will be null.
|
|
765
768
|
|
|
766
769
|
When this option isn't given, the `placeholderText` option will
|
|
767
770
|
be used to create the placeholder element.
|
|
768
771
|
*/
|
|
769
|
-
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void) => HTMLElement) | null;
|
|
772
|
+
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void, prepared: any) => HTMLElement) | null;
|
|
770
773
|
/**
|
|
771
774
|
Text to use as placeholder for folded text. Defaults to `"…"`.
|
|
772
775
|
Will be styled with the `"cm-foldPlaceholder"` class.
|
|
773
776
|
*/
|
|
774
777
|
placeholderText?: string;
|
|
778
|
+
/**
|
|
779
|
+
Given a range that is being folded, create a value that
|
|
780
|
+
describes it, to be used by `placeholderDOM` to render a custom
|
|
781
|
+
widget that, for example, indicates something about the folded
|
|
782
|
+
range's size or type.
|
|
783
|
+
*/
|
|
784
|
+
preparePlaceholder?: (state: EditorState, range: {
|
|
785
|
+
from: number;
|
|
786
|
+
to: number;
|
|
787
|
+
}) => any;
|
|
775
788
|
}
|
|
776
789
|
/**
|
|
777
790
|
Create an extension that configures code folding.
|
|
778
791
|
*/
|
|
779
792
|
declare function codeFolding(config?: FoldConfig): Extension;
|
|
780
|
-
|
|
793
|
+
type Handlers = {
|
|
781
794
|
[event: string]: (view: EditorView, line: BlockInfo, event: Event) => boolean;
|
|
782
795
|
};
|
|
783
796
|
interface FoldGutterConfig {
|
package/dist/index.d.ts
CHANGED
|
@@ -567,12 +567,12 @@ declare class TreeIndentContext extends IndentContext {
|
|
|
567
567
|
The position at which indentation is being computed.
|
|
568
568
|
*/
|
|
569
569
|
readonly pos: number;
|
|
570
|
+
private constructor();
|
|
570
571
|
/**
|
|
571
572
|
The syntax tree node to which the indentation strategy
|
|
572
573
|
applies.
|
|
573
574
|
*/
|
|
574
|
-
|
|
575
|
-
private constructor();
|
|
575
|
+
get node(): SyntaxNode;
|
|
576
576
|
/**
|
|
577
577
|
Get the text directly after `this.pos`, either the entire line
|
|
578
578
|
or the next 100 characters, whichever is shorter.
|
|
@@ -689,7 +689,7 @@ declare function foldable(state: EditorState, lineStart: number, lineEnd: number
|
|
|
689
689
|
from: number;
|
|
690
690
|
to: number;
|
|
691
691
|
} | null;
|
|
692
|
-
|
|
692
|
+
type DocRange = {
|
|
693
693
|
from: number;
|
|
694
694
|
to: number;
|
|
695
695
|
};
|
|
@@ -761,23 +761,36 @@ interface FoldConfig {
|
|
|
761
761
|
position of folded code. The `onclick` argument is the default
|
|
762
762
|
click event handler, which toggles folding on the line that
|
|
763
763
|
holds the element, and should probably be added as an event
|
|
764
|
-
handler to the returned element.
|
|
764
|
+
handler to the returned element. If
|
|
765
|
+
[`preparePlaceholder`](https://codemirror.net/6/docs/ref/#language.FoldConfig.preparePlaceholder)
|
|
766
|
+
is given, its result will be passed as 3rd argument. Otherwise,
|
|
767
|
+
this will be null.
|
|
765
768
|
|
|
766
769
|
When this option isn't given, the `placeholderText` option will
|
|
767
770
|
be used to create the placeholder element.
|
|
768
771
|
*/
|
|
769
|
-
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void) => HTMLElement) | null;
|
|
772
|
+
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void, prepared: any) => HTMLElement) | null;
|
|
770
773
|
/**
|
|
771
774
|
Text to use as placeholder for folded text. Defaults to `"…"`.
|
|
772
775
|
Will be styled with the `"cm-foldPlaceholder"` class.
|
|
773
776
|
*/
|
|
774
777
|
placeholderText?: string;
|
|
778
|
+
/**
|
|
779
|
+
Given a range that is being folded, create a value that
|
|
780
|
+
describes it, to be used by `placeholderDOM` to render a custom
|
|
781
|
+
widget that, for example, indicates something about the folded
|
|
782
|
+
range's size or type.
|
|
783
|
+
*/
|
|
784
|
+
preparePlaceholder?: (state: EditorState, range: {
|
|
785
|
+
from: number;
|
|
786
|
+
to: number;
|
|
787
|
+
}) => any;
|
|
775
788
|
}
|
|
776
789
|
/**
|
|
777
790
|
Create an extension that configures code folding.
|
|
778
791
|
*/
|
|
779
792
|
declare function codeFolding(config?: FoldConfig): Extension;
|
|
780
|
-
|
|
793
|
+
type Handlers = {
|
|
781
794
|
[event: string]: (view: EditorView, line: BlockInfo, event: Event) => boolean;
|
|
782
795
|
};
|
|
783
796
|
interface FoldGutterConfig {
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NodeProp,
|
|
1
|
+
import { NodeProp, IterMode, Tree, TreeFragment, Parser, NodeType, NodeSet } from '@lezer/common';
|
|
2
2
|
import { StateEffect, StateField, Facet, EditorState, countColumn, combineConfig, RangeSet, RangeSetBuilder, Prec } from '@codemirror/state';
|
|
3
3
|
import { ViewPlugin, logException, EditorView, Decoration, WidgetType, gutter, GutterMarker } from '@codemirror/view';
|
|
4
4
|
import { tags, tagHighlighter, highlightTree, styleTags } from '@lezer/highlight';
|
|
@@ -534,14 +534,14 @@ class LanguageState {
|
|
|
534
534
|
// state updates with parse work beyond the viewport.
|
|
535
535
|
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
|
536
536
|
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
|
537
|
-
if (!newCx.work(20 /* Apply */, upto))
|
|
537
|
+
if (!newCx.work(20 /* Work.Apply */, upto))
|
|
538
538
|
newCx.takeTree();
|
|
539
539
|
return new LanguageState(newCx);
|
|
540
540
|
}
|
|
541
541
|
static init(state) {
|
|
542
|
-
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
542
|
+
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
|
543
543
|
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
|
544
|
-
if (!parseState.work(20 /* Apply */, vpTo))
|
|
544
|
+
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
|
545
545
|
parseState.takeTree();
|
|
546
546
|
return new LanguageState(parseState);
|
|
547
547
|
}
|
|
@@ -558,14 +558,14 @@ Language.state = /*@__PURE__*/StateField.define({
|
|
|
558
558
|
}
|
|
559
559
|
});
|
|
560
560
|
let requestIdle = (callback) => {
|
|
561
|
-
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
|
561
|
+
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
|
562
562
|
return () => clearTimeout(timeout);
|
|
563
563
|
};
|
|
564
564
|
if (typeof requestIdleCallback != "undefined")
|
|
565
565
|
requestIdle = (callback) => {
|
|
566
566
|
let idle = -1, timeout = setTimeout(() => {
|
|
567
|
-
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
|
568
|
-
}, 100 /* MinPause */);
|
|
567
|
+
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
|
568
|
+
}, 100 /* Work.MinPause */);
|
|
569
569
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
570
570
|
};
|
|
571
571
|
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
@@ -586,9 +586,9 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
586
586
|
let cx = this.view.state.field(Language.state).context;
|
|
587
587
|
if (cx.updateViewport(update.view.viewport) || this.view.viewport.to > cx.treeLen)
|
|
588
588
|
this.scheduleWork();
|
|
589
|
-
if (update.docChanged) {
|
|
589
|
+
if (update.docChanged || update.selectionSet) {
|
|
590
590
|
if (this.view.hasFocus)
|
|
591
|
-
this.chunkBudget += 50 /* ChangeBonus */;
|
|
591
|
+
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
|
592
592
|
this.scheduleWork();
|
|
593
593
|
}
|
|
594
594
|
this.checkAsyncSchedule(cx);
|
|
@@ -604,19 +604,19 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
604
604
|
this.working = null;
|
|
605
605
|
let now = Date.now();
|
|
606
606
|
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
|
607
|
-
this.chunkEnd = now + 30000 /* ChunkTime */;
|
|
608
|
-
this.chunkBudget = 3000 /* ChunkBudget */;
|
|
607
|
+
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
|
608
|
+
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
|
609
609
|
}
|
|
610
610
|
if (this.chunkBudget <= 0)
|
|
611
611
|
return; // No more budget
|
|
612
612
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
613
|
-
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
613
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
|
614
614
|
return;
|
|
615
|
-
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
615
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
616
616
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
617
617
|
let done = field.context.work(() => {
|
|
618
618
|
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
619
|
-
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
619
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
|
620
620
|
this.chunkBudget -= Date.now() - now;
|
|
621
621
|
if (done || this.chunkBudget <= 0) {
|
|
622
622
|
field.context.takeTree();
|
|
@@ -861,7 +861,7 @@ function getIndentation(context, pos) {
|
|
|
861
861
|
return result;
|
|
862
862
|
}
|
|
863
863
|
let tree = syntaxTree(context.state);
|
|
864
|
-
return tree ? syntaxIndentation(context, tree, pos) : null;
|
|
864
|
+
return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;
|
|
865
865
|
}
|
|
866
866
|
/**
|
|
867
867
|
Create a change set that auto-indents all lines touched by the
|
|
@@ -992,7 +992,24 @@ indicates that no definitive indentation can be determined.
|
|
|
992
992
|
const indentNodeProp = /*@__PURE__*/new NodeProp();
|
|
993
993
|
// Compute the indentation for a given position from the syntax tree.
|
|
994
994
|
function syntaxIndentation(cx, ast, pos) {
|
|
995
|
-
|
|
995
|
+
let stack = ast.resolveStack(pos);
|
|
996
|
+
let inner = stack.node.enterUnfinishedNodesBefore(pos);
|
|
997
|
+
if (inner != stack.node) {
|
|
998
|
+
let add = [];
|
|
999
|
+
for (let cur = inner; cur != stack.node; cur = cur.parent)
|
|
1000
|
+
add.push(cur);
|
|
1001
|
+
for (let i = add.length - 1; i >= 0; i--)
|
|
1002
|
+
stack = { node: add[i], next: stack };
|
|
1003
|
+
}
|
|
1004
|
+
return indentFor(stack, cx, pos);
|
|
1005
|
+
}
|
|
1006
|
+
function indentFor(stack, cx, pos) {
|
|
1007
|
+
for (let cur = stack; cur; cur = cur.next) {
|
|
1008
|
+
let strategy = indentStrategy(cur.node);
|
|
1009
|
+
if (strategy)
|
|
1010
|
+
return strategy(TreeIndentContext.create(cx, pos, cur));
|
|
1011
|
+
}
|
|
1012
|
+
return 0;
|
|
996
1013
|
}
|
|
997
1014
|
function ignoreClosed(cx) {
|
|
998
1015
|
return cx.pos == cx.options.simulateBreak && cx.options.simulateDoubleBreak;
|
|
@@ -1008,14 +1025,6 @@ function indentStrategy(tree) {
|
|
|
1008
1025
|
}
|
|
1009
1026
|
return tree.parent == null ? topIndent : null;
|
|
1010
1027
|
}
|
|
1011
|
-
function indentFrom(node, pos, base) {
|
|
1012
|
-
for (; node; node = node.parent) {
|
|
1013
|
-
let strategy = indentStrategy(node);
|
|
1014
|
-
if (strategy)
|
|
1015
|
-
return strategy(TreeIndentContext.create(base, pos, node));
|
|
1016
|
-
}
|
|
1017
|
-
return null;
|
|
1018
|
-
}
|
|
1019
1028
|
function topIndent() { return 0; }
|
|
1020
1029
|
/**
|
|
1021
1030
|
Objects of this type provide context information and helper
|
|
@@ -1028,20 +1037,24 @@ class TreeIndentContext extends IndentContext {
|
|
|
1028
1037
|
*/
|
|
1029
1038
|
pos,
|
|
1030
1039
|
/**
|
|
1031
|
-
|
|
1032
|
-
applies.
|
|
1040
|
+
@internal
|
|
1033
1041
|
*/
|
|
1034
|
-
|
|
1042
|
+
context) {
|
|
1035
1043
|
super(base.state, base.options);
|
|
1036
1044
|
this.base = base;
|
|
1037
1045
|
this.pos = pos;
|
|
1038
|
-
this.
|
|
1046
|
+
this.context = context;
|
|
1039
1047
|
}
|
|
1040
1048
|
/**
|
|
1049
|
+
The syntax tree node to which the indentation strategy
|
|
1050
|
+
applies.
|
|
1051
|
+
*/
|
|
1052
|
+
get node() { return this.context.node; }
|
|
1053
|
+
/**
|
|
1041
1054
|
@internal
|
|
1042
1055
|
*/
|
|
1043
|
-
static create(base, pos,
|
|
1044
|
-
return new TreeIndentContext(base, pos,
|
|
1056
|
+
static create(base, pos, context) {
|
|
1057
|
+
return new TreeIndentContext(base, pos, context);
|
|
1045
1058
|
}
|
|
1046
1059
|
/**
|
|
1047
1060
|
Get the text directly after `this.pos`, either the entire line
|
|
@@ -1082,8 +1095,7 @@ class TreeIndentContext extends IndentContext {
|
|
|
1082
1095
|
and return the result of that.
|
|
1083
1096
|
*/
|
|
1084
1097
|
continue() {
|
|
1085
|
-
|
|
1086
|
-
return parent ? indentFrom(parent, this.pos, this.base) : 0;
|
|
1098
|
+
return indentFor(this.context.next, this.base, this.pos);
|
|
1087
1099
|
}
|
|
1088
1100
|
}
|
|
1089
1101
|
function isParent(parent, of) {
|
|
@@ -1225,9 +1237,10 @@ function syntaxFolding(state, start, end) {
|
|
|
1225
1237
|
let tree = syntaxTree(state);
|
|
1226
1238
|
if (tree.length < end)
|
|
1227
1239
|
return null;
|
|
1228
|
-
let
|
|
1240
|
+
let stack = tree.resolveStack(end, 1);
|
|
1229
1241
|
let found = null;
|
|
1230
|
-
for (let
|
|
1242
|
+
for (let iter = stack; iter; iter = iter.next) {
|
|
1243
|
+
let cur = iter.node;
|
|
1231
1244
|
if (cur.to <= end || cur.from > end)
|
|
1232
1245
|
continue;
|
|
1233
1246
|
if (found && cur.from < start)
|
|
@@ -1300,11 +1313,16 @@ const foldState = /*@__PURE__*/StateField.define({
|
|
|
1300
1313
|
update(folded, tr) {
|
|
1301
1314
|
folded = folded.map(tr.changes);
|
|
1302
1315
|
for (let e of tr.effects) {
|
|
1303
|
-
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to))
|
|
1304
|
-
|
|
1305
|
-
|
|
1316
|
+
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to)) {
|
|
1317
|
+
let { preparePlaceholder } = tr.state.facet(foldConfig);
|
|
1318
|
+
let widget = !preparePlaceholder ? foldWidget :
|
|
1319
|
+
Decoration.replace({ widget: new PreparedFoldWidget(preparePlaceholder(tr.state, e.value)) });
|
|
1320
|
+
folded = folded.update({ add: [widget.range(e.value.from, e.value.to)] });
|
|
1321
|
+
}
|
|
1322
|
+
else if (e.is(unfoldEffect)) {
|
|
1306
1323
|
folded = folded.update({ filter: (from, to) => e.value.from != from || e.value.to != to,
|
|
1307
1324
|
filterFrom: e.value.from, filterTo: e.value.to });
|
|
1325
|
+
}
|
|
1308
1326
|
}
|
|
1309
1327
|
// Clear folded ranges that cover the selection head
|
|
1310
1328
|
if (tr.selection) {
|
|
@@ -1481,6 +1499,7 @@ const foldKeymap = [
|
|
|
1481
1499
|
];
|
|
1482
1500
|
const defaultConfig = {
|
|
1483
1501
|
placeholderDOM: null,
|
|
1502
|
+
preparePlaceholder: null,
|
|
1484
1503
|
placeholderText: "…"
|
|
1485
1504
|
};
|
|
1486
1505
|
const foldConfig = /*@__PURE__*/Facet.define({
|
|
@@ -1495,27 +1514,36 @@ function codeFolding(config) {
|
|
|
1495
1514
|
result.push(foldConfig.of(config));
|
|
1496
1515
|
return result;
|
|
1497
1516
|
}
|
|
1517
|
+
function widgetToDOM(view, prepared) {
|
|
1518
|
+
let { state } = view, conf = state.facet(foldConfig);
|
|
1519
|
+
let onclick = (event) => {
|
|
1520
|
+
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1521
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
1522
|
+
if (folded)
|
|
1523
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1524
|
+
event.preventDefault();
|
|
1525
|
+
};
|
|
1526
|
+
if (conf.placeholderDOM)
|
|
1527
|
+
return conf.placeholderDOM(view, onclick, prepared);
|
|
1528
|
+
let element = document.createElement("span");
|
|
1529
|
+
element.textContent = conf.placeholderText;
|
|
1530
|
+
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1531
|
+
element.title = state.phrase("unfold");
|
|
1532
|
+
element.className = "cm-foldPlaceholder";
|
|
1533
|
+
element.onclick = onclick;
|
|
1534
|
+
return element;
|
|
1535
|
+
}
|
|
1498
1536
|
const foldWidget = /*@__PURE__*/Decoration.replace({ widget: /*@__PURE__*/new class extends WidgetType {
|
|
1499
|
-
toDOM(view) {
|
|
1500
|
-
let { state } = view, conf = state.facet(foldConfig);
|
|
1501
|
-
let onclick = (event) => {
|
|
1502
|
-
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1503
|
-
let folded = findFold(view.state, line.from, line.to);
|
|
1504
|
-
if (folded)
|
|
1505
|
-
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1506
|
-
event.preventDefault();
|
|
1507
|
-
};
|
|
1508
|
-
if (conf.placeholderDOM)
|
|
1509
|
-
return conf.placeholderDOM(view, onclick);
|
|
1510
|
-
let element = document.createElement("span");
|
|
1511
|
-
element.textContent = conf.placeholderText;
|
|
1512
|
-
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1513
|
-
element.title = state.phrase("unfold");
|
|
1514
|
-
element.className = "cm-foldPlaceholder";
|
|
1515
|
-
element.onclick = onclick;
|
|
1516
|
-
return element;
|
|
1517
|
-
}
|
|
1537
|
+
toDOM(view) { return widgetToDOM(view, null); }
|
|
1518
1538
|
} });
|
|
1539
|
+
class PreparedFoldWidget extends WidgetType {
|
|
1540
|
+
constructor(value) {
|
|
1541
|
+
super();
|
|
1542
|
+
this.value = value;
|
|
1543
|
+
}
|
|
1544
|
+
eq(other) { return this.value == other.value; }
|
|
1545
|
+
toDOM(view) { return widgetToDOM(view, this.value); }
|
|
1546
|
+
}
|
|
1519
1547
|
const foldGutterDefaults = {
|
|
1520
1548
|
openText: "⌄",
|
|
1521
1549
|
closedText: "›",
|
|
@@ -2203,7 +2231,7 @@ class StreamLanguage extends Language {
|
|
|
2203
2231
|
state = this.streamParser.startState(cx.unit);
|
|
2204
2232
|
statePos = 0;
|
|
2205
2233
|
}
|
|
2206
|
-
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
|
2234
|
+
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
|
2207
2235
|
return null;
|
|
2208
2236
|
while (statePos < pos) {
|
|
2209
2237
|
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
|
@@ -2285,7 +2313,7 @@ class Parse {
|
|
|
2285
2313
|
this.chunks.push(tree.children[i]);
|
|
2286
2314
|
this.chunkPos.push(tree.positions[i]);
|
|
2287
2315
|
}
|
|
2288
|
-
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
|
2316
|
+
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
|
2289
2317
|
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
|
2290
2318
|
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
|
2291
2319
|
this.parsedPos = context.viewport.from;
|
|
@@ -2295,7 +2323,7 @@ class Parse {
|
|
|
2295
2323
|
advance() {
|
|
2296
2324
|
let context = ParseContext.get();
|
|
2297
2325
|
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
|
2298
|
-
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
|
2326
|
+
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
|
2299
2327
|
if (context)
|
|
2300
2328
|
end = Math.min(end, context.viewport.to);
|
|
2301
2329
|
while (this.parsedPos < end)
|
|
@@ -2379,7 +2407,7 @@ class Parse {
|
|
|
2379
2407
|
let token = readToken(streamParser.token, stream, this.state);
|
|
2380
2408
|
if (token)
|
|
2381
2409
|
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
|
2382
|
-
if (stream.start > 10000 /* MaxLineLength */)
|
|
2410
|
+
if (stream.start > 10000 /* C.MaxLineLength */)
|
|
2383
2411
|
break;
|
|
2384
2412
|
}
|
|
2385
2413
|
}
|
|
@@ -2395,7 +2423,7 @@ class Parse {
|
|
|
2395
2423
|
length: this.parsedPos - this.chunkStart,
|
|
2396
2424
|
nodeSet,
|
|
2397
2425
|
topID: 0,
|
|
2398
|
-
maxBufferLength: 2048 /* ChunkSize */,
|
|
2426
|
+
maxBufferLength: 2048 /* C.ChunkSize */,
|
|
2399
2427
|
reused: this.chunkReused
|
|
2400
2428
|
});
|
|
2401
2429
|
tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
|
@@ -2485,7 +2513,7 @@ function createTokenType(extra, tagStr) {
|
|
|
2485
2513
|
return type.id;
|
|
2486
2514
|
}
|
|
2487
2515
|
function docID(data) {
|
|
2488
|
-
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
|
|
2516
|
+
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
|
|
2489
2517
|
typeArray.push(type);
|
|
2490
2518
|
return type;
|
|
2491
2519
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/language",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.1",
|
|
4
4
|
"description": "Language support infrastructure for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@codemirror/state": "^6.0.0",
|
|
30
30
|
"@codemirror/view": "^6.0.0",
|
|
31
|
-
"@lezer/common": "^1.
|
|
31
|
+
"@lezer/common": "^1.1.0",
|
|
32
32
|
"@lezer/highlight": "^1.0.0",
|
|
33
33
|
"@lezer/lr": "^1.0.0",
|
|
34
34
|
"style-mod": "^4.0.0"
|