@codemirror/language 6.5.0 → 6.6.0

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,9 @@
1
+ ## 6.6.0 (2023-02-13)
2
+
3
+ ### New features
4
+
5
+ Syntax-driven language data queries now support sublanguages, which make it possible to return different data for specific parts of the tree produced by a single language.
6
+
1
7
  ## 6.5.0 (2023-02-07)
2
8
 
3
9
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -28,6 +28,11 @@ function defineLanguageFacet(baseData) {
28
28
  });
29
29
  }
30
30
  /**
31
+ Syntax node prop used to register sublangauges. Should be added to
32
+ the top level node type for the language.
33
+ */
34
+ const sublanguageProp = new common.NodeProp();
35
+ /**
31
36
  A language object manages parsing and per-language
32
37
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
33
38
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -64,14 +69,28 @@ class Language {
64
69
  this.parser = parser;
65
70
  this.extension = [
66
71
  language.of(this),
67
- state.EditorState.languageData.of((state, pos, side) => state.facet(languageDataFacetAt(state, pos, side)))
72
+ state.EditorState.languageData.of((state, pos, side) => {
73
+ let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);
74
+ if (!data)
75
+ return [];
76
+ let base = state.facet(data), sub = top.type.prop(sublanguageProp);
77
+ if (sub) {
78
+ let innerNode = top.resolve(pos - top.from, side);
79
+ for (let sublang of sub)
80
+ if (sublang.test(innerNode, state)) {
81
+ let data = state.facet(sublang.facet);
82
+ return sublang.type == "replace" ? data : data.concat(base);
83
+ }
84
+ }
85
+ return base;
86
+ })
68
87
  ].concat(extraExtensions);
69
88
  }
70
89
  /**
71
90
  Query whether this language is active at the given position.
72
91
  */
73
92
  isActiveAt(state, pos, side = -1) {
74
- return languageDataFacetAt(state, pos, side) == this.data;
93
+ return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
75
94
  }
76
95
  /**
77
96
  Find the document regions that were parsed using this language.
@@ -126,16 +145,14 @@ class Language {
126
145
  @internal
127
146
  */
128
147
  Language.setState = state.StateEffect.define();
129
- function languageDataFacetAt(state, pos, side) {
130
- let topLang = state.facet(language);
131
- if (!topLang)
132
- return null;
133
- let facet = topLang.data;
134
- if (topLang.allowsNesting) {
135
- for (let node = syntaxTree(state).topNode; node; node = node.enter(pos, side, common.IterMode.ExcludeBuffers))
136
- facet = node.type.prop(languageDataProp) || facet;
148
+ function topNodeAt(state, pos, side) {
149
+ let topLang = state.facet(language), tree = syntaxTree(state).topNode;
150
+ if (!topLang || topLang.allowsNesting) {
151
+ for (let node = tree; node; node = node.enter(pos, side, common.IterMode.ExcludeBuffers))
152
+ if (node.type.isTop)
153
+ tree = node;
137
154
  }
138
- return facet;
155
+ return tree;
139
156
  }
140
157
  /**
141
158
  A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer
@@ -2506,6 +2523,7 @@ exports.indentUnit = indentUnit;
2506
2523
  exports.language = language;
2507
2524
  exports.languageDataProp = languageDataProp;
2508
2525
  exports.matchBrackets = matchBrackets;
2526
+ exports.sublanguageProp = sublanguageProp;
2509
2527
  exports.syntaxHighlighting = syntaxHighlighting;
2510
2528
  exports.syntaxParserRunning = syntaxParserRunning;
2511
2529
  exports.syntaxTree = syntaxTree;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { NodeProp, Parser, Tree, TreeFragment, SyntaxNode, NodeType } from '@lezer/common';
1
+ import { NodeProp, SyntaxNode, Parser, Tree, TreeFragment, NodeType } from '@lezer/common';
2
2
  import { LRParser, ParserConfig } from '@lezer/lr';
3
3
  import * as _codemirror_state from '@codemirror/state';
4
- import { Facet, Extension, EditorState, StateField, Range } from '@codemirror/state';
4
+ import { Facet, EditorState, Extension, StateField, Range } from '@codemirror/state';
5
5
  import { EditorView, DecorationSet, Command, KeyBinding, ViewUpdate, BlockInfo, Decoration } from '@codemirror/view';
6
6
  import { Highlighter, Tag } from '@lezer/highlight';
7
7
  import { StyleModule, StyleSpec } from 'style-mod';
@@ -31,6 +31,44 @@ declare function defineLanguageFacet(baseData?: {
31
31
  [name: string]: any;
32
32
  }[]>;
33
33
  /**
34
+ Some languages need to return different [language
35
+ data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) for some parts of their
36
+ tree. Sublanguages, registered by adding a [node
37
+ prop](https://codemirror.net/6/docs/ref/#language.sublanguageProp) to the language's top syntax
38
+ node, provide a mechanism to do this.
39
+
40
+ (Note that when using nested parsing, where nested syntax is
41
+ parsed by a different parser and has its own top node type, you
42
+ don't need a sublanguage.)
43
+ */
44
+ interface Sublanguage {
45
+ /**
46
+ Determines whether the data provided by this sublanguage should
47
+ completely replace the regular data or be added to it (with
48
+ higher-precedence). The default is `"extend"`.
49
+ */
50
+ type?: "replace" | "extend";
51
+ /**
52
+ A predicate that returns whether the node at the queried
53
+ position is part of the sublanguage.
54
+ */
55
+ test: (node: SyntaxNode, state: EditorState) => boolean;
56
+ /**
57
+ The language data facet that holds the sublanguage's data.
58
+ You'll want to use
59
+ [`defineLanguageFacet`](https://codemirror.net/6/docs/ref/#language.defineLanguageFacet) to create
60
+ this.
61
+ */
62
+ facet: Facet<{
63
+ [name: string]: any;
64
+ }>;
65
+ }
66
+ /**
67
+ Syntax node prop used to register sublangauges. Should be added to
68
+ the top level node type for the language.
69
+ */
70
+ declare const sublanguageProp: NodeProp<Sublanguage[]>;
71
+ /**
34
72
  A language object manages parsing and per-language
35
73
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
36
74
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -1119,4 +1157,4 @@ declare class StreamLanguage<State> extends Language {
1119
1157
  get allowsNesting(): boolean;
1120
1158
  }
1121
1159
 
1122
- export { Config, HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, MatchResult, ParseContext, StreamLanguage, StreamParser, StringStream, TagStyle, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
1160
+ export { Config, HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, MatchResult, ParseContext, StreamLanguage, StreamParser, StringStream, Sublanguage, TagStyle, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, sublanguageProp, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
package/dist/index.js CHANGED
@@ -24,6 +24,11 @@ function defineLanguageFacet(baseData) {
24
24
  });
25
25
  }
26
26
  /**
27
+ Syntax node prop used to register sublangauges. Should be added to
28
+ the top level node type for the language.
29
+ */
30
+ const sublanguageProp = /*@__PURE__*/new NodeProp();
31
+ /**
27
32
  A language object manages parsing and per-language
28
33
  [metadata](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt). Parse data is
29
34
  managed as a [Lezer](https://lezer.codemirror.net) tree. The class
@@ -60,14 +65,28 @@ class Language {
60
65
  this.parser = parser;
61
66
  this.extension = [
62
67
  language.of(this),
63
- EditorState.languageData.of((state, pos, side) => state.facet(languageDataFacetAt(state, pos, side)))
68
+ EditorState.languageData.of((state, pos, side) => {
69
+ let top = topNodeAt(state, pos, side), data = top.type.prop(languageDataProp);
70
+ if (!data)
71
+ return [];
72
+ let base = state.facet(data), sub = top.type.prop(sublanguageProp);
73
+ if (sub) {
74
+ let innerNode = top.resolve(pos - top.from, side);
75
+ for (let sublang of sub)
76
+ if (sublang.test(innerNode, state)) {
77
+ let data = state.facet(sublang.facet);
78
+ return sublang.type == "replace" ? data : data.concat(base);
79
+ }
80
+ }
81
+ return base;
82
+ })
64
83
  ].concat(extraExtensions);
65
84
  }
66
85
  /**
67
86
  Query whether this language is active at the given position.
68
87
  */
69
88
  isActiveAt(state, pos, side = -1) {
70
- return languageDataFacetAt(state, pos, side) == this.data;
89
+ return topNodeAt(state, pos, side).type.prop(languageDataProp) == this.data;
71
90
  }
72
91
  /**
73
92
  Find the document regions that were parsed using this language.
@@ -122,16 +141,14 @@ class Language {
122
141
  @internal
123
142
  */
124
143
  Language.setState = /*@__PURE__*/StateEffect.define();
125
- function languageDataFacetAt(state, pos, side) {
126
- let topLang = state.facet(language);
127
- if (!topLang)
128
- return null;
129
- let facet = topLang.data;
130
- if (topLang.allowsNesting) {
131
- for (let node = syntaxTree(state).topNode; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
132
- facet = node.type.prop(languageDataProp) || facet;
144
+ function topNodeAt(state, pos, side) {
145
+ let topLang = state.facet(language), tree = syntaxTree(state).topNode;
146
+ if (!topLang || topLang.allowsNesting) {
147
+ for (let node = tree; node; node = node.enter(pos, side, IterMode.ExcludeBuffers))
148
+ if (node.type.isTop)
149
+ tree = node;
133
150
  }
134
- return facet;
151
+ return tree;
135
152
  }
136
153
  /**
137
154
  A subclass of [`Language`](https://codemirror.net/6/docs/ref/#language.Language) for use with Lezer
@@ -2459,4 +2476,4 @@ function docID(data) {
2459
2476
  return type;
2460
2477
  }
2461
2478
 
2462
- export { HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, ParseContext, StreamLanguage, StringStream, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
2479
+ export { HighlightStyle, IndentContext, LRLanguage, Language, LanguageDescription, LanguageSupport, ParseContext, StreamLanguage, StringStream, TreeIndentContext, bracketMatching, bracketMatchingHandle, codeFolding, continuedIndent, defaultHighlightStyle, defineLanguageFacet, delimitedIndent, ensureSyntaxTree, flatIndent, foldAll, foldCode, foldEffect, foldGutter, foldInside, foldKeymap, foldNodeProp, foldService, foldState, foldable, foldedRanges, forceParsing, getIndentUnit, getIndentation, highlightingFor, indentNodeProp, indentOnInput, indentRange, indentService, indentString, indentUnit, language, languageDataProp, matchBrackets, sublanguageProp, syntaxHighlighting, syntaxParserRunning, syntaxTree, syntaxTreeAvailable, toggleFold, unfoldAll, unfoldCode, unfoldEffect };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/language",
3
- "version": "6.5.0",
3
+ "version": "6.6.0",
4
4
  "description": "Language support infrastructure for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",