@codemirror/language 6.2.1 → 6.3.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 +16 -0
- package/dist/index.cjs +64 -40
- package/dist/index.d.ts +40 -14
- package/dist/index.js +66 -42
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 6.3.1 (2022-11-14)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make syntax-based folding include syntax nodes that start right at the end of a line as potential fold targets.
|
|
6
|
+
|
|
7
|
+
Fix the `indentService` protocol to allow a distinction between declining to handle the indentation and returning null to indicate the line has no definite indentation.
|
|
8
|
+
|
|
9
|
+
## 6.3.0 (2022-10-24)
|
|
10
|
+
|
|
11
|
+
### New features
|
|
12
|
+
|
|
13
|
+
`HighlightStyle` objects now have a `specs` property holding the tag styles that were used to define them.
|
|
14
|
+
|
|
15
|
+
`Language` objects now have a `name` field holding the language name.
|
|
16
|
+
|
|
1
17
|
## 6.2.1 (2022-07-21)
|
|
2
18
|
|
|
3
19
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -49,8 +49,13 @@ class Language {
|
|
|
49
49
|
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
|
|
50
50
|
used for this language.
|
|
51
51
|
*/
|
|
52
|
-
data, parser, extraExtensions = []
|
|
52
|
+
data, parser, extraExtensions = [],
|
|
53
|
+
/**
|
|
54
|
+
A language name.
|
|
55
|
+
*/
|
|
56
|
+
name = "") {
|
|
53
57
|
this.data = data;
|
|
58
|
+
this.name = name;
|
|
54
59
|
// Kludge to define EditorState.tree as a debugging helper,
|
|
55
60
|
// without the EditorState package actually knowing about
|
|
56
61
|
// languages and lezer trees.
|
|
@@ -138,8 +143,8 @@ A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language)
|
|
|
138
143
|
parsers.
|
|
139
144
|
*/
|
|
140
145
|
class LRLanguage extends Language {
|
|
141
|
-
constructor(data, parser) {
|
|
142
|
-
super(data, parser);
|
|
146
|
+
constructor(data, parser, name) {
|
|
147
|
+
super(data, parser, [], name);
|
|
143
148
|
this.parser = parser;
|
|
144
149
|
}
|
|
145
150
|
/**
|
|
@@ -149,14 +154,14 @@ class LRLanguage extends Language {
|
|
|
149
154
|
let data = defineLanguageFacet(spec.languageData);
|
|
150
155
|
return new LRLanguage(data, spec.parser.configure({
|
|
151
156
|
props: [languageDataProp.add(type => type.isTop ? data : undefined)]
|
|
152
|
-
}));
|
|
157
|
+
}), spec.name);
|
|
153
158
|
}
|
|
154
159
|
/**
|
|
155
160
|
Create a new instance of this language with a reconfigured
|
|
156
|
-
version of its parser.
|
|
161
|
+
version of its parser and optionally a new name.
|
|
157
162
|
*/
|
|
158
|
-
configure(options) {
|
|
159
|
-
return new LRLanguage(this.data, this.parser.configure(options));
|
|
163
|
+
configure(options, name) {
|
|
164
|
+
return new LRLanguage(this.data, this.parser.configure(options), name || this.name);
|
|
160
165
|
}
|
|
161
166
|
get allowsNesting() { return this.parser.hasWrappers(); }
|
|
162
167
|
}
|
|
@@ -503,14 +508,14 @@ class LanguageState {
|
|
|
503
508
|
// state updates with parse work beyond the viewport.
|
|
504
509
|
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
|
505
510
|
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
|
506
|
-
if (!newCx.work(20 /* Apply */, upto))
|
|
511
|
+
if (!newCx.work(20 /* Work.Apply */, upto))
|
|
507
512
|
newCx.takeTree();
|
|
508
513
|
return new LanguageState(newCx);
|
|
509
514
|
}
|
|
510
515
|
static init(state) {
|
|
511
|
-
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
516
|
+
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
|
512
517
|
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
|
513
|
-
if (!parseState.work(20 /* Apply */, vpTo))
|
|
518
|
+
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
|
514
519
|
parseState.takeTree();
|
|
515
520
|
return new LanguageState(parseState);
|
|
516
521
|
}
|
|
@@ -527,14 +532,14 @@ Language.state = state.StateField.define({
|
|
|
527
532
|
}
|
|
528
533
|
});
|
|
529
534
|
let requestIdle = (callback) => {
|
|
530
|
-
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
|
535
|
+
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
|
531
536
|
return () => clearTimeout(timeout);
|
|
532
537
|
};
|
|
533
538
|
if (typeof requestIdleCallback != "undefined")
|
|
534
539
|
requestIdle = (callback) => {
|
|
535
540
|
let idle = -1, timeout = setTimeout(() => {
|
|
536
|
-
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
|
537
|
-
}, 100 /* MinPause */);
|
|
541
|
+
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
|
542
|
+
}, 100 /* Work.MinPause */);
|
|
538
543
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
539
544
|
};
|
|
540
545
|
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
@@ -557,7 +562,7 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
557
562
|
this.scheduleWork();
|
|
558
563
|
if (update.docChanged) {
|
|
559
564
|
if (this.view.hasFocus)
|
|
560
|
-
this.chunkBudget += 50 /* ChangeBonus */;
|
|
565
|
+
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
|
561
566
|
this.scheduleWork();
|
|
562
567
|
}
|
|
563
568
|
this.checkAsyncSchedule(cx);
|
|
@@ -573,19 +578,19 @@ const parseWorker = view.ViewPlugin.fromClass(class ParseWorker {
|
|
|
573
578
|
this.working = null;
|
|
574
579
|
let now = Date.now();
|
|
575
580
|
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
|
576
|
-
this.chunkEnd = now + 30000 /* ChunkTime */;
|
|
577
|
-
this.chunkBudget = 3000 /* ChunkBudget */;
|
|
581
|
+
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
|
582
|
+
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
|
578
583
|
}
|
|
579
584
|
if (this.chunkBudget <= 0)
|
|
580
585
|
return; // No more budget
|
|
581
586
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
582
|
-
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
587
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
|
583
588
|
return;
|
|
584
|
-
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
589
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
585
590
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
586
591
|
let done = field.context.work(() => {
|
|
587
592
|
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
588
|
-
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
593
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
|
589
594
|
this.chunkBudget -= Date.now() - now;
|
|
590
595
|
if (done || this.chunkBudget <= 0) {
|
|
591
596
|
field.context.takeTree();
|
|
@@ -623,7 +628,14 @@ current language on a state.
|
|
|
623
628
|
*/
|
|
624
629
|
const language = state.Facet.define({
|
|
625
630
|
combine(languages) { return languages.length ? languages[0] : null; },
|
|
626
|
-
enables: [
|
|
631
|
+
enables: language => [
|
|
632
|
+
Language.state,
|
|
633
|
+
parseWorker,
|
|
634
|
+
view.EditorView.contentAttributes.compute([language], state => {
|
|
635
|
+
let lang = state.facet(language);
|
|
636
|
+
return lang && lang.name ? { "data-language": lang.name } : {};
|
|
637
|
+
})
|
|
638
|
+
]
|
|
627
639
|
});
|
|
628
640
|
/**
|
|
629
641
|
This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
|
|
@@ -753,8 +765,12 @@ class LanguageDescription {
|
|
|
753
765
|
|
|
754
766
|
/**
|
|
755
767
|
Facet that defines a way to provide a function that computes the
|
|
756
|
-
appropriate indentation depth
|
|
757
|
-
`
|
|
768
|
+
appropriate indentation depth, as a column number (see
|
|
769
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
|
770
|
+
line. A return value of `null` indicates no indentation can be
|
|
771
|
+
determined, and the line should inherit the indentation of the one
|
|
772
|
+
above it. A return value of `undefined` defers to the next indent
|
|
773
|
+
service.
|
|
758
774
|
*/
|
|
759
775
|
const indentService = state.Facet.define();
|
|
760
776
|
/**
|
|
@@ -799,19 +815,20 @@ function indentString(state, cols) {
|
|
|
799
815
|
return result;
|
|
800
816
|
}
|
|
801
817
|
/**
|
|
802
|
-
Get the indentation at the given position.
|
|
803
|
-
[indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
804
|
-
and if none of those return an indentation,
|
|
805
|
-
syntax tree for the [indent node
|
|
806
|
-
and use that if found. Returns a
|
|
807
|
-
be determined, and null
|
|
818
|
+
Get the indentation, as a column number, at the given position.
|
|
819
|
+
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
820
|
+
that are registered, and if none of those return an indentation,
|
|
821
|
+
this will check the syntax tree for the [indent node
|
|
822
|
+
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
|
823
|
+
number when an indentation could be determined, and null
|
|
824
|
+
otherwise.
|
|
808
825
|
*/
|
|
809
826
|
function getIndentation(context, pos) {
|
|
810
827
|
if (context instanceof state.EditorState)
|
|
811
828
|
context = new IndentContext(context);
|
|
812
829
|
for (let service of context.state.facet(indentService)) {
|
|
813
830
|
let result = service(context, pos);
|
|
814
|
-
if (result
|
|
831
|
+
if (result !== undefined)
|
|
815
832
|
return result;
|
|
816
833
|
}
|
|
817
834
|
let tree = syntaxTree(context.state);
|
|
@@ -939,8 +956,9 @@ class IndentContext {
|
|
|
939
956
|
/**
|
|
940
957
|
A syntax tree node prop used to associate indentation strategies
|
|
941
958
|
with node types. Such a strategy is a function from an indentation
|
|
942
|
-
context to a column number
|
|
943
|
-
|
|
959
|
+
context to a column number (see also
|
|
960
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
|
961
|
+
indicates that no definitive indentation can be determined.
|
|
944
962
|
*/
|
|
945
963
|
const indentNodeProp = new common.NodeProp();
|
|
946
964
|
// Compute the indentation for a given position from the syntax tree.
|
|
@@ -1171,7 +1189,7 @@ function syntaxFolding(state, start, end) {
|
|
|
1171
1189
|
let tree = syntaxTree(state);
|
|
1172
1190
|
if (tree.length < end)
|
|
1173
1191
|
return null;
|
|
1174
|
-
let inner = tree.resolveInner(end);
|
|
1192
|
+
let inner = tree.resolveInner(end, 1);
|
|
1175
1193
|
let found = null;
|
|
1176
1194
|
for (let cur = inner; cur; cur = cur.parent) {
|
|
1177
1195
|
if (cur.to <= end || cur.from > end)
|
|
@@ -1531,7 +1549,12 @@ A highlight style associates CSS styles with higlighting
|
|
|
1531
1549
|
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
|
1532
1550
|
*/
|
|
1533
1551
|
class HighlightStyle {
|
|
1534
|
-
constructor(
|
|
1552
|
+
constructor(
|
|
1553
|
+
/**
|
|
1554
|
+
The tag styles used to create this highlight style.
|
|
1555
|
+
*/
|
|
1556
|
+
specs, options) {
|
|
1557
|
+
this.specs = specs;
|
|
1535
1558
|
let modSpec;
|
|
1536
1559
|
function def(spec) {
|
|
1537
1560
|
let cls = styleMod.StyleModule.newName();
|
|
@@ -1542,7 +1565,7 @@ class HighlightStyle {
|
|
|
1542
1565
|
const scopeOpt = options.scope;
|
|
1543
1566
|
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
|
1544
1567
|
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
|
1545
|
-
this.style = highlight.tagHighlighter(
|
|
1568
|
+
this.style = highlight.tagHighlighter(specs.map(style => ({
|
|
1546
1569
|
tag: style.tag,
|
|
1547
1570
|
class: style.class || def(Object.assign({}, style, { tag: null }))
|
|
1548
1571
|
})), {
|
|
@@ -2021,6 +2044,7 @@ class StringStream {
|
|
|
2021
2044
|
|
|
2022
2045
|
function fullParser(spec) {
|
|
2023
2046
|
return {
|
|
2047
|
+
name: spec.name || "",
|
|
2024
2048
|
token: spec.token,
|
|
2025
2049
|
blankLine: spec.blankLine || (() => { }),
|
|
2026
2050
|
startState: spec.startState || (() => true),
|
|
@@ -2053,7 +2077,7 @@ class StreamLanguage extends Language {
|
|
|
2053
2077
|
return new Parse(self, input, fragments, ranges);
|
|
2054
2078
|
}
|
|
2055
2079
|
};
|
|
2056
|
-
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))]);
|
|
2080
|
+
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
|
|
2057
2081
|
this.topNode = docID(data);
|
|
2058
2082
|
self = this;
|
|
2059
2083
|
this.streamParser = p;
|
|
@@ -2079,7 +2103,7 @@ class StreamLanguage extends Language {
|
|
|
2079
2103
|
state = this.streamParser.startState(cx.unit);
|
|
2080
2104
|
statePos = 0;
|
|
2081
2105
|
}
|
|
2082
|
-
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
|
2106
|
+
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
|
2083
2107
|
return null;
|
|
2084
2108
|
while (statePos < pos) {
|
|
2085
2109
|
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
|
@@ -2158,7 +2182,7 @@ class Parse {
|
|
|
2158
2182
|
this.chunks.push(tree.children[i]);
|
|
2159
2183
|
this.chunkPos.push(tree.positions[i]);
|
|
2160
2184
|
}
|
|
2161
|
-
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
|
2185
|
+
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
|
2162
2186
|
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
|
2163
2187
|
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
|
2164
2188
|
this.parsedPos = context.viewport.from;
|
|
@@ -2168,7 +2192,7 @@ class Parse {
|
|
|
2168
2192
|
advance() {
|
|
2169
2193
|
let context = ParseContext.get();
|
|
2170
2194
|
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
|
2171
|
-
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
|
2195
|
+
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
|
2172
2196
|
if (context)
|
|
2173
2197
|
end = Math.min(end, context.viewport.to);
|
|
2174
2198
|
while (this.parsedPos < end)
|
|
@@ -2252,7 +2276,7 @@ class Parse {
|
|
|
2252
2276
|
let token = readToken(streamParser.token, stream, this.state);
|
|
2253
2277
|
if (token)
|
|
2254
2278
|
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
|
2255
|
-
if (stream.start > 10000 /* MaxLineLength */)
|
|
2279
|
+
if (stream.start > 10000 /* C.MaxLineLength */)
|
|
2256
2280
|
break;
|
|
2257
2281
|
}
|
|
2258
2282
|
}
|
|
@@ -2268,7 +2292,7 @@ class Parse {
|
|
|
2268
2292
|
length: this.parsedPos - this.chunkStart,
|
|
2269
2293
|
nodeSet,
|
|
2270
2294
|
topID: 0,
|
|
2271
|
-
maxBufferLength: 2048 /* ChunkSize */,
|
|
2295
|
+
maxBufferLength: 2048 /* C.ChunkSize */,
|
|
2272
2296
|
reused: this.chunkReused
|
|
2273
2297
|
});
|
|
2274
2298
|
tree = new common.Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|
package/dist/index.d.ts
CHANGED
|
@@ -48,6 +48,10 @@ declare class Language {
|
|
|
48
48
|
[name: string]: any;
|
|
49
49
|
}>;
|
|
50
50
|
/**
|
|
51
|
+
A language name.
|
|
52
|
+
*/
|
|
53
|
+
readonly name: string;
|
|
54
|
+
/**
|
|
51
55
|
The extension value to install this as the document language.
|
|
52
56
|
*/
|
|
53
57
|
readonly extension: Extension;
|
|
@@ -70,7 +74,11 @@ declare class Language {
|
|
|
70
74
|
*/
|
|
71
75
|
data: Facet<{
|
|
72
76
|
[name: string]: any;
|
|
73
|
-
}>, parser: Parser, extraExtensions?: Extension[]
|
|
77
|
+
}>, parser: Parser, extraExtensions?: Extension[],
|
|
78
|
+
/**
|
|
79
|
+
A language name.
|
|
80
|
+
*/
|
|
81
|
+
name?: string);
|
|
74
82
|
/**
|
|
75
83
|
Query whether this language is active at the given position.
|
|
76
84
|
*/
|
|
@@ -102,6 +110,10 @@ declare class LRLanguage extends Language {
|
|
|
102
110
|
Define a language from a parser.
|
|
103
111
|
*/
|
|
104
112
|
static define(spec: {
|
|
113
|
+
/**
|
|
114
|
+
The [name](https://codemirror.net/6/docs/ref/#Language.name) of the language.
|
|
115
|
+
*/
|
|
116
|
+
name?: string;
|
|
105
117
|
/**
|
|
106
118
|
The parser to use. Should already have added editor-relevant
|
|
107
119
|
node props (and optionally things like dialect and top rule)
|
|
@@ -118,9 +130,9 @@ declare class LRLanguage extends Language {
|
|
|
118
130
|
}): LRLanguage;
|
|
119
131
|
/**
|
|
120
132
|
Create a new instance of this language with a reconfigured
|
|
121
|
-
version of its parser.
|
|
133
|
+
version of its parser and optionally a new name.
|
|
122
134
|
*/
|
|
123
|
-
configure(options: ParserConfig): LRLanguage;
|
|
135
|
+
configure(options: ParserConfig, name?: string): LRLanguage;
|
|
124
136
|
get allowsNesting(): boolean;
|
|
125
137
|
}
|
|
126
138
|
/**
|
|
@@ -349,10 +361,14 @@ declare class LanguageDescription {
|
|
|
349
361
|
|
|
350
362
|
/**
|
|
351
363
|
Facet that defines a way to provide a function that computes the
|
|
352
|
-
appropriate indentation depth
|
|
353
|
-
`
|
|
364
|
+
appropriate indentation depth, as a column number (see
|
|
365
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
|
366
|
+
line. A return value of `null` indicates no indentation can be
|
|
367
|
+
determined, and the line should inherit the indentation of the one
|
|
368
|
+
above it. A return value of `undefined` defers to the next indent
|
|
369
|
+
service.
|
|
354
370
|
*/
|
|
355
|
-
declare const indentService: Facet<(context: IndentContext, pos: number) => number | null, readonly ((context: IndentContext, pos: number) => number | null)[]>;
|
|
371
|
+
declare const indentService: Facet<(context: IndentContext, pos: number) => number | null | undefined, readonly ((context: IndentContext, pos: number) => number | null | undefined)[]>;
|
|
356
372
|
/**
|
|
357
373
|
Facet for overriding the unit by which indentation happens.
|
|
358
374
|
Should be a string consisting either entirely of spaces or
|
|
@@ -374,12 +390,13 @@ tabs.
|
|
|
374
390
|
*/
|
|
375
391
|
declare function indentString(state: EditorState, cols: number): string;
|
|
376
392
|
/**
|
|
377
|
-
Get the indentation at the given position.
|
|
378
|
-
[indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
379
|
-
and if none of those return an indentation,
|
|
380
|
-
syntax tree for the [indent node
|
|
381
|
-
and use that if found. Returns a
|
|
382
|
-
be determined, and null
|
|
393
|
+
Get the indentation, as a column number, at the given position.
|
|
394
|
+
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
395
|
+
that are registered, and if none of those return an indentation,
|
|
396
|
+
this will check the syntax tree for the [indent node
|
|
397
|
+
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
|
398
|
+
number when an indentation could be determined, and null
|
|
399
|
+
otherwise.
|
|
383
400
|
*/
|
|
384
401
|
declare function getIndentation(context: IndentContext | EditorState, pos: number): number | null;
|
|
385
402
|
/**
|
|
@@ -477,8 +494,9 @@ declare class IndentContext {
|
|
|
477
494
|
/**
|
|
478
495
|
A syntax tree node prop used to associate indentation strategies
|
|
479
496
|
with node types. Such a strategy is a function from an indentation
|
|
480
|
-
context to a column number
|
|
481
|
-
|
|
497
|
+
context to a column number (see also
|
|
498
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
|
499
|
+
indicates that no definitive indentation can be determined.
|
|
482
500
|
*/
|
|
483
501
|
declare const indentNodeProp: NodeProp<(context: TreeIndentContext) => number | null>;
|
|
484
502
|
/**
|
|
@@ -732,6 +750,10 @@ A highlight style associates CSS styles with higlighting
|
|
|
732
750
|
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
|
733
751
|
*/
|
|
734
752
|
declare class HighlightStyle implements Highlighter {
|
|
753
|
+
/**
|
|
754
|
+
The tag styles used to create this highlight style.
|
|
755
|
+
*/
|
|
756
|
+
readonly specs: readonly TagStyle[];
|
|
735
757
|
/**
|
|
736
758
|
A style module holding the CSS rules for this highlight style.
|
|
737
759
|
When using
|
|
@@ -1013,6 +1035,10 @@ copyable) object with state, in which it can store information
|
|
|
1013
1035
|
about the current context.
|
|
1014
1036
|
*/
|
|
1015
1037
|
interface StreamParser<State> {
|
|
1038
|
+
/**
|
|
1039
|
+
A name for this language.
|
|
1040
|
+
*/
|
|
1041
|
+
name?: string;
|
|
1016
1042
|
/**
|
|
1017
1043
|
Produce a start state for the parser.
|
|
1018
1044
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
|
-
import { ViewPlugin, logException,
|
|
3
|
+
import { ViewPlugin, logException, EditorView, Decoration, WidgetType, gutter, GutterMarker } from '@codemirror/view';
|
|
4
4
|
import { tags, tagHighlighter, highlightTree, styleTags } from '@lezer/highlight';
|
|
5
5
|
import { StyleModule } from 'style-mod';
|
|
6
6
|
|
|
@@ -45,8 +45,13 @@ class Language {
|
|
|
45
45
|
The [language data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) facet
|
|
46
46
|
used for this language.
|
|
47
47
|
*/
|
|
48
|
-
data, parser, extraExtensions = []
|
|
48
|
+
data, parser, extraExtensions = [],
|
|
49
|
+
/**
|
|
50
|
+
A language name.
|
|
51
|
+
*/
|
|
52
|
+
name = "") {
|
|
49
53
|
this.data = data;
|
|
54
|
+
this.name = name;
|
|
50
55
|
// Kludge to define EditorState.tree as a debugging helper,
|
|
51
56
|
// without the EditorState package actually knowing about
|
|
52
57
|
// languages and lezer trees.
|
|
@@ -134,8 +139,8 @@ A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language)
|
|
|
134
139
|
parsers.
|
|
135
140
|
*/
|
|
136
141
|
class LRLanguage extends Language {
|
|
137
|
-
constructor(data, parser) {
|
|
138
|
-
super(data, parser);
|
|
142
|
+
constructor(data, parser, name) {
|
|
143
|
+
super(data, parser, [], name);
|
|
139
144
|
this.parser = parser;
|
|
140
145
|
}
|
|
141
146
|
/**
|
|
@@ -145,14 +150,14 @@ class LRLanguage extends Language {
|
|
|
145
150
|
let data = defineLanguageFacet(spec.languageData);
|
|
146
151
|
return new LRLanguage(data, spec.parser.configure({
|
|
147
152
|
props: [languageDataProp.add(type => type.isTop ? data : undefined)]
|
|
148
|
-
}));
|
|
153
|
+
}), spec.name);
|
|
149
154
|
}
|
|
150
155
|
/**
|
|
151
156
|
Create a new instance of this language with a reconfigured
|
|
152
|
-
version of its parser.
|
|
157
|
+
version of its parser and optionally a new name.
|
|
153
158
|
*/
|
|
154
|
-
configure(options) {
|
|
155
|
-
return new LRLanguage(this.data, this.parser.configure(options));
|
|
159
|
+
configure(options, name) {
|
|
160
|
+
return new LRLanguage(this.data, this.parser.configure(options), name || this.name);
|
|
156
161
|
}
|
|
157
162
|
get allowsNesting() { return this.parser.hasWrappers(); }
|
|
158
163
|
}
|
|
@@ -499,14 +504,14 @@ class LanguageState {
|
|
|
499
504
|
// state updates with parse work beyond the viewport.
|
|
500
505
|
let upto = this.context.treeLen == tr.startState.doc.length ? undefined
|
|
501
506
|
: Math.max(tr.changes.mapPos(this.context.treeLen), newCx.viewport.to);
|
|
502
|
-
if (!newCx.work(20 /* Apply */, upto))
|
|
507
|
+
if (!newCx.work(20 /* Work.Apply */, upto))
|
|
503
508
|
newCx.takeTree();
|
|
504
509
|
return new LanguageState(newCx);
|
|
505
510
|
}
|
|
506
511
|
static init(state) {
|
|
507
|
-
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
512
|
+
let vpTo = Math.min(3000 /* Work.InitViewport */, state.doc.length);
|
|
508
513
|
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
|
509
|
-
if (!parseState.work(20 /* Apply */, vpTo))
|
|
514
|
+
if (!parseState.work(20 /* Work.Apply */, vpTo))
|
|
510
515
|
parseState.takeTree();
|
|
511
516
|
return new LanguageState(parseState);
|
|
512
517
|
}
|
|
@@ -523,14 +528,14 @@ Language.state = /*@__PURE__*/StateField.define({
|
|
|
523
528
|
}
|
|
524
529
|
});
|
|
525
530
|
let requestIdle = (callback) => {
|
|
526
|
-
let timeout = setTimeout(() => callback(), 500 /* MaxPause */);
|
|
531
|
+
let timeout = setTimeout(() => callback(), 500 /* Work.MaxPause */);
|
|
527
532
|
return () => clearTimeout(timeout);
|
|
528
533
|
};
|
|
529
534
|
if (typeof requestIdleCallback != "undefined")
|
|
530
535
|
requestIdle = (callback) => {
|
|
531
536
|
let idle = -1, timeout = setTimeout(() => {
|
|
532
|
-
idle = requestIdleCallback(callback, { timeout: 500 /* MaxPause */ - 100 /* MinPause */ });
|
|
533
|
-
}, 100 /* MinPause */);
|
|
537
|
+
idle = requestIdleCallback(callback, { timeout: 500 /* Work.MaxPause */ - 100 /* Work.MinPause */ });
|
|
538
|
+
}, 100 /* Work.MinPause */);
|
|
534
539
|
return () => idle < 0 ? clearTimeout(timeout) : cancelIdleCallback(idle);
|
|
535
540
|
};
|
|
536
541
|
const isInputPending = typeof navigator != "undefined" && ((_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending)
|
|
@@ -553,7 +558,7 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
553
558
|
this.scheduleWork();
|
|
554
559
|
if (update.docChanged) {
|
|
555
560
|
if (this.view.hasFocus)
|
|
556
|
-
this.chunkBudget += 50 /* ChangeBonus */;
|
|
561
|
+
this.chunkBudget += 50 /* Work.ChangeBonus */;
|
|
557
562
|
this.scheduleWork();
|
|
558
563
|
}
|
|
559
564
|
this.checkAsyncSchedule(cx);
|
|
@@ -569,19 +574,19 @@ const parseWorker = /*@__PURE__*/ViewPlugin.fromClass(class ParseWorker {
|
|
|
569
574
|
this.working = null;
|
|
570
575
|
let now = Date.now();
|
|
571
576
|
if (this.chunkEnd < now && (this.chunkEnd < 0 || this.view.hasFocus)) { // Start a new chunk
|
|
572
|
-
this.chunkEnd = now + 30000 /* ChunkTime */;
|
|
573
|
-
this.chunkBudget = 3000 /* ChunkBudget */;
|
|
577
|
+
this.chunkEnd = now + 30000 /* Work.ChunkTime */;
|
|
578
|
+
this.chunkBudget = 3000 /* Work.ChunkBudget */;
|
|
574
579
|
}
|
|
575
580
|
if (this.chunkBudget <= 0)
|
|
576
581
|
return; // No more budget
|
|
577
582
|
let { state, viewport: { to: vpTo } } = this.view, field = state.field(Language.state);
|
|
578
|
-
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* MaxParseAhead */))
|
|
583
|
+
if (field.tree == field.context.tree && field.context.isDone(vpTo + 100000 /* Work.MaxParseAhead */))
|
|
579
584
|
return;
|
|
580
|
-
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Slice */, deadline && !isInputPending ? Math.max(25 /* MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
585
|
+
let endTime = Date.now() + Math.min(this.chunkBudget, 100 /* Work.Slice */, deadline && !isInputPending ? Math.max(25 /* Work.MinSlice */, deadline.timeRemaining() - 5) : 1e9);
|
|
581
586
|
let viewportFirst = field.context.treeLen < vpTo && state.doc.length > vpTo + 1000;
|
|
582
587
|
let done = field.context.work(() => {
|
|
583
588
|
return isInputPending && isInputPending() || Date.now() > endTime;
|
|
584
|
-
}, vpTo + (viewportFirst ? 0 : 100000 /* MaxParseAhead */));
|
|
589
|
+
}, vpTo + (viewportFirst ? 0 : 100000 /* Work.MaxParseAhead */));
|
|
585
590
|
this.chunkBudget -= Date.now() - now;
|
|
586
591
|
if (done || this.chunkBudget <= 0) {
|
|
587
592
|
field.context.takeTree();
|
|
@@ -619,7 +624,14 @@ current language on a state.
|
|
|
619
624
|
*/
|
|
620
625
|
const language = /*@__PURE__*/Facet.define({
|
|
621
626
|
combine(languages) { return languages.length ? languages[0] : null; },
|
|
622
|
-
enables: [
|
|
627
|
+
enables: language => [
|
|
628
|
+
Language.state,
|
|
629
|
+
parseWorker,
|
|
630
|
+
EditorView.contentAttributes.compute([language], state => {
|
|
631
|
+
let lang = state.facet(language);
|
|
632
|
+
return lang && lang.name ? { "data-language": lang.name } : {};
|
|
633
|
+
})
|
|
634
|
+
]
|
|
623
635
|
});
|
|
624
636
|
/**
|
|
625
637
|
This class bundles a [language](https://codemirror.net/6/docs/ref/#language.Language) with an
|
|
@@ -749,8 +761,12 @@ class LanguageDescription {
|
|
|
749
761
|
|
|
750
762
|
/**
|
|
751
763
|
Facet that defines a way to provide a function that computes the
|
|
752
|
-
appropriate indentation depth
|
|
753
|
-
`
|
|
764
|
+
appropriate indentation depth, as a column number (see
|
|
765
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)), at the start of a given
|
|
766
|
+
line. A return value of `null` indicates no indentation can be
|
|
767
|
+
determined, and the line should inherit the indentation of the one
|
|
768
|
+
above it. A return value of `undefined` defers to the next indent
|
|
769
|
+
service.
|
|
754
770
|
*/
|
|
755
771
|
const indentService = /*@__PURE__*/Facet.define();
|
|
756
772
|
/**
|
|
@@ -795,19 +811,20 @@ function indentString(state, cols) {
|
|
|
795
811
|
return result;
|
|
796
812
|
}
|
|
797
813
|
/**
|
|
798
|
-
Get the indentation at the given position.
|
|
799
|
-
[indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
800
|
-
and if none of those return an indentation,
|
|
801
|
-
syntax tree for the [indent node
|
|
802
|
-
and use that if found. Returns a
|
|
803
|
-
be determined, and null
|
|
814
|
+
Get the indentation, as a column number, at the given position.
|
|
815
|
+
Will first consult any [indent services](https://codemirror.net/6/docs/ref/#language.indentService)
|
|
816
|
+
that are registered, and if none of those return an indentation,
|
|
817
|
+
this will check the syntax tree for the [indent node
|
|
818
|
+
prop](https://codemirror.net/6/docs/ref/#language.indentNodeProp) and use that if found. Returns a
|
|
819
|
+
number when an indentation could be determined, and null
|
|
820
|
+
otherwise.
|
|
804
821
|
*/
|
|
805
822
|
function getIndentation(context, pos) {
|
|
806
823
|
if (context instanceof EditorState)
|
|
807
824
|
context = new IndentContext(context);
|
|
808
825
|
for (let service of context.state.facet(indentService)) {
|
|
809
826
|
let result = service(context, pos);
|
|
810
|
-
if (result
|
|
827
|
+
if (result !== undefined)
|
|
811
828
|
return result;
|
|
812
829
|
}
|
|
813
830
|
let tree = syntaxTree(context.state);
|
|
@@ -935,8 +952,9 @@ class IndentContext {
|
|
|
935
952
|
/**
|
|
936
953
|
A syntax tree node prop used to associate indentation strategies
|
|
937
954
|
with node types. Such a strategy is a function from an indentation
|
|
938
|
-
context to a column number
|
|
939
|
-
|
|
955
|
+
context to a column number (see also
|
|
956
|
+
[`indentString`](https://codemirror.net/6/docs/ref/#language.indentString)) or null, where null
|
|
957
|
+
indicates that no definitive indentation can be determined.
|
|
940
958
|
*/
|
|
941
959
|
const indentNodeProp = /*@__PURE__*/new NodeProp();
|
|
942
960
|
// Compute the indentation for a given position from the syntax tree.
|
|
@@ -1167,7 +1185,7 @@ function syntaxFolding(state, start, end) {
|
|
|
1167
1185
|
let tree = syntaxTree(state);
|
|
1168
1186
|
if (tree.length < end)
|
|
1169
1187
|
return null;
|
|
1170
|
-
let inner = tree.resolveInner(end);
|
|
1188
|
+
let inner = tree.resolveInner(end, 1);
|
|
1171
1189
|
let found = null;
|
|
1172
1190
|
for (let cur = inner; cur; cur = cur.parent) {
|
|
1173
1191
|
if (cur.to <= end || cur.from > end)
|
|
@@ -1527,7 +1545,12 @@ A highlight style associates CSS styles with higlighting
|
|
|
1527
1545
|
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
|
|
1528
1546
|
*/
|
|
1529
1547
|
class HighlightStyle {
|
|
1530
|
-
constructor(
|
|
1548
|
+
constructor(
|
|
1549
|
+
/**
|
|
1550
|
+
The tag styles used to create this highlight style.
|
|
1551
|
+
*/
|
|
1552
|
+
specs, options) {
|
|
1553
|
+
this.specs = specs;
|
|
1531
1554
|
let modSpec;
|
|
1532
1555
|
function def(spec) {
|
|
1533
1556
|
let cls = StyleModule.newName();
|
|
@@ -1538,7 +1561,7 @@ class HighlightStyle {
|
|
|
1538
1561
|
const scopeOpt = options.scope;
|
|
1539
1562
|
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
|
1540
1563
|
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
|
1541
|
-
this.style = tagHighlighter(
|
|
1564
|
+
this.style = tagHighlighter(specs.map(style => ({
|
|
1542
1565
|
tag: style.tag,
|
|
1543
1566
|
class: style.class || def(Object.assign({}, style, { tag: null }))
|
|
1544
1567
|
})), {
|
|
@@ -2017,6 +2040,7 @@ class StringStream {
|
|
|
2017
2040
|
|
|
2018
2041
|
function fullParser(spec) {
|
|
2019
2042
|
return {
|
|
2043
|
+
name: spec.name || "",
|
|
2020
2044
|
token: spec.token,
|
|
2021
2045
|
blankLine: spec.blankLine || (() => { }),
|
|
2022
2046
|
startState: spec.startState || (() => true),
|
|
@@ -2049,7 +2073,7 @@ class StreamLanguage extends Language {
|
|
|
2049
2073
|
return new Parse(self, input, fragments, ranges);
|
|
2050
2074
|
}
|
|
2051
2075
|
};
|
|
2052
|
-
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))]);
|
|
2076
|
+
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
|
|
2053
2077
|
this.topNode = docID(data);
|
|
2054
2078
|
self = this;
|
|
2055
2079
|
this.streamParser = p;
|
|
@@ -2075,7 +2099,7 @@ class StreamLanguage extends Language {
|
|
|
2075
2099
|
state = this.streamParser.startState(cx.unit);
|
|
2076
2100
|
statePos = 0;
|
|
2077
2101
|
}
|
|
2078
|
-
if (pos - statePos > 10000 /* MaxIndentScanDist */)
|
|
2102
|
+
if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
|
|
2079
2103
|
return null;
|
|
2080
2104
|
while (statePos < pos) {
|
|
2081
2105
|
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
|
|
@@ -2154,7 +2178,7 @@ class Parse {
|
|
|
2154
2178
|
this.chunks.push(tree.children[i]);
|
|
2155
2179
|
this.chunkPos.push(tree.positions[i]);
|
|
2156
2180
|
}
|
|
2157
|
-
if (context && this.parsedPos < context.viewport.from - 100000 /* MaxDistanceBeforeViewport */) {
|
|
2181
|
+
if (context && this.parsedPos < context.viewport.from - 100000 /* C.MaxDistanceBeforeViewport */) {
|
|
2158
2182
|
this.state = this.lang.streamParser.startState(getIndentUnit(context.state));
|
|
2159
2183
|
context.skipUntilInView(this.parsedPos, context.viewport.from);
|
|
2160
2184
|
this.parsedPos = context.viewport.from;
|
|
@@ -2164,7 +2188,7 @@ class Parse {
|
|
|
2164
2188
|
advance() {
|
|
2165
2189
|
let context = ParseContext.get();
|
|
2166
2190
|
let parseEnd = this.stoppedAt == null ? this.to : Math.min(this.to, this.stoppedAt);
|
|
2167
|
-
let end = Math.min(parseEnd, this.chunkStart + 2048 /* ChunkSize */);
|
|
2191
|
+
let end = Math.min(parseEnd, this.chunkStart + 2048 /* C.ChunkSize */);
|
|
2168
2192
|
if (context)
|
|
2169
2193
|
end = Math.min(end, context.viewport.to);
|
|
2170
2194
|
while (this.parsedPos < end)
|
|
@@ -2248,7 +2272,7 @@ class Parse {
|
|
|
2248
2272
|
let token = readToken(streamParser.token, stream, this.state);
|
|
2249
2273
|
if (token)
|
|
2250
2274
|
offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
|
|
2251
|
-
if (stream.start > 10000 /* MaxLineLength */)
|
|
2275
|
+
if (stream.start > 10000 /* C.MaxLineLength */)
|
|
2252
2276
|
break;
|
|
2253
2277
|
}
|
|
2254
2278
|
}
|
|
@@ -2264,7 +2288,7 @@ class Parse {
|
|
|
2264
2288
|
length: this.parsedPos - this.chunkStart,
|
|
2265
2289
|
nodeSet,
|
|
2266
2290
|
topID: 0,
|
|
2267
|
-
maxBufferLength: 2048 /* ChunkSize */,
|
|
2291
|
+
maxBufferLength: 2048 /* C.ChunkSize */,
|
|
2268
2292
|
reused: this.chunkReused
|
|
2269
2293
|
});
|
|
2270
2294
|
tree = new Tree(tree.type, tree.children, tree.positions, tree.length, [[this.lang.stateAfter, this.lang.streamParser.copyState(this.state)]]);
|