@codemirror/language 0.19.6 → 0.19.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/index.cjs +27 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +27 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 0.19.9 (2022-03-30)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make sure nodes that end at the end of a partial parse aren't treated as valid fold targets.
|
|
6
|
+
|
|
7
|
+
Fix an issue where the parser sometimes wouldn't reuse parsing work done in the background on transactions.
|
|
8
|
+
|
|
9
|
+
## 0.19.8 (2022-03-03)
|
|
10
|
+
|
|
11
|
+
### Bug fixes
|
|
12
|
+
|
|
13
|
+
Fix an issue that could cause indentation logic to use the wrong line content when indenting multiple lines at once.
|
|
14
|
+
|
|
15
|
+
## 0.19.7 (2021-12-02)
|
|
16
|
+
|
|
17
|
+
### Bug fixes
|
|
18
|
+
|
|
19
|
+
Fix an issue where the parse worker could incorrectly stop working when the parse tree has skipped gaps in it.
|
|
20
|
+
|
|
1
21
|
## 0.19.6 (2021-11-26)
|
|
2
22
|
|
|
3
23
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var state = require('@codemirror/state');
|
|
|
7
7
|
var view = require('@codemirror/view');
|
|
8
8
|
var text = require('@codemirror/text');
|
|
9
9
|
|
|
10
|
+
var _a;
|
|
10
11
|
/**
|
|
11
12
|
Node prop stored in a grammar's top syntax node to provide the
|
|
12
13
|
facet that stores language data for that language.
|
|
@@ -179,7 +180,7 @@ up to that point if the tree isn't already available.
|
|
|
179
180
|
function ensureSyntaxTree(state, upto, timeout = 50) {
|
|
180
181
|
var _a;
|
|
181
182
|
let parse = (_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context;
|
|
182
|
-
return !parse ? null : parse.
|
|
183
|
+
return !parse ? null : parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
|
183
184
|
}
|
|
184
185
|
/**
|
|
185
186
|
Queries whether there is a full syntax tree available up to the
|
|
@@ -292,7 +293,7 @@ class ParseContext {
|
|
|
292
293
|
/**
|
|
293
294
|
@internal
|
|
294
295
|
*/
|
|
295
|
-
work(
|
|
296
|
+
work(until, upto) {
|
|
296
297
|
if (upto != null && upto >= this.state.doc.length)
|
|
297
298
|
upto = undefined;
|
|
298
299
|
if (this.tree != common.Tree.empty && this.isDone(upto !== null && upto !== void 0 ? upto : this.state.doc.length)) {
|
|
@@ -301,7 +302,10 @@ class ParseContext {
|
|
|
301
302
|
}
|
|
302
303
|
return this.withContext(() => {
|
|
303
304
|
var _a;
|
|
304
|
-
|
|
305
|
+
if (typeof until == "number") {
|
|
306
|
+
let endTime = Date.now() + until;
|
|
307
|
+
until = () => Date.now() > endTime;
|
|
308
|
+
}
|
|
305
309
|
if (!this.parse)
|
|
306
310
|
this.parse = this.startParse();
|
|
307
311
|
if (upto != null && (this.parse.stoppedAt == null || this.parse.stoppedAt > upto) &&
|
|
@@ -319,7 +323,7 @@ class ParseContext {
|
|
|
319
323
|
else
|
|
320
324
|
return true;
|
|
321
325
|
}
|
|
322
|
-
if (
|
|
326
|
+
if (until())
|
|
323
327
|
return false;
|
|
324
328
|
}
|
|
325
329
|
});
|
|
@@ -452,6 +456,7 @@ class ParseContext {
|
|
|
452
456
|
@internal
|
|
453
457
|
*/
|
|
454
458
|
isDone(upto) {
|
|
459
|
+
upto = Math.min(upto, this.state.doc.length);
|
|
455
460
|
let frags = this.fragments;
|
|
456
461
|
return this.treeLen >= upto && frags.length && frags[0].from == 0 && frags[0].to >= upto;
|
|
457
462
|
}
|
|
@@ -473,7 +478,7 @@ class LanguageState {
|
|
|
473
478
|
this.tree = context.tree;
|
|
474
479
|
}
|
|
475
480
|
apply(tr) {
|
|
476
|
-
if (!tr.docChanged)
|
|
481
|
+
if (!tr.docChanged && this.tree == this.context.tree)
|
|
477
482
|
return this;
|
|
478
483
|
let newCx = this.context.changes(tr.changes, tr.state);
|
|
479
484
|
// If the previous parse wasn't done, go forward only up to its
|
|
@@ -515,6 +520,8 @@ if (typeof requestIdleCallback != "undefined")
|
|
|
515
520
|
}, 100 /* MinPause */);
|
|
516
521
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
517
522
|
};
|
|
523
|
+
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
524
|
+
? () => navigator.scheduling.isInputPending() : null;
|
|
518
525
|
const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
519
526
|
constructor(view) {
|
|
520
527
|
this.view = view;
|
|
@@ -555,11 +562,13 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
555
562
|
if (this.chunkBudget <= 0)
|
|
556
563
|
return; // No more budget
|
|
557
564
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
558
|
-
if (field.tree == field.context.tree && field.context.
|
|
565
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
559
566
|
return;
|
|
560
|
-
let
|
|
567
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
561
568
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
562
|
-
let done = field.context.work(
|
|
569
|
+
let done = field.context.work(() => {
|
|
570
|
+
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
571
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
563
572
|
this.chunkBudget -= Date.now() - now;
|
|
564
573
|
if (done || this.chunkBudget <= 0) {
|
|
565
574
|
field.context.takeTree();
|
|
@@ -584,7 +593,7 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
584
593
|
this.working();
|
|
585
594
|
}
|
|
586
595
|
isWorking() {
|
|
587
|
-
return this.working || this.workScheduled > 0;
|
|
596
|
+
return !!(this.working || this.workScheduled > 0);
|
|
588
597
|
}
|
|
589
598
|
}, {
|
|
590
599
|
eventHandlers: { focus() { this.scheduleWork(); } }
|
|
@@ -821,9 +830,11 @@ class IndentContext {
|
|
|
821
830
|
*/
|
|
822
831
|
lineAt(pos, bias = 1) {
|
|
823
832
|
let line = this.state.doc.lineAt(pos);
|
|
824
|
-
let { simulateBreak } = this.options;
|
|
833
|
+
let { simulateBreak, simulateDoubleBreak } = this.options;
|
|
825
834
|
if (simulateBreak != null && simulateBreak >= line.from && simulateBreak <= line.to) {
|
|
826
|
-
if (
|
|
835
|
+
if (simulateDoubleBreak && simulateBreak == pos)
|
|
836
|
+
return { text: "", from: pos };
|
|
837
|
+
else if (bias < 0 ? simulateBreak < pos : simulateBreak <= pos)
|
|
827
838
|
return { text: line.text.slice(simulateBreak - line.from), from: simulateBreak };
|
|
828
839
|
else
|
|
829
840
|
return { text: line.text.slice(0, simulateBreak - line.from), from: line.from };
|
|
@@ -1120,7 +1131,7 @@ function syntaxFolding(state, start, end) {
|
|
|
1120
1131
|
if (found && cur.from < start)
|
|
1121
1132
|
break;
|
|
1122
1133
|
let prop = cur.type.prop(foldNodeProp);
|
|
1123
|
-
if (prop) {
|
|
1134
|
+
if (prop && (cur.to < tree.length - 50 || tree.length == state.doc.length || !isUnfinished(cur))) {
|
|
1124
1135
|
let value = prop(cur, state);
|
|
1125
1136
|
if (value && value.from <= end && value.from >= start && value.to > end)
|
|
1126
1137
|
found = value;
|
|
@@ -1128,6 +1139,10 @@ function syntaxFolding(state, start, end) {
|
|
|
1128
1139
|
}
|
|
1129
1140
|
return found;
|
|
1130
1141
|
}
|
|
1142
|
+
function isUnfinished(node) {
|
|
1143
|
+
let ch = node.lastChild;
|
|
1144
|
+
return ch && ch.to == node.to && ch.type.isError;
|
|
1145
|
+
}
|
|
1131
1146
|
/**
|
|
1132
1147
|
Check whether the given line is foldable. First asks any fold
|
|
1133
1148
|
services registered through
|
package/dist/index.d.ts
CHANGED
|
@@ -156,7 +156,7 @@ stopped running, either because it parsed the entire document,
|
|
|
156
156
|
because it spent too much time and was cut off, or because there
|
|
157
157
|
is no language parser enabled.
|
|
158
158
|
*/
|
|
159
|
-
declare function syntaxParserRunning(view: EditorView): boolean
|
|
159
|
+
declare function syntaxParserRunning(view: EditorView): boolean;
|
|
160
160
|
/**
|
|
161
161
|
A parse context provided to parsers working on the editor content.
|
|
162
162
|
*/
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { StateEffect, StateField, Facet, EditorState } from '@codemirror/state';
|
|
|
3
3
|
import { ViewPlugin, logException } from '@codemirror/view';
|
|
4
4
|
import { countColumn } from '@codemirror/text';
|
|
5
5
|
|
|
6
|
+
var _a;
|
|
6
7
|
/**
|
|
7
8
|
Node prop stored in a grammar's top syntax node to provide the
|
|
8
9
|
facet that stores language data for that language.
|
|
@@ -175,7 +176,7 @@ up to that point if the tree isn't already available.
|
|
|
175
176
|
function ensureSyntaxTree(state, upto, timeout = 50) {
|
|
176
177
|
var _a;
|
|
177
178
|
let parse = (_a = state.field(Language.state, false)) === null || _a === void 0 ? void 0 : _a.context;
|
|
178
|
-
return !parse ? null : parse.
|
|
179
|
+
return !parse ? null : parse.isDone(upto) || parse.work(timeout, upto) ? parse.tree : null;
|
|
179
180
|
}
|
|
180
181
|
/**
|
|
181
182
|
Queries whether there is a full syntax tree available up to the
|
|
@@ -288,7 +289,7 @@ class ParseContext {
|
|
|
288
289
|
/**
|
|
289
290
|
@internal
|
|
290
291
|
*/
|
|
291
|
-
work(
|
|
292
|
+
work(until, upto) {
|
|
292
293
|
if (upto != null && upto >= this.state.doc.length)
|
|
293
294
|
upto = undefined;
|
|
294
295
|
if (this.tree != Tree.empty && this.isDone(upto !== null && upto !== void 0 ? upto : this.state.doc.length)) {
|
|
@@ -297,7 +298,10 @@ class ParseContext {
|
|
|
297
298
|
}
|
|
298
299
|
return this.withContext(() => {
|
|
299
300
|
var _a;
|
|
300
|
-
|
|
301
|
+
if (typeof until == "number") {
|
|
302
|
+
let endTime = Date.now() + until;
|
|
303
|
+
until = () => Date.now() > endTime;
|
|
304
|
+
}
|
|
301
305
|
if (!this.parse)
|
|
302
306
|
this.parse = this.startParse();
|
|
303
307
|
if (upto != null && (this.parse.stoppedAt == null || this.parse.stoppedAt > upto) &&
|
|
@@ -315,7 +319,7 @@ class ParseContext {
|
|
|
315
319
|
else
|
|
316
320
|
return true;
|
|
317
321
|
}
|
|
318
|
-
if (
|
|
322
|
+
if (until())
|
|
319
323
|
return false;
|
|
320
324
|
}
|
|
321
325
|
});
|
|
@@ -448,6 +452,7 @@ class ParseContext {
|
|
|
448
452
|
@internal
|
|
449
453
|
*/
|
|
450
454
|
isDone(upto) {
|
|
455
|
+
upto = Math.min(upto, this.state.doc.length);
|
|
451
456
|
let frags = this.fragments;
|
|
452
457
|
return this.treeLen >= upto && frags.length && frags[0].from == 0 && frags[0].to >= upto;
|
|
453
458
|
}
|
|
@@ -469,7 +474,7 @@ class LanguageState {
|
|
|
469
474
|
this.tree = context.tree;
|
|
470
475
|
}
|
|
471
476
|
apply(tr) {
|
|
472
|
-
if (!tr.docChanged)
|
|
477
|
+
if (!tr.docChanged && this.tree == this.context.tree)
|
|
473
478
|
return this;
|
|
474
479
|
let newCx = this.context.changes(tr.changes, tr.state);
|
|
475
480
|
// If the previous parse wasn't done, go forward only up to its
|
|
@@ -511,6 +516,8 @@ if (typeof requestIdleCallback != "undefined")
|
|
|
511
516
|
}, 100 /* MinPause */);
|
|
512
517
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
513
518
|
};
|
|
519
|
+
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
520
|
+
? () => navigator.scheduling.isInputPending() : null;
|
|
514
521
|
const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
515
522
|
constructor(view) {
|
|
516
523
|
this.view = view;
|
|
@@ -551,11 +558,13 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
551
558
|
if (this.chunkBudget <= 0)
|
|
552
559
|
return; // No more budget
|
|
553
560
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
554
|
-
if (field.tree == field.context.tree && field.context.
|
|
561
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
555
562
|
return;
|
|
556
|
-
let
|
|
563
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
557
564
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
558
|
-
let done = field.context.work(
|
|
565
|
+
let done = field.context.work(() => {
|
|
566
|
+
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
567
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
559
568
|
this.chunkBudget -= Date.now() - now;
|
|
560
569
|
if (done || this.chunkBudget <= 0) {
|
|
561
570
|
field.context.takeTree();
|
|
@@ -580,7 +589,7 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
580
589
|
this.working();
|
|
581
590
|
}
|
|
582
591
|
isWorking() {
|
|
583
|
-
return this.working || this.workScheduled > 0;
|
|
592
|
+
return !!(this.working || this.workScheduled > 0);
|
|
584
593
|
}
|
|
585
594
|
}, {
|
|
586
595
|
eventHandlers: { focus() { this.scheduleWork(); } }
|
|
@@ -817,9 +826,11 @@ class IndentContext {
|
|
|
817
826
|
*/
|
|
818
827
|
lineAt(pos, bias = 1) {
|
|
819
828
|
let line = this.state.doc.lineAt(pos);
|
|
820
|
-
let { simulateBreak } = this.options;
|
|
829
|
+
let { simulateBreak, simulateDoubleBreak } = this.options;
|
|
821
830
|
if (simulateBreak != null && simulateBreak >= line.from && simulateBreak <= line.to) {
|
|
822
|
-
if (
|
|
831
|
+
if (simulateDoubleBreak && simulateBreak == pos)
|
|
832
|
+
return { text: "", from: pos };
|
|
833
|
+
else if (bias < 0 ? simulateBreak < pos : simulateBreak <= pos)
|
|
823
834
|
return { text: line.text.slice(simulateBreak - line.from), from: simulateBreak };
|
|
824
835
|
else
|
|
825
836
|
return { text: line.text.slice(0, simulateBreak - line.from), from: line.from };
|
|
@@ -1116,7 +1127,7 @@ function syntaxFolding(state, start, end) {
|
|
|
1116
1127
|
if (found && cur.from < start)
|
|
1117
1128
|
break;
|
|
1118
1129
|
let prop = cur.type.prop(foldNodeProp);
|
|
1119
|
-
if (prop) {
|
|
1130
|
+
if (prop && (cur.to < tree.length - 50 || tree.length == state.doc.length || !isUnfinished(cur))) {
|
|
1120
1131
|
let value = prop(cur, state);
|
|
1121
1132
|
if (value && value.from <= end && value.from >= start && value.to > end)
|
|
1122
1133
|
found = value;
|
|
@@ -1124,6 +1135,10 @@ function syntaxFolding(state, start, end) {
|
|
|
1124
1135
|
}
|
|
1125
1136
|
return found;
|
|
1126
1137
|
}
|
|
1138
|
+
function isUnfinished(node) {
|
|
1139
|
+
let ch = node.lastChild;
|
|
1140
|
+
return ch && ch.to == node.to && ch.type.isError;
|
|
1141
|
+
}
|
|
1127
1142
|
/**
|
|
1128
1143
|
Check whether the given line is foldable. First asks any fold
|
|
1129
1144
|
services registered through
|