@codemirror/language 6.10.2 → 6.10.4

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 CHANGED
@@ -1,3 +1,21 @@
1
+ ## 6.10.4 (2024-11-24)
2
+
3
+ ### Bug fixes
4
+
5
+ Join adjacent tokens of the same type into a single token in .
6
+
7
+ Call stream language indent functions even when the language is used as a nested parser.
8
+
9
+ Fix a crash in `StreamParser` when a parse was resumed with different input ranges.
10
+
11
+ ## 6.10.3 (2024-09-19)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix a TypeScript error when using `HighlightStyle` with the `exactOptionalPropertyTypes` typechecking option enabled.
16
+
17
+ Make `delimitedIndent` align to spaces after the opening token.
18
+
1
19
  ## 6.10.2 (2024-06-03)
2
20
 
3
21
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1121,8 +1121,12 @@ function bracketedAligned(context) {
1121
1121
  let next = tree.childAfter(pos);
1122
1122
  if (!next || next == last)
1123
1123
  return null;
1124
- if (!next.type.isSkipped)
1125
- return next.from < lineEnd ? openToken : null;
1124
+ if (!next.type.isSkipped) {
1125
+ if (next.from >= lineEnd)
1126
+ return null;
1127
+ let space = /^ */.exec(openLine.text.slice(openToken.to - openLine.from))[0].length;
1128
+ return { from: openToken.from, to: openToken.to + space };
1129
+ }
1126
1130
  pos = next.to;
1127
1131
  }
1128
1132
  }
@@ -2204,8 +2208,8 @@ class StreamLanguage extends Language {
2204
2208
  return new Parse(self, input, fragments, ranges);
2205
2209
  }
2206
2210
  };
2207
- super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
2208
- this.topNode = docID(data);
2211
+ super(data, impl, [], parser.name);
2212
+ this.topNode = docID(data, this);
2209
2213
  self = this;
2210
2214
  this.streamParser = p;
2211
2215
  this.stateAfter = new common.NodeProp({ perNode: true });
@@ -2215,20 +2219,18 @@ class StreamLanguage extends Language {
2215
2219
  Define a stream language.
2216
2220
  */
2217
2221
  static define(spec) { return new StreamLanguage(spec); }
2218
- getIndent(cx, pos) {
2219
- let tree = syntaxTree(cx.state), at = tree.resolve(pos);
2220
- while (at && at.type != this.topNode)
2221
- at = at.parent;
2222
- if (!at)
2223
- return null;
2222
+ /**
2223
+ @internal
2224
+ */
2225
+ getIndent(cx) {
2224
2226
  let from = undefined;
2225
2227
  let { overrideIndentation } = cx.options;
2226
2228
  if (overrideIndentation) {
2227
2229
  from = IndentedFrom.get(cx.state);
2228
- if (from != null && from < pos - 1e4)
2230
+ if (from != null && from < cx.pos - 1e4)
2229
2231
  from = undefined;
2230
2232
  }
2231
- let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state;
2233
+ let start = findState(this, cx.node.tree, 0, cx.node.from, from !== null && from !== void 0 ? from : cx.pos), statePos, state;
2232
2234
  if (start) {
2233
2235
  state = start.state;
2234
2236
  statePos = start.pos + 1;
@@ -2237,10 +2239,10 @@ class StreamLanguage extends Language {
2237
2239
  state = this.streamParser.startState(cx.unit);
2238
2240
  statePos = 0;
2239
2241
  }
2240
- if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
2242
+ if (cx.pos - statePos > 10000 /* C.MaxIndentScanDist */)
2241
2243
  return null;
2242
- while (statePos < pos) {
2243
- let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
2244
+ while (statePos < cx.pos) {
2245
+ let line = cx.state.doc.lineAt(statePos), end = Math.min(cx.pos, line.to);
2244
2246
  if (line.length) {
2245
2247
  let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
2246
2248
  let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
@@ -2250,11 +2252,11 @@ class StreamLanguage extends Language {
2250
2252
  else {
2251
2253
  this.streamParser.blankLine(state, cx.unit);
2252
2254
  }
2253
- if (end == pos)
2255
+ if (end == cx.pos)
2254
2256
  break;
2255
2257
  statePos = line.to + 1;
2256
2258
  }
2257
- let line = cx.lineAt(pos);
2259
+ let line = cx.lineAt(cx.pos);
2258
2260
  if (overrideIndentation && from == null)
2259
2261
  IndentedFrom.set(cx.state, line.from);
2260
2262
  return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
@@ -2289,11 +2291,11 @@ function cutTree(lang, tree, from, to, inside) {
2289
2291
  }
2290
2292
  return null;
2291
2293
  }
2292
- function findStartInFragments(lang, fragments, startPos, editorState) {
2294
+ function findStartInFragments(lang, fragments, startPos, endPos, editorState) {
2293
2295
  for (let f of fragments) {
2294
2296
  let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
2295
2297
  let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
2296
- if (found && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
2298
+ if (found && found.pos <= endPos && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
2297
2299
  return { state: found.state, tree };
2298
2300
  }
2299
2301
  return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: common.Tree.empty };
@@ -2312,7 +2314,7 @@ class Parse {
2312
2314
  this.rangeIndex = 0;
2313
2315
  this.to = ranges[ranges.length - 1].to;
2314
2316
  let context = ParseContext.get(), from = ranges[0].from;
2315
- let { state, tree } = findStartInFragments(lang, fragments, from, context === null || context === void 0 ? void 0 : context.state);
2317
+ let { state, tree } = findStartInFragments(lang, fragments, from, ranges[ranges.length - 1].to, context === null || context === void 0 ? void 0 : context.state);
2316
2318
  this.state = state;
2317
2319
  this.parsedPos = this.chunkStart = from + tree.length;
2318
2320
  for (let i = 0; i < tree.children.length; i++) {
@@ -2390,7 +2392,8 @@ class Parse {
2390
2392
  while (this.ranges[this.rangeIndex].to < this.parsedPos)
2391
2393
  this.rangeIndex++;
2392
2394
  }
2393
- emitToken(id, from, to, size, offset) {
2395
+ emitToken(id, from, to, offset) {
2396
+ let size = 4;
2394
2397
  if (this.ranges.length > 1) {
2395
2398
  offset = this.skipGapsTo(from, offset, 1);
2396
2399
  from += offset;
@@ -2399,7 +2402,11 @@ class Parse {
2399
2402
  to += offset;
2400
2403
  size += this.chunk.length - len0;
2401
2404
  }
2402
- this.chunk.push(id, from, to, size);
2405
+ let last = this.chunk.length - 4;
2406
+ if (size == 4 && last >= 0 && this.chunk[last] == id && this.chunk[last + 2] == from)
2407
+ this.chunk[last + 2] = to;
2408
+ else
2409
+ this.chunk.push(id, from, to, size);
2403
2410
  return offset;
2404
2411
  }
2405
2412
  parseLine(context) {
@@ -2412,7 +2419,7 @@ class Parse {
2412
2419
  while (!stream.eol()) {
2413
2420
  let token = readToken(streamParser.token, stream, this.state);
2414
2421
  if (token)
2415
- offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
2422
+ offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, offset);
2416
2423
  if (stream.start > 10000 /* C.MaxLineLength */)
2417
2424
  break;
2418
2425
  }
@@ -2529,8 +2536,11 @@ function createTokenType(extra, tagStr) {
2529
2536
  typeArray.push(type);
2530
2537
  return type.id;
2531
2538
  }
2532
- function docID(data) {
2533
- let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
2539
+ function docID(data, lang) {
2540
+ let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [
2541
+ languageDataProp.add(() => data),
2542
+ indentNodeProp.add(() => cx => lang.getIndent(cx))
2543
+ ], top: true });
2534
2544
  typeArray.push(type);
2535
2545
  return type;
2536
2546
  }
package/dist/index.d.cts CHANGED
@@ -845,7 +845,7 @@ declare class HighlightStyle implements Highlighter {
845
845
  */
846
846
  readonly module: StyleModule | null;
847
847
  readonly style: (tags: readonly Tag[]) => string | null;
848
- readonly scope: ((type: NodeType) => boolean) | undefined;
848
+ readonly scope?: (type: NodeType) => boolean;
849
849
  private constructor();
850
850
  /**
851
851
  Create a highlighter style that associates the given styles to
@@ -1193,7 +1193,6 @@ declare class StreamLanguage<State> extends Language {
1193
1193
  Define a stream language.
1194
1194
  */
1195
1195
  static define<State>(spec: StreamParser<State>): StreamLanguage<State>;
1196
- private getIndent;
1197
1196
  get allowsNesting(): boolean;
1198
1197
  }
1199
1198
 
package/dist/index.d.ts CHANGED
@@ -845,7 +845,7 @@ declare class HighlightStyle implements Highlighter {
845
845
  */
846
846
  readonly module: StyleModule | null;
847
847
  readonly style: (tags: readonly Tag[]) => string | null;
848
- readonly scope: ((type: NodeType) => boolean) | undefined;
848
+ readonly scope?: (type: NodeType) => boolean;
849
849
  private constructor();
850
850
  /**
851
851
  Create a highlighter style that associates the given styles to
@@ -1193,7 +1193,6 @@ declare class StreamLanguage<State> extends Language {
1193
1193
  Define a stream language.
1194
1194
  */
1195
1195
  static define<State>(spec: StreamParser<State>): StreamLanguage<State>;
1196
- private getIndent;
1197
1196
  get allowsNesting(): boolean;
1198
1197
  }
1199
1198
 
package/dist/index.js CHANGED
@@ -1119,8 +1119,12 @@ function bracketedAligned(context) {
1119
1119
  let next = tree.childAfter(pos);
1120
1120
  if (!next || next == last)
1121
1121
  return null;
1122
- if (!next.type.isSkipped)
1123
- return next.from < lineEnd ? openToken : null;
1122
+ if (!next.type.isSkipped) {
1123
+ if (next.from >= lineEnd)
1124
+ return null;
1125
+ let space = /^ */.exec(openLine.text.slice(openToken.to - openLine.from))[0].length;
1126
+ return { from: openToken.from, to: openToken.to + space };
1127
+ }
1124
1128
  pos = next.to;
1125
1129
  }
1126
1130
  }
@@ -2202,8 +2206,8 @@ class StreamLanguage extends Language {
2202
2206
  return new Parse(self, input, fragments, ranges);
2203
2207
  }
2204
2208
  };
2205
- super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
2206
- this.topNode = docID(data);
2209
+ super(data, impl, [], parser.name);
2210
+ this.topNode = docID(data, this);
2207
2211
  self = this;
2208
2212
  this.streamParser = p;
2209
2213
  this.stateAfter = new NodeProp({ perNode: true });
@@ -2213,20 +2217,18 @@ class StreamLanguage extends Language {
2213
2217
  Define a stream language.
2214
2218
  */
2215
2219
  static define(spec) { return new StreamLanguage(spec); }
2216
- getIndent(cx, pos) {
2217
- let tree = syntaxTree(cx.state), at = tree.resolve(pos);
2218
- while (at && at.type != this.topNode)
2219
- at = at.parent;
2220
- if (!at)
2221
- return null;
2220
+ /**
2221
+ @internal
2222
+ */
2223
+ getIndent(cx) {
2222
2224
  let from = undefined;
2223
2225
  let { overrideIndentation } = cx.options;
2224
2226
  if (overrideIndentation) {
2225
2227
  from = IndentedFrom.get(cx.state);
2226
- if (from != null && from < pos - 1e4)
2228
+ if (from != null && from < cx.pos - 1e4)
2227
2229
  from = undefined;
2228
2230
  }
2229
- let start = findState(this, tree, 0, at.from, from !== null && from !== void 0 ? from : pos), statePos, state;
2231
+ let start = findState(this, cx.node.tree, 0, cx.node.from, from !== null && from !== void 0 ? from : cx.pos), statePos, state;
2230
2232
  if (start) {
2231
2233
  state = start.state;
2232
2234
  statePos = start.pos + 1;
@@ -2235,10 +2237,10 @@ class StreamLanguage extends Language {
2235
2237
  state = this.streamParser.startState(cx.unit);
2236
2238
  statePos = 0;
2237
2239
  }
2238
- if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
2240
+ if (cx.pos - statePos > 10000 /* C.MaxIndentScanDist */)
2239
2241
  return null;
2240
- while (statePos < pos) {
2241
- let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to);
2242
+ while (statePos < cx.pos) {
2243
+ let line = cx.state.doc.lineAt(statePos), end = Math.min(cx.pos, line.to);
2242
2244
  if (line.length) {
2243
2245
  let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
2244
2246
  let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
@@ -2248,11 +2250,11 @@ class StreamLanguage extends Language {
2248
2250
  else {
2249
2251
  this.streamParser.blankLine(state, cx.unit);
2250
2252
  }
2251
- if (end == pos)
2253
+ if (end == cx.pos)
2252
2254
  break;
2253
2255
  statePos = line.to + 1;
2254
2256
  }
2255
- let line = cx.lineAt(pos);
2257
+ let line = cx.lineAt(cx.pos);
2256
2258
  if (overrideIndentation && from == null)
2257
2259
  IndentedFrom.set(cx.state, line.from);
2258
2260
  return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
@@ -2287,11 +2289,11 @@ function cutTree(lang, tree, from, to, inside) {
2287
2289
  }
2288
2290
  return null;
2289
2291
  }
2290
- function findStartInFragments(lang, fragments, startPos, editorState) {
2292
+ function findStartInFragments(lang, fragments, startPos, endPos, editorState) {
2291
2293
  for (let f of fragments) {
2292
2294
  let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
2293
2295
  let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
2294
- if (found && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
2296
+ if (found && found.pos <= endPos && (tree = cutTree(lang, f.tree, startPos + f.offset, found.pos + f.offset, false)))
2295
2297
  return { state: found.state, tree };
2296
2298
  }
2297
2299
  return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: Tree.empty };
@@ -2310,7 +2312,7 @@ class Parse {
2310
2312
  this.rangeIndex = 0;
2311
2313
  this.to = ranges[ranges.length - 1].to;
2312
2314
  let context = ParseContext.get(), from = ranges[0].from;
2313
- let { state, tree } = findStartInFragments(lang, fragments, from, context === null || context === void 0 ? void 0 : context.state);
2315
+ let { state, tree } = findStartInFragments(lang, fragments, from, ranges[ranges.length - 1].to, context === null || context === void 0 ? void 0 : context.state);
2314
2316
  this.state = state;
2315
2317
  this.parsedPos = this.chunkStart = from + tree.length;
2316
2318
  for (let i = 0; i < tree.children.length; i++) {
@@ -2388,7 +2390,8 @@ class Parse {
2388
2390
  while (this.ranges[this.rangeIndex].to < this.parsedPos)
2389
2391
  this.rangeIndex++;
2390
2392
  }
2391
- emitToken(id, from, to, size, offset) {
2393
+ emitToken(id, from, to, offset) {
2394
+ let size = 4;
2392
2395
  if (this.ranges.length > 1) {
2393
2396
  offset = this.skipGapsTo(from, offset, 1);
2394
2397
  from += offset;
@@ -2397,7 +2400,11 @@ class Parse {
2397
2400
  to += offset;
2398
2401
  size += this.chunk.length - len0;
2399
2402
  }
2400
- this.chunk.push(id, from, to, size);
2403
+ let last = this.chunk.length - 4;
2404
+ if (size == 4 && last >= 0 && this.chunk[last] == id && this.chunk[last + 2] == from)
2405
+ this.chunk[last + 2] = to;
2406
+ else
2407
+ this.chunk.push(id, from, to, size);
2401
2408
  return offset;
2402
2409
  }
2403
2410
  parseLine(context) {
@@ -2410,7 +2417,7 @@ class Parse {
2410
2417
  while (!stream.eol()) {
2411
2418
  let token = readToken(streamParser.token, stream, this.state);
2412
2419
  if (token)
2413
- offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, 4, offset);
2420
+ offset = this.emitToken(this.lang.tokenTable.resolve(token), this.parsedPos + stream.start, this.parsedPos + stream.pos, offset);
2414
2421
  if (stream.start > 10000 /* C.MaxLineLength */)
2415
2422
  break;
2416
2423
  }
@@ -2527,8 +2534,11 @@ function createTokenType(extra, tagStr) {
2527
2534
  typeArray.push(type);
2528
2535
  return type.id;
2529
2536
  }
2530
- function docID(data) {
2531
- let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
2537
+ function docID(data, lang) {
2538
+ let type = NodeType.define({ id: typeArray.length, name: "Document", props: [
2539
+ languageDataProp.add(() => data),
2540
+ indentNodeProp.add(() => cx => lang.getIndent(cx))
2541
+ ], top: true });
2532
2542
  typeArray.push(type);
2533
2543
  return type;
2534
2544
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/language",
3
- "version": "6.10.2",
3
+ "version": "6.10.4",
4
4
  "description": "Language support infrastructure for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",