@codemirror/language 6.10.3 → 6.10.5

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,19 @@
1
+ ## 6.10.5 (2024-11-27)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where a `StreamLanguage` could get confused when trying to reuse existing parse data when the parsed range changed.
6
+
7
+ ## 6.10.4 (2024-11-24)
8
+
9
+ ### Bug fixes
10
+
11
+ Join adjacent tokens of the same type into a single token in .
12
+
13
+ Call stream language indent functions even when the language is used as a nested parser.
14
+
15
+ Fix a crash in `StreamParser` when a parse was resumed with different input ranges.
16
+
1
17
  ## 6.10.3 (2024-09-19)
2
18
 
3
19
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -2208,8 +2208,8 @@ class StreamLanguage extends Language {
2208
2208
  return new Parse(self, input, fragments, ranges);
2209
2209
  }
2210
2210
  };
2211
- super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
2212
- this.topNode = docID(data);
2211
+ super(data, impl, [], parser.name);
2212
+ this.topNode = docID(data, this);
2213
2213
  self = this;
2214
2214
  this.streamParser = p;
2215
2215
  this.stateAfter = new common.NodeProp({ perNode: true });
@@ -2219,20 +2219,18 @@ class StreamLanguage extends Language {
2219
2219
  Define a stream language.
2220
2220
  */
2221
2221
  static define(spec) { return new StreamLanguage(spec); }
2222
- getIndent(cx, pos) {
2223
- let tree = syntaxTree(cx.state), at = tree.resolve(pos);
2224
- while (at && at.type != this.topNode)
2225
- at = at.parent;
2226
- if (!at)
2227
- return null;
2222
+ /**
2223
+ @internal
2224
+ */
2225
+ getIndent(cx) {
2228
2226
  let from = undefined;
2229
2227
  let { overrideIndentation } = cx.options;
2230
2228
  if (overrideIndentation) {
2231
2229
  from = IndentedFrom.get(cx.state);
2232
- if (from != null && from < pos - 1e4)
2230
+ if (from != null && from < cx.pos - 1e4)
2233
2231
  from = undefined;
2234
2232
  }
2235
- 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;
2236
2234
  if (start) {
2237
2235
  state = start.state;
2238
2236
  statePos = start.pos + 1;
@@ -2241,10 +2239,10 @@ class StreamLanguage extends Language {
2241
2239
  state = this.streamParser.startState(cx.unit);
2242
2240
  statePos = 0;
2243
2241
  }
2244
- if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
2242
+ if (cx.pos - statePos > 10000 /* C.MaxIndentScanDist */)
2245
2243
  return null;
2246
- while (statePos < pos) {
2247
- 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);
2248
2246
  if (line.length) {
2249
2247
  let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
2250
2248
  let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
@@ -2254,11 +2252,11 @@ class StreamLanguage extends Language {
2254
2252
  else {
2255
2253
  this.streamParser.blankLine(state, cx.unit);
2256
2254
  }
2257
- if (end == pos)
2255
+ if (end == cx.pos)
2258
2256
  break;
2259
2257
  statePos = line.to + 1;
2260
2258
  }
2261
- let line = cx.lineAt(pos);
2259
+ let line = cx.lineAt(cx.pos);
2262
2260
  if (overrideIndentation && from == null)
2263
2261
  IndentedFrom.set(cx.state, line.from);
2264
2262
  return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
@@ -2280,7 +2278,7 @@ function findState(lang, tree, off, startPos, before) {
2280
2278
  function cutTree(lang, tree, from, to, inside) {
2281
2279
  if (inside && from <= 0 && to >= tree.length)
2282
2280
  return tree;
2283
- if (!inside && tree.type == lang.topNode)
2281
+ if (!inside && from == 0 && tree.type == lang.topNode)
2284
2282
  inside = true;
2285
2283
  for (let i = tree.children.length - 1; i >= 0; i--) {
2286
2284
  let pos = tree.positions[i], child = tree.children[i], inner;
@@ -2293,11 +2291,11 @@ function cutTree(lang, tree, from, to, inside) {
2293
2291
  }
2294
2292
  return null;
2295
2293
  }
2296
- function findStartInFragments(lang, fragments, startPos, editorState) {
2294
+ function findStartInFragments(lang, fragments, startPos, endPos, editorState) {
2297
2295
  for (let f of fragments) {
2298
2296
  let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
2299
2297
  let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
2300
- 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)))
2301
2299
  return { state: found.state, tree };
2302
2300
  }
2303
2301
  return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: common.Tree.empty };
@@ -2316,7 +2314,7 @@ class Parse {
2316
2314
  this.rangeIndex = 0;
2317
2315
  this.to = ranges[ranges.length - 1].to;
2318
2316
  let context = ParseContext.get(), from = ranges[0].from;
2319
- 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);
2320
2318
  this.state = state;
2321
2319
  this.parsedPos = this.chunkStart = from + tree.length;
2322
2320
  for (let i = 0; i < tree.children.length; i++) {
@@ -2394,7 +2392,8 @@ class Parse {
2394
2392
  while (this.ranges[this.rangeIndex].to < this.parsedPos)
2395
2393
  this.rangeIndex++;
2396
2394
  }
2397
- emitToken(id, from, to, size, offset) {
2395
+ emitToken(id, from, to, offset) {
2396
+ let size = 4;
2398
2397
  if (this.ranges.length > 1) {
2399
2398
  offset = this.skipGapsTo(from, offset, 1);
2400
2399
  from += offset;
@@ -2403,7 +2402,11 @@ class Parse {
2403
2402
  to += offset;
2404
2403
  size += this.chunk.length - len0;
2405
2404
  }
2406
- 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);
2407
2410
  return offset;
2408
2411
  }
2409
2412
  parseLine(context) {
@@ -2416,7 +2419,7 @@ class Parse {
2416
2419
  while (!stream.eol()) {
2417
2420
  let token = readToken(streamParser.token, stream, this.state);
2418
2421
  if (token)
2419
- 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);
2420
2423
  if (stream.start > 10000 /* C.MaxLineLength */)
2421
2424
  break;
2422
2425
  }
@@ -2533,8 +2536,11 @@ function createTokenType(extra, tagStr) {
2533
2536
  typeArray.push(type);
2534
2537
  return type.id;
2535
2538
  }
2536
- function docID(data) {
2537
- 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 });
2538
2544
  typeArray.push(type);
2539
2545
  return type;
2540
2546
  }
package/dist/index.d.cts CHANGED
@@ -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
@@ -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
@@ -2206,8 +2206,8 @@ class StreamLanguage extends Language {
2206
2206
  return new Parse(self, input, fragments, ranges);
2207
2207
  }
2208
2208
  };
2209
- super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name);
2210
- this.topNode = docID(data);
2209
+ super(data, impl, [], parser.name);
2210
+ this.topNode = docID(data, this);
2211
2211
  self = this;
2212
2212
  this.streamParser = p;
2213
2213
  this.stateAfter = new NodeProp({ perNode: true });
@@ -2217,20 +2217,18 @@ class StreamLanguage extends Language {
2217
2217
  Define a stream language.
2218
2218
  */
2219
2219
  static define(spec) { return new StreamLanguage(spec); }
2220
- getIndent(cx, pos) {
2221
- let tree = syntaxTree(cx.state), at = tree.resolve(pos);
2222
- while (at && at.type != this.topNode)
2223
- at = at.parent;
2224
- if (!at)
2225
- return null;
2220
+ /**
2221
+ @internal
2222
+ */
2223
+ getIndent(cx) {
2226
2224
  let from = undefined;
2227
2225
  let { overrideIndentation } = cx.options;
2228
2226
  if (overrideIndentation) {
2229
2227
  from = IndentedFrom.get(cx.state);
2230
- if (from != null && from < pos - 1e4)
2228
+ if (from != null && from < cx.pos - 1e4)
2231
2229
  from = undefined;
2232
2230
  }
2233
- 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;
2234
2232
  if (start) {
2235
2233
  state = start.state;
2236
2234
  statePos = start.pos + 1;
@@ -2239,10 +2237,10 @@ class StreamLanguage extends Language {
2239
2237
  state = this.streamParser.startState(cx.unit);
2240
2238
  statePos = 0;
2241
2239
  }
2242
- if (pos - statePos > 10000 /* C.MaxIndentScanDist */)
2240
+ if (cx.pos - statePos > 10000 /* C.MaxIndentScanDist */)
2243
2241
  return null;
2244
- while (statePos < pos) {
2245
- 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);
2246
2244
  if (line.length) {
2247
2245
  let indentation = overrideIndentation ? overrideIndentation(line.from) : -1;
2248
2246
  let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation);
@@ -2252,11 +2250,11 @@ class StreamLanguage extends Language {
2252
2250
  else {
2253
2251
  this.streamParser.blankLine(state, cx.unit);
2254
2252
  }
2255
- if (end == pos)
2253
+ if (end == cx.pos)
2256
2254
  break;
2257
2255
  statePos = line.to + 1;
2258
2256
  }
2259
- let line = cx.lineAt(pos);
2257
+ let line = cx.lineAt(cx.pos);
2260
2258
  if (overrideIndentation && from == null)
2261
2259
  IndentedFrom.set(cx.state, line.from);
2262
2260
  return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)[1], cx);
@@ -2278,7 +2276,7 @@ function findState(lang, tree, off, startPos, before) {
2278
2276
  function cutTree(lang, tree, from, to, inside) {
2279
2277
  if (inside && from <= 0 && to >= tree.length)
2280
2278
  return tree;
2281
- if (!inside && tree.type == lang.topNode)
2279
+ if (!inside && from == 0 && tree.type == lang.topNode)
2282
2280
  inside = true;
2283
2281
  for (let i = tree.children.length - 1; i >= 0; i--) {
2284
2282
  let pos = tree.positions[i], child = tree.children[i], inner;
@@ -2291,11 +2289,11 @@ function cutTree(lang, tree, from, to, inside) {
2291
2289
  }
2292
2290
  return null;
2293
2291
  }
2294
- function findStartInFragments(lang, fragments, startPos, editorState) {
2292
+ function findStartInFragments(lang, fragments, startPos, endPos, editorState) {
2295
2293
  for (let f of fragments) {
2296
2294
  let from = f.from + (f.openStart ? 25 : 0), to = f.to - (f.openEnd ? 25 : 0);
2297
2295
  let found = from <= startPos && to > startPos && findState(lang, f.tree, 0 - f.offset, startPos, to), tree;
2298
- 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)))
2299
2297
  return { state: found.state, tree };
2300
2298
  }
2301
2299
  return { state: lang.streamParser.startState(editorState ? getIndentUnit(editorState) : 4), tree: Tree.empty };
@@ -2314,7 +2312,7 @@ class Parse {
2314
2312
  this.rangeIndex = 0;
2315
2313
  this.to = ranges[ranges.length - 1].to;
2316
2314
  let context = ParseContext.get(), from = ranges[0].from;
2317
- 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);
2318
2316
  this.state = state;
2319
2317
  this.parsedPos = this.chunkStart = from + tree.length;
2320
2318
  for (let i = 0; i < tree.children.length; i++) {
@@ -2392,7 +2390,8 @@ class Parse {
2392
2390
  while (this.ranges[this.rangeIndex].to < this.parsedPos)
2393
2391
  this.rangeIndex++;
2394
2392
  }
2395
- emitToken(id, from, to, size, offset) {
2393
+ emitToken(id, from, to, offset) {
2394
+ let size = 4;
2396
2395
  if (this.ranges.length > 1) {
2397
2396
  offset = this.skipGapsTo(from, offset, 1);
2398
2397
  from += offset;
@@ -2401,7 +2400,11 @@ class Parse {
2401
2400
  to += offset;
2402
2401
  size += this.chunk.length - len0;
2403
2402
  }
2404
- 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);
2405
2408
  return offset;
2406
2409
  }
2407
2410
  parseLine(context) {
@@ -2414,7 +2417,7 @@ class Parse {
2414
2417
  while (!stream.eol()) {
2415
2418
  let token = readToken(streamParser.token, stream, this.state);
2416
2419
  if (token)
2417
- 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);
2418
2421
  if (stream.start > 10000 /* C.MaxLineLength */)
2419
2422
  break;
2420
2423
  }
@@ -2531,8 +2534,11 @@ function createTokenType(extra, tagStr) {
2531
2534
  typeArray.push(type);
2532
2535
  return type.id;
2533
2536
  }
2534
- function docID(data) {
2535
- 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 });
2536
2542
  typeArray.push(type);
2537
2543
  return type;
2538
2544
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/language",
3
- "version": "6.10.3",
3
+ "version": "6.10.5",
4
4
  "description": "Language support infrastructure for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",