lang-feel 2.1.1 → 2.3.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.
@@ -8,6 +8,8 @@ export declare function contextualKeyword(options: {
8
8
  }): CompletionSource;
9
9
  export declare const keywordCompletions: CompletionSource[];
10
10
  export declare const dontComplete: string[];
11
+ export declare const doComplete: string[];
12
+ export declare function ifExpression(completionSource: CompletionSource): CompletionSource;
11
13
  export declare function snippetCompletion(snippets: readonly Completion[]): CompletionSource;
12
14
  export declare function matchLeft(node: SyntaxNode, position: number, nodes: (string | undefined)[]): SyntaxNode | null;
13
15
  export declare function matchRight(node: SyntaxNode, position: number, nodes: (string | undefined)[]): SyntaxNode | null;
package/dist/feel.d.ts CHANGED
@@ -21,6 +21,7 @@ export declare const expressionLanguage: LRLanguage;
21
21
  */
22
22
  export declare function feel(config?: {
23
23
  dialect?: 'expression' | 'unaryTests';
24
+ parserDialect?: string;
24
25
  completions?: CompletionSource[];
25
26
  context?: Record<string, any>;
26
27
  }): LanguageSupport;
package/dist/index.cjs CHANGED
@@ -29,6 +29,18 @@ const snippets = [autocomplete.snippetCompletion('function(${params}) ${body}',
29
29
  label: 'context',
30
30
  detail: 'block',
31
31
  type: 'keyword'
32
+ }), autocomplete.snippetCompletion('null', {
33
+ label: 'null',
34
+ detail: 'literal',
35
+ type: 'keyword'
36
+ }), autocomplete.snippetCompletion('true', {
37
+ label: 'true',
38
+ detail: 'literal',
39
+ type: 'keyword'
40
+ }), autocomplete.snippetCompletion('false', {
41
+ label: 'false',
42
+ detail: 'literal',
43
+ type: 'keyword'
32
44
  })];
33
45
 
34
46
  function contextualKeyword(options) {
@@ -69,9 +81,27 @@ const keywordCompletions = [contextualKeyword({
69
81
  after: 'InExpressions',
70
82
  keyword: 'return'
71
83
  })];
72
- const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment', 'PathExpression'];
84
+ const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment', 'PathExpression', 'Context', 'Key', 'ParameterName'];
85
+ const doComplete = ['Expr', 'ContextEntry'];
86
+ function ifExpression(completionSource) {
87
+ const allNodes = [...dontComplete, ...doComplete];
88
+ return context => {
89
+ const {
90
+ state,
91
+ pos
92
+ } = context;
93
+ const match = matchUp(language.syntaxTree(state).resolveInner(pos, -1), allNodes);
94
+ if (match) {
95
+ const [_, name] = match;
96
+ if (dontComplete.includes(name)) {
97
+ return null;
98
+ }
99
+ }
100
+ return completionSource(context);
101
+ };
102
+ }
73
103
  function snippetCompletion(snippets) {
74
- return autocomplete.ifNotIn(dontComplete, autocomplete.completeFromList(snippets.map(s => ({
104
+ return ifExpression(autocomplete.completeFromList(snippets.map(s => ({
75
105
  ...s,
76
106
  type: 'text'
77
107
  }))));
@@ -102,10 +132,12 @@ function matchUp(node, nodeNames) {
102
132
  nodeNames = [nodeNames];
103
133
  }
104
134
  for (; node; node = node.parent) {
105
- if (nodeNames.includes(node.name)) {
106
- return node;
135
+ const nodeType = node.type;
136
+ const matchedName = nodeNames.find(name => name && nodeType.is(name));
137
+ if (matchedName) {
138
+ return [node, matchedName];
107
139
  }
108
- if (node.type.isTop) {
140
+ if (nodeType.isTop) {
109
141
  break;
110
142
  }
111
143
  }
@@ -123,10 +155,11 @@ function ifInside(options, source) {
123
155
  state,
124
156
  pos
125
157
  } = context;
126
- const node = matchUp(language.syntaxTree(state).resolveInner(pos, -1), nodes);
127
- if (!node) {
158
+ const match = matchUp(language.syntaxTree(state).resolveInner(pos, -1), nodes);
159
+ if (!match) {
128
160
  return null;
129
161
  }
162
+ const [node] = match;
130
163
  if (matchLeft(node, pos, [keyword, before])) {
131
164
  return null;
132
165
  }
@@ -206,9 +239,12 @@ const expressionLanguage = feelLanguage.configure({
206
239
  * Includes [snippet](#lang-feel.snippets)
207
240
  */
208
241
  function feel(config = {}) {
209
- const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
210
- const contextualLang = lang.configure({
211
- contextTracker: lezerFeel.trackVariables(config.context)
242
+ const language$1 = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
243
+ const dialect = config.parserDialect;
244
+ const contextTracker = lezerFeel.trackVariables(config.context);
245
+ const contextualLang = language$1.configure({
246
+ contextTracker,
247
+ dialect
212
248
  });
213
249
  const completions = config.completions || [snippetCompletion(snippets), keywordCompletions].flat();
214
250
  return new language.LanguageSupport(contextualLang, [...completions.map(autocomplete => contextualLang.data.of({
@@ -217,10 +253,12 @@ function feel(config = {}) {
217
253
  }
218
254
 
219
255
  exports.contextualKeyword = contextualKeyword;
256
+ exports.doComplete = doComplete;
220
257
  exports.dontComplete = dontComplete;
221
258
  exports.expressionLanguage = expressionLanguage;
222
259
  exports.feel = feel;
223
260
  exports.feelLanguage = feelLanguage;
261
+ exports.ifExpression = ifExpression;
224
262
  exports.ifInside = ifInside;
225
263
  exports.keywordCompletions = keywordCompletions;
226
264
  exports.matchChildren = matchChildren;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/snippets.ts","../src/completion.ts","../src/feel.ts"],"sourcesContent":["import { Completion, snippetCompletion } from '@codemirror/autocomplete';\n\n/**\n * A collection of FEEL-related [snippets](#autocomplete.snippet).\n */\nexport const snippets: readonly Completion[] = [\n snippetCompletion('function(${params}) ${body}', {\n label: 'function',\n detail: 'definition',\n type: 'keyword'\n }),\n snippetCompletion('for ${var} in ${collection} return ${value}', {\n label: 'for',\n detail: 'expression',\n type: 'keyword'\n }),\n snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {\n label: 'every',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {\n label: 'some',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('if ${condition} then ${value} else ${other value}', {\n label: 'if',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('{ ${key}: ${value} }', {\n label: 'context',\n detail: 'block',\n type: 'keyword'\n })\n];\n","import { syntaxTree } from '@codemirror/language';\nimport { SyntaxNode } from '@lezer/common';\n\nimport {\n CompletionSource,\n Completion,\n completeFromList,\n ifNotIn\n} from '@codemirror/autocomplete';\n\n\nexport function contextualKeyword(options: {\n before?: string,\n after?: string,\n context: string,\n keyword: string\n}) : CompletionSource {\n\n const {\n context: nodes,\n after,\n before,\n keyword\n } = options;\n\n return ifInside({ nodes, before, after, keyword }, completeFromList([\n { label: keyword, type: 'keyword', boost: 10 }\n ]));\n}\n\nexport const keywordCompletions = [\n contextualKeyword({\n context: 'InExpression',\n keyword: 'in'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'then',\n after: 'if',\n before: 'else'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'else',\n after: 'then'\n }),\n contextualKeyword({\n context: 'QuantifiedExpression',\n keyword: 'satisfies'\n }),\n contextualKeyword({\n context: 'ForExpression',\n after: 'InExpressions',\n keyword: 'return'\n })\n];\n\nexport const dontComplete = [\n 'StringLiteral', 'Identifier',\n 'LineComment', 'BlockComment',\n 'PathExpression'\n];\n\nexport function snippetCompletion(snippets: readonly Completion[]) : CompletionSource {\n return ifNotIn(\n dontComplete, completeFromList(snippets.map(s => ({ ...s, type: 'text' })))\n );\n}\n\nexport function matchLeft(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, -1);\n}\n\nexport function matchRight(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, 1);\n}\n\nexport function matchChildren(node: SyntaxNode, position: number, nodes: (string|undefined)[], direction: 1 | -1) : SyntaxNode | null {\n\n let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);\n\n while (child) {\n if (nodes.includes(child.name)) {\n return child;\n }\n\n if (child.type.isError && child.firstChild) {\n if (nodes.includes(child.firstChild.name)) {\n return child.firstChild;\n }\n }\n\n child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];\n }\n\n return null;\n}\n\nfunction matchUp(node: SyntaxNode, nodeNames: string | undefined | (string | undefined)[]) {\n\n if (!Array.isArray(nodeNames)) {\n nodeNames = [ nodeNames ];\n }\n\n for (; node; node = node.parent!) {\n if (nodeNames.includes(node.name)) {\n return node;\n }\n\n if (node.type.isTop) {\n break;\n }\n }\n\n return null;\n}\n\nexport function ifInside(options: {\n nodes: string | string[],\n keyword: string,\n before?: string,\n after?: string\n}, source: CompletionSource): CompletionSource {\n\n const {\n nodes,\n before,\n after,\n keyword\n } = options;\n\n return (context) => {\n\n const { state, pos } = context;\n\n const node = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);\n\n if (!node) {\n return null;\n }\n\n if (matchLeft(node, pos, [ keyword, before ])) {\n return null;\n }\n\n if (matchRight(node, pos, [ keyword, after ])) {\n return null;\n }\n\n if (after && !matchLeft(node, pos, [ after ])) {\n return null;\n }\n\n return source(context);\n };\n}","import {\n parser,\n trackVariables\n} from 'lezer-feel';\n\nimport {\n LRLanguage,\n LanguageSupport,\n delimitedIndent,\n continuedIndent,\n indentNodeProp,\n foldNodeProp,\n foldInside\n} from '@codemirror/language';\n\nimport {\n snippets\n} from './snippets';\n\nimport {\n keywordCompletions,\n snippetCompletion\n} from './completion';\n\nimport {\n CompletionSource\n} from '@codemirror/autocomplete';\n\n\n/**\n * A FEEL language provider based on the\n * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),\n * extended with highlighting and indentation information.\n */\nexport const feelLanguage = LRLanguage.define({\n parser: parser.configure({\n props: [\n indentNodeProp.add({\n 'Context': delimitedIndent({\n closing: '}'\n }),\n 'List FilterExpression': delimitedIndent({\n closing: ']'\n }),\n 'ParenthesizedExpression FunctionInvocation': continuedIndent({\n except: /^\\s*\\)/\n }),\n 'ForExpression QuantifiedExpression IfExpression': continuedIndent({\n except: /^\\s*(then|else|return|satisfies)\\b/\n }),\n 'FunctionDefinition': continuedIndent({\n except: /^\\s*(\\(|\\))/\n })\n }),\n foldNodeProp.add({\n Context: foldInside,\n List: foldInside,\n ParenthesizedExpression: foldInside,\n FunctionDefinition(node) {\n const last = node.getChild(')');\n\n if (!last) return null;\n\n return {\n from: last.to,\n to: node.to\n };\n }\n })\n ]\n }),\n languageData: {\n indentOnInput: /^\\s*(\\)|\\}|\\]|then|else|return|satisfies)$/,\n commentTokens: {\n line: '//',\n block: {\n open: '/*',\n close: '*/'\n }\n }\n }\n});\n\n/**\n * A language provider for FEEL Unary Tests\n */\nexport const unaryTestsLanguage = feelLanguage.configure({\n top: 'UnaryTests',\n}, 'FEEL unary tests');\n\n/**\n * Language provider for FEEL Expression\n */\nexport const expressionLanguage = feelLanguage.configure({\n top: 'Expression'\n}, 'FEEL expression');\n\n\n\n/**\n * Feel language support for CodeMirror.\n *\n * Includes [snippet](#lang-feel.snippets)\n */\nexport function feel(config: {\n dialect?: 'expression' | 'unaryTests',\n completions?: CompletionSource[],\n context?: Record<string, any>\n} = {}) {\n const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;\n\n const contextualLang = lang.configure({\n contextTracker: trackVariables(config.context)\n });\n\n const completions = config.completions || [\n snippetCompletion(snippets),\n keywordCompletions,\n ].flat();\n\n return new LanguageSupport(contextualLang, [\n ...(\n completions.map(autocomplete => contextualLang.data.of({\n autocomplete\n }))\n )\n ]);\n\n}"],"names":["snippets","snippetCompletion","label","detail","type","contextualKeyword","options","context","nodes","after","before","keyword","ifInside","completeFromList","boost","keywordCompletions","dontComplete","ifNotIn","map","s","matchLeft","node","position","matchChildren","matchRight","direction","child","includes","name","isError","firstChild","matchUp","nodeNames","Array","isArray","parent","isTop","source","state","pos","syntaxTree","resolveInner","feelLanguage","LRLanguage","define","parser","configure","props","indentNodeProp","add","delimitedIndent","closing","continuedIndent","except","foldNodeProp","Context","foldInside","List","ParenthesizedExpression","FunctionDefinition","last","getChild","from","to","languageData","indentOnInput","commentTokens","line","block","open","close","unaryTestsLanguage","top","expressionLanguage","feel","config","lang","dialect","contextualLang","contextTracker","trackVariables","completions","flat","LanguageSupport","autocomplete","data","of"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/snippets.ts","../src/completion.ts","../src/feel.ts"],"sourcesContent":["import { Completion, snippetCompletion } from '@codemirror/autocomplete';\n\n/**\n * A collection of FEEL-related [snippets](#autocomplete.snippet).\n */\nexport const snippets: readonly Completion[] = [\n snippetCompletion('function(${params}) ${body}', {\n label: 'function',\n detail: 'definition',\n type: 'keyword'\n }),\n snippetCompletion('for ${var} in ${collection} return ${value}', {\n label: 'for',\n detail: 'expression',\n type: 'keyword'\n }),\n snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {\n label: 'every',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {\n label: 'some',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('if ${condition} then ${value} else ${other value}', {\n label: 'if',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('{ ${key}: ${value} }', {\n label: 'context',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('null', {\n label: 'null',\n detail: 'literal',\n type: 'keyword'\n }),\n snippetCompletion('true', {\n label: 'true',\n detail: 'literal',\n type: 'keyword'\n }),\n snippetCompletion('false', {\n label: 'false',\n detail: 'literal',\n type: 'keyword'\n })\n];\n","import { syntaxTree } from '@codemirror/language';\nimport { SyntaxNode } from '@lezer/common';\n\nimport {\n CompletionSource,\n Completion,\n completeFromList,\n CompletionContext\n} from '@codemirror/autocomplete';\n\n\nexport function contextualKeyword(options: {\n before?: string,\n after?: string,\n context: string,\n keyword: string\n}) : CompletionSource {\n\n const {\n context: nodes,\n after,\n before,\n keyword\n } = options;\n\n return ifInside({ nodes, before, after, keyword }, completeFromList([\n { label: keyword, type: 'keyword', boost: 10 }\n ]));\n}\n\nexport const keywordCompletions = [\n contextualKeyword({\n context: 'InExpression',\n keyword: 'in'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'then',\n after: 'if',\n before: 'else'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'else',\n after: 'then'\n }),\n contextualKeyword({\n context: 'QuantifiedExpression',\n keyword: 'satisfies'\n }),\n contextualKeyword({\n context: 'ForExpression',\n after: 'InExpressions',\n keyword: 'return'\n })\n];\n\nexport const dontComplete = [\n 'StringLiteral', 'Identifier',\n 'LineComment', 'BlockComment',\n 'PathExpression', 'Context',\n 'Key', 'ParameterName'\n];\n\nexport const doComplete = [\n 'Expr',\n 'ContextEntry'\n];\n\nexport function ifExpression(completionSource: CompletionSource) : CompletionSource {\n\n const allNodes = [ ...dontComplete, ...doComplete ];\n\n return (context: CompletionContext) => {\n\n const { state, pos } = context;\n\n const match = matchUp(syntaxTree(state).resolveInner(pos, -1), allNodes);\n\n if (match) {\n\n const [ _, name ] = match;\n\n if (dontComplete.includes(name)) {\n return null;\n }\n }\n\n return completionSource(context);\n };\n}\n\nexport function snippetCompletion(snippets: readonly Completion[]) : CompletionSource {\n return ifExpression(\n completeFromList(snippets.map(s => ({ ...s, type: 'text' })))\n );\n}\n\nexport function matchLeft(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, -1);\n}\n\nexport function matchRight(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, 1);\n}\n\nexport function matchChildren(node: SyntaxNode, position: number, nodes: (string|undefined)[], direction: 1 | -1) : SyntaxNode | null {\n\n let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);\n\n while (child) {\n if (nodes.includes(child.name)) {\n return child;\n }\n\n if (child.type.isError && child.firstChild) {\n if (nodes.includes(child.firstChild.name)) {\n return child.firstChild;\n }\n }\n\n child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];\n }\n\n return null;\n}\n\nfunction matchUp(node: SyntaxNode, nodeNames: string | string[]) : [ SyntaxNode, string ] | null {\n\n if (!Array.isArray(nodeNames)) {\n nodeNames = [ nodeNames ];\n }\n\n for (; node; node = node.parent!) {\n\n const nodeType = node.type;\n\n const matchedName = nodeNames.find(name => name && nodeType.is(name));\n\n if (matchedName) {\n return [ node, matchedName ];\n }\n\n if (nodeType.isTop) {\n break;\n }\n }\n\n return null;\n}\n\nexport function ifInside(options: {\n nodes: string | string[],\n keyword: string,\n before?: string,\n after?: string\n}, source: CompletionSource): CompletionSource {\n\n const {\n nodes,\n before,\n after,\n keyword\n } = options;\n\n return (context) => {\n\n const { state, pos } = context;\n\n const match = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);\n\n if (!match) {\n return null;\n }\n\n const [ node ] = match;\n\n if (matchLeft(node, pos, [ keyword, before ])) {\n return null;\n }\n\n if (matchRight(node, pos, [ keyword, after ])) {\n return null;\n }\n\n if (after && !matchLeft(node, pos, [ after ])) {\n return null;\n }\n\n return source(context);\n };\n}","import {\n parser,\n trackVariables\n} from 'lezer-feel';\n\nimport {\n LRLanguage,\n LanguageSupport,\n delimitedIndent,\n continuedIndent,\n indentNodeProp,\n foldNodeProp,\n foldInside\n} from '@codemirror/language';\n\nimport {\n snippets\n} from './snippets';\n\nimport {\n keywordCompletions,\n snippetCompletion\n} from './completion';\n\nimport {\n CompletionSource\n} from '@codemirror/autocomplete';\n\n\n/**\n * A FEEL language provider based on the\n * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),\n * extended with highlighting and indentation information.\n */\nexport const feelLanguage = LRLanguage.define({\n parser: parser.configure({\n props: [\n indentNodeProp.add({\n 'Context': delimitedIndent({\n closing: '}'\n }),\n 'List FilterExpression': delimitedIndent({\n closing: ']'\n }),\n 'ParenthesizedExpression FunctionInvocation': continuedIndent({\n except: /^\\s*\\)/\n }),\n 'ForExpression QuantifiedExpression IfExpression': continuedIndent({\n except: /^\\s*(then|else|return|satisfies)\\b/\n }),\n 'FunctionDefinition': continuedIndent({\n except: /^\\s*(\\(|\\))/\n })\n }),\n foldNodeProp.add({\n Context: foldInside,\n List: foldInside,\n ParenthesizedExpression: foldInside,\n FunctionDefinition(node) {\n const last = node.getChild(')');\n\n if (!last) return null;\n\n return {\n from: last.to,\n to: node.to\n };\n }\n })\n ]\n }),\n languageData: {\n indentOnInput: /^\\s*(\\)|\\}|\\]|then|else|return|satisfies)$/,\n commentTokens: {\n line: '//',\n block: {\n open: '/*',\n close: '*/'\n }\n }\n }\n});\n\n/**\n * A language provider for FEEL Unary Tests\n */\nexport const unaryTestsLanguage = feelLanguage.configure({\n top: 'UnaryTests',\n}, 'FEEL unary tests');\n\n/**\n * Language provider for FEEL Expression\n */\nexport const expressionLanguage = feelLanguage.configure({\n top: 'Expression'\n}, 'FEEL expression');\n\n\n\n/**\n * Feel language support for CodeMirror.\n *\n * Includes [snippet](#lang-feel.snippets)\n */\nexport function feel(config: {\n dialect?: 'expression' | 'unaryTests',\n parserDialect?: string,\n completions?: CompletionSource[],\n context?: Record<string, any>\n} = {}) {\n const language = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;\n\n const dialect = config.parserDialect;\n const contextTracker = trackVariables(config.context);\n\n const contextualLang = language.configure({\n contextTracker,\n dialect\n });\n\n const completions = config.completions || [\n snippetCompletion(snippets),\n keywordCompletions,\n ].flat();\n\n return new LanguageSupport(contextualLang, [\n ...(\n completions.map(autocomplete => contextualLang.data.of({\n autocomplete\n }))\n )\n ]);\n\n}"],"names":["snippets","snippetCompletion","label","detail","type","contextualKeyword","options","context","nodes","after","before","keyword","ifInside","completeFromList","boost","keywordCompletions","dontComplete","doComplete","ifExpression","completionSource","allNodes","state","pos","match","matchUp","syntaxTree","resolveInner","_","name","includes","map","s","matchLeft","node","position","matchChildren","matchRight","direction","child","isError","firstChild","nodeNames","Array","isArray","parent","nodeType","matchedName","find","is","isTop","source","feelLanguage","LRLanguage","define","parser","configure","props","indentNodeProp","add","delimitedIndent","closing","continuedIndent","except","foldNodeProp","Context","foldInside","List","ParenthesizedExpression","FunctionDefinition","last","getChild","from","to","languageData","indentOnInput","commentTokens","line","block","open","close","unaryTestsLanguage","top","expressionLanguage","feel","config","language","dialect","parserDialect","contextTracker","trackVariables","contextualLang","completions","flat","LanguageSupport","autocomplete","data","of"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { parser, trackVariables } from 'lezer-feel';
2
2
  import { syntaxTree, LRLanguage, indentNodeProp, delimitedIndent, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
3
- import { snippetCompletion as snippetCompletion$1, completeFromList, ifNotIn } from '@codemirror/autocomplete';
3
+ import { snippetCompletion as snippetCompletion$1, completeFromList } from '@codemirror/autocomplete';
4
4
 
5
5
  /**
6
6
  * A collection of FEEL-related [snippets](#autocomplete.snippet).
@@ -29,6 +29,18 @@ const snippets = [snippetCompletion$1('function(${params}) ${body}', {
29
29
  label: 'context',
30
30
  detail: 'block',
31
31
  type: 'keyword'
32
+ }), snippetCompletion$1('null', {
33
+ label: 'null',
34
+ detail: 'literal',
35
+ type: 'keyword'
36
+ }), snippetCompletion$1('true', {
37
+ label: 'true',
38
+ detail: 'literal',
39
+ type: 'keyword'
40
+ }), snippetCompletion$1('false', {
41
+ label: 'false',
42
+ detail: 'literal',
43
+ type: 'keyword'
32
44
  })];
33
45
 
34
46
  function _extends() {
@@ -84,9 +96,27 @@ const keywordCompletions = [contextualKeyword({
84
96
  after: 'InExpressions',
85
97
  keyword: 'return'
86
98
  })];
87
- const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment', 'PathExpression'];
99
+ const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment', 'PathExpression', 'Context', 'Key', 'ParameterName'];
100
+ const doComplete = ['Expr', 'ContextEntry'];
101
+ function ifExpression(completionSource) {
102
+ const allNodes = [...dontComplete, ...doComplete];
103
+ return context => {
104
+ const {
105
+ state,
106
+ pos
107
+ } = context;
108
+ const match = matchUp(syntaxTree(state).resolveInner(pos, -1), allNodes);
109
+ if (match) {
110
+ const [_, name] = match;
111
+ if (dontComplete.includes(name)) {
112
+ return null;
113
+ }
114
+ }
115
+ return completionSource(context);
116
+ };
117
+ }
88
118
  function snippetCompletion(snippets) {
89
- return ifNotIn(dontComplete, completeFromList(snippets.map(s => _extends({}, s, {
119
+ return ifExpression(completeFromList(snippets.map(s => _extends({}, s, {
90
120
  type: 'text'
91
121
  }))));
92
122
  }
@@ -116,10 +146,12 @@ function matchUp(node, nodeNames) {
116
146
  nodeNames = [nodeNames];
117
147
  }
118
148
  for (; node; node = node.parent) {
119
- if (nodeNames.includes(node.name)) {
120
- return node;
149
+ const nodeType = node.type;
150
+ const matchedName = nodeNames.find(name => name && nodeType.is(name));
151
+ if (matchedName) {
152
+ return [node, matchedName];
121
153
  }
122
- if (node.type.isTop) {
154
+ if (nodeType.isTop) {
123
155
  break;
124
156
  }
125
157
  }
@@ -137,10 +169,11 @@ function ifInside(options, source) {
137
169
  state,
138
170
  pos
139
171
  } = context;
140
- const node = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);
141
- if (!node) {
172
+ const match = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);
173
+ if (!match) {
142
174
  return null;
143
175
  }
176
+ const [node] = match;
144
177
  if (matchLeft(node, pos, [keyword, before])) {
145
178
  return null;
146
179
  }
@@ -220,9 +253,12 @@ const expressionLanguage = feelLanguage.configure({
220
253
  * Includes [snippet](#lang-feel.snippets)
221
254
  */
222
255
  function feel(config = {}) {
223
- const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
224
- const contextualLang = lang.configure({
225
- contextTracker: trackVariables(config.context)
256
+ const language = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
257
+ const dialect = config.parserDialect;
258
+ const contextTracker = trackVariables(config.context);
259
+ const contextualLang = language.configure({
260
+ contextTracker,
261
+ dialect
226
262
  });
227
263
  const completions = config.completions || [snippetCompletion(snippets), keywordCompletions].flat();
228
264
  return new LanguageSupport(contextualLang, [...completions.map(autocomplete => contextualLang.data.of({
@@ -230,5 +266,5 @@ function feel(config = {}) {
230
266
  }))]);
231
267
  }
232
268
 
233
- export { contextualKeyword, dontComplete, expressionLanguage, feel, feelLanguage, ifInside, keywordCompletions, matchChildren, matchLeft, matchRight, snippetCompletion, snippets, unaryTestsLanguage };
269
+ export { contextualKeyword, doComplete, dontComplete, expressionLanguage, feel, feelLanguage, ifExpression, ifInside, keywordCompletions, matchChildren, matchLeft, matchRight, snippetCompletion, snippets, unaryTestsLanguage };
234
270
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/snippets.ts","../src/completion.ts","../src/feel.ts"],"sourcesContent":["import { Completion, snippetCompletion } from '@codemirror/autocomplete';\n\n/**\n * A collection of FEEL-related [snippets](#autocomplete.snippet).\n */\nexport const snippets: readonly Completion[] = [\n snippetCompletion('function(${params}) ${body}', {\n label: 'function',\n detail: 'definition',\n type: 'keyword'\n }),\n snippetCompletion('for ${var} in ${collection} return ${value}', {\n label: 'for',\n detail: 'expression',\n type: 'keyword'\n }),\n snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {\n label: 'every',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {\n label: 'some',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('if ${condition} then ${value} else ${other value}', {\n label: 'if',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('{ ${key}: ${value} }', {\n label: 'context',\n detail: 'block',\n type: 'keyword'\n })\n];\n","import { syntaxTree } from '@codemirror/language';\nimport { SyntaxNode } from '@lezer/common';\n\nimport {\n CompletionSource,\n Completion,\n completeFromList,\n ifNotIn\n} from '@codemirror/autocomplete';\n\n\nexport function contextualKeyword(options: {\n before?: string,\n after?: string,\n context: string,\n keyword: string\n}) : CompletionSource {\n\n const {\n context: nodes,\n after,\n before,\n keyword\n } = options;\n\n return ifInside({ nodes, before, after, keyword }, completeFromList([\n { label: keyword, type: 'keyword', boost: 10 }\n ]));\n}\n\nexport const keywordCompletions = [\n contextualKeyword({\n context: 'InExpression',\n keyword: 'in'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'then',\n after: 'if',\n before: 'else'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'else',\n after: 'then'\n }),\n contextualKeyword({\n context: 'QuantifiedExpression',\n keyword: 'satisfies'\n }),\n contextualKeyword({\n context: 'ForExpression',\n after: 'InExpressions',\n keyword: 'return'\n })\n];\n\nexport const dontComplete = [\n 'StringLiteral', 'Identifier',\n 'LineComment', 'BlockComment',\n 'PathExpression'\n];\n\nexport function snippetCompletion(snippets: readonly Completion[]) : CompletionSource {\n return ifNotIn(\n dontComplete, completeFromList(snippets.map(s => ({ ...s, type: 'text' })))\n );\n}\n\nexport function matchLeft(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, -1);\n}\n\nexport function matchRight(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, 1);\n}\n\nexport function matchChildren(node: SyntaxNode, position: number, nodes: (string|undefined)[], direction: 1 | -1) : SyntaxNode | null {\n\n let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);\n\n while (child) {\n if (nodes.includes(child.name)) {\n return child;\n }\n\n if (child.type.isError && child.firstChild) {\n if (nodes.includes(child.firstChild.name)) {\n return child.firstChild;\n }\n }\n\n child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];\n }\n\n return null;\n}\n\nfunction matchUp(node: SyntaxNode, nodeNames: string | undefined | (string | undefined)[]) {\n\n if (!Array.isArray(nodeNames)) {\n nodeNames = [ nodeNames ];\n }\n\n for (; node; node = node.parent!) {\n if (nodeNames.includes(node.name)) {\n return node;\n }\n\n if (node.type.isTop) {\n break;\n }\n }\n\n return null;\n}\n\nexport function ifInside(options: {\n nodes: string | string[],\n keyword: string,\n before?: string,\n after?: string\n}, source: CompletionSource): CompletionSource {\n\n const {\n nodes,\n before,\n after,\n keyword\n } = options;\n\n return (context) => {\n\n const { state, pos } = context;\n\n const node = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);\n\n if (!node) {\n return null;\n }\n\n if (matchLeft(node, pos, [ keyword, before ])) {\n return null;\n }\n\n if (matchRight(node, pos, [ keyword, after ])) {\n return null;\n }\n\n if (after && !matchLeft(node, pos, [ after ])) {\n return null;\n }\n\n return source(context);\n };\n}","import {\n parser,\n trackVariables\n} from 'lezer-feel';\n\nimport {\n LRLanguage,\n LanguageSupport,\n delimitedIndent,\n continuedIndent,\n indentNodeProp,\n foldNodeProp,\n foldInside\n} from '@codemirror/language';\n\nimport {\n snippets\n} from './snippets';\n\nimport {\n keywordCompletions,\n snippetCompletion\n} from './completion';\n\nimport {\n CompletionSource\n} from '@codemirror/autocomplete';\n\n\n/**\n * A FEEL language provider based on the\n * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),\n * extended with highlighting and indentation information.\n */\nexport const feelLanguage = LRLanguage.define({\n parser: parser.configure({\n props: [\n indentNodeProp.add({\n 'Context': delimitedIndent({\n closing: '}'\n }),\n 'List FilterExpression': delimitedIndent({\n closing: ']'\n }),\n 'ParenthesizedExpression FunctionInvocation': continuedIndent({\n except: /^\\s*\\)/\n }),\n 'ForExpression QuantifiedExpression IfExpression': continuedIndent({\n except: /^\\s*(then|else|return|satisfies)\\b/\n }),\n 'FunctionDefinition': continuedIndent({\n except: /^\\s*(\\(|\\))/\n })\n }),\n foldNodeProp.add({\n Context: foldInside,\n List: foldInside,\n ParenthesizedExpression: foldInside,\n FunctionDefinition(node) {\n const last = node.getChild(')');\n\n if (!last) return null;\n\n return {\n from: last.to,\n to: node.to\n };\n }\n })\n ]\n }),\n languageData: {\n indentOnInput: /^\\s*(\\)|\\}|\\]|then|else|return|satisfies)$/,\n commentTokens: {\n line: '//',\n block: {\n open: '/*',\n close: '*/'\n }\n }\n }\n});\n\n/**\n * A language provider for FEEL Unary Tests\n */\nexport const unaryTestsLanguage = feelLanguage.configure({\n top: 'UnaryTests',\n}, 'FEEL unary tests');\n\n/**\n * Language provider for FEEL Expression\n */\nexport const expressionLanguage = feelLanguage.configure({\n top: 'Expression'\n}, 'FEEL expression');\n\n\n\n/**\n * Feel language support for CodeMirror.\n *\n * Includes [snippet](#lang-feel.snippets)\n */\nexport function feel(config: {\n dialect?: 'expression' | 'unaryTests',\n completions?: CompletionSource[],\n context?: Record<string, any>\n} = {}) {\n const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;\n\n const contextualLang = lang.configure({\n contextTracker: trackVariables(config.context)\n });\n\n const completions = config.completions || [\n snippetCompletion(snippets),\n keywordCompletions,\n ].flat();\n\n return new LanguageSupport(contextualLang, [\n ...(\n completions.map(autocomplete => contextualLang.data.of({\n autocomplete\n }))\n )\n ]);\n\n}"],"names":["snippets","snippetCompletion","label","detail","type","contextualKeyword","options","context","nodes","after","before","keyword","ifInside","completeFromList","boost","keywordCompletions","dontComplete","ifNotIn","map","s","_extends","matchLeft","node","position","matchChildren","matchRight","direction","child","includes","name","isError","firstChild","matchUp","nodeNames","Array","isArray","parent","isTop","source","state","pos","syntaxTree","resolveInner","feelLanguage","LRLanguage","define","parser","configure","props","indentNodeProp","add","delimitedIndent","closing","continuedIndent","except","foldNodeProp","Context","foldInside","List","ParenthesizedExpression","FunctionDefinition","last","getChild","from","to","languageData","indentOnInput","commentTokens","line","block","open","close","unaryTestsLanguage","top","expressionLanguage","feel","config","lang","dialect","contextualLang","contextTracker","trackVariables","completions","flat","LanguageSupport","autocomplete","data","of"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/snippets.ts","../src/completion.ts","../src/feel.ts"],"sourcesContent":["import { Completion, snippetCompletion } from '@codemirror/autocomplete';\n\n/**\n * A collection of FEEL-related [snippets](#autocomplete.snippet).\n */\nexport const snippets: readonly Completion[] = [\n snippetCompletion('function(${params}) ${body}', {\n label: 'function',\n detail: 'definition',\n type: 'keyword'\n }),\n snippetCompletion('for ${var} in ${collection} return ${value}', {\n label: 'for',\n detail: 'expression',\n type: 'keyword'\n }),\n snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {\n label: 'every',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {\n label: 'some',\n detail: 'quantified expression',\n type: 'keyword'\n }),\n snippetCompletion('if ${condition} then ${value} else ${other value}', {\n label: 'if',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('{ ${key}: ${value} }', {\n label: 'context',\n detail: 'block',\n type: 'keyword'\n }),\n snippetCompletion('null', {\n label: 'null',\n detail: 'literal',\n type: 'keyword'\n }),\n snippetCompletion('true', {\n label: 'true',\n detail: 'literal',\n type: 'keyword'\n }),\n snippetCompletion('false', {\n label: 'false',\n detail: 'literal',\n type: 'keyword'\n })\n];\n","import { syntaxTree } from '@codemirror/language';\nimport { SyntaxNode } from '@lezer/common';\n\nimport {\n CompletionSource,\n Completion,\n completeFromList,\n CompletionContext\n} from '@codemirror/autocomplete';\n\n\nexport function contextualKeyword(options: {\n before?: string,\n after?: string,\n context: string,\n keyword: string\n}) : CompletionSource {\n\n const {\n context: nodes,\n after,\n before,\n keyword\n } = options;\n\n return ifInside({ nodes, before, after, keyword }, completeFromList([\n { label: keyword, type: 'keyword', boost: 10 }\n ]));\n}\n\nexport const keywordCompletions = [\n contextualKeyword({\n context: 'InExpression',\n keyword: 'in'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'then',\n after: 'if',\n before: 'else'\n }),\n contextualKeyword({\n context: 'IfExpression',\n keyword: 'else',\n after: 'then'\n }),\n contextualKeyword({\n context: 'QuantifiedExpression',\n keyword: 'satisfies'\n }),\n contextualKeyword({\n context: 'ForExpression',\n after: 'InExpressions',\n keyword: 'return'\n })\n];\n\nexport const dontComplete = [\n 'StringLiteral', 'Identifier',\n 'LineComment', 'BlockComment',\n 'PathExpression', 'Context',\n 'Key', 'ParameterName'\n];\n\nexport const doComplete = [\n 'Expr',\n 'ContextEntry'\n];\n\nexport function ifExpression(completionSource: CompletionSource) : CompletionSource {\n\n const allNodes = [ ...dontComplete, ...doComplete ];\n\n return (context: CompletionContext) => {\n\n const { state, pos } = context;\n\n const match = matchUp(syntaxTree(state).resolveInner(pos, -1), allNodes);\n\n if (match) {\n\n const [ _, name ] = match;\n\n if (dontComplete.includes(name)) {\n return null;\n }\n }\n\n return completionSource(context);\n };\n}\n\nexport function snippetCompletion(snippets: readonly Completion[]) : CompletionSource {\n return ifExpression(\n completeFromList(snippets.map(s => ({ ...s, type: 'text' })))\n );\n}\n\nexport function matchLeft(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, -1);\n}\n\nexport function matchRight(node: SyntaxNode, position: number, nodes: (string|undefined)[]) : SyntaxNode | null {\n return matchChildren(node, position, nodes, 1);\n}\n\nexport function matchChildren(node: SyntaxNode, position: number, nodes: (string|undefined)[], direction: 1 | -1) : SyntaxNode | null {\n\n let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);\n\n while (child) {\n if (nodes.includes(child.name)) {\n return child;\n }\n\n if (child.type.isError && child.firstChild) {\n if (nodes.includes(child.firstChild.name)) {\n return child.firstChild;\n }\n }\n\n child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];\n }\n\n return null;\n}\n\nfunction matchUp(node: SyntaxNode, nodeNames: string | string[]) : [ SyntaxNode, string ] | null {\n\n if (!Array.isArray(nodeNames)) {\n nodeNames = [ nodeNames ];\n }\n\n for (; node; node = node.parent!) {\n\n const nodeType = node.type;\n\n const matchedName = nodeNames.find(name => name && nodeType.is(name));\n\n if (matchedName) {\n return [ node, matchedName ];\n }\n\n if (nodeType.isTop) {\n break;\n }\n }\n\n return null;\n}\n\nexport function ifInside(options: {\n nodes: string | string[],\n keyword: string,\n before?: string,\n after?: string\n}, source: CompletionSource): CompletionSource {\n\n const {\n nodes,\n before,\n after,\n keyword\n } = options;\n\n return (context) => {\n\n const { state, pos } = context;\n\n const match = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);\n\n if (!match) {\n return null;\n }\n\n const [ node ] = match;\n\n if (matchLeft(node, pos, [ keyword, before ])) {\n return null;\n }\n\n if (matchRight(node, pos, [ keyword, after ])) {\n return null;\n }\n\n if (after && !matchLeft(node, pos, [ after ])) {\n return null;\n }\n\n return source(context);\n };\n}","import {\n parser,\n trackVariables\n} from 'lezer-feel';\n\nimport {\n LRLanguage,\n LanguageSupport,\n delimitedIndent,\n continuedIndent,\n indentNodeProp,\n foldNodeProp,\n foldInside\n} from '@codemirror/language';\n\nimport {\n snippets\n} from './snippets';\n\nimport {\n keywordCompletions,\n snippetCompletion\n} from './completion';\n\nimport {\n CompletionSource\n} from '@codemirror/autocomplete';\n\n\n/**\n * A FEEL language provider based on the\n * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),\n * extended with highlighting and indentation information.\n */\nexport const feelLanguage = LRLanguage.define({\n parser: parser.configure({\n props: [\n indentNodeProp.add({\n 'Context': delimitedIndent({\n closing: '}'\n }),\n 'List FilterExpression': delimitedIndent({\n closing: ']'\n }),\n 'ParenthesizedExpression FunctionInvocation': continuedIndent({\n except: /^\\s*\\)/\n }),\n 'ForExpression QuantifiedExpression IfExpression': continuedIndent({\n except: /^\\s*(then|else|return|satisfies)\\b/\n }),\n 'FunctionDefinition': continuedIndent({\n except: /^\\s*(\\(|\\))/\n })\n }),\n foldNodeProp.add({\n Context: foldInside,\n List: foldInside,\n ParenthesizedExpression: foldInside,\n FunctionDefinition(node) {\n const last = node.getChild(')');\n\n if (!last) return null;\n\n return {\n from: last.to,\n to: node.to\n };\n }\n })\n ]\n }),\n languageData: {\n indentOnInput: /^\\s*(\\)|\\}|\\]|then|else|return|satisfies)$/,\n commentTokens: {\n line: '//',\n block: {\n open: '/*',\n close: '*/'\n }\n }\n }\n});\n\n/**\n * A language provider for FEEL Unary Tests\n */\nexport const unaryTestsLanguage = feelLanguage.configure({\n top: 'UnaryTests',\n}, 'FEEL unary tests');\n\n/**\n * Language provider for FEEL Expression\n */\nexport const expressionLanguage = feelLanguage.configure({\n top: 'Expression'\n}, 'FEEL expression');\n\n\n\n/**\n * Feel language support for CodeMirror.\n *\n * Includes [snippet](#lang-feel.snippets)\n */\nexport function feel(config: {\n dialect?: 'expression' | 'unaryTests',\n parserDialect?: string,\n completions?: CompletionSource[],\n context?: Record<string, any>\n} = {}) {\n const language = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;\n\n const dialect = config.parserDialect;\n const contextTracker = trackVariables(config.context);\n\n const contextualLang = language.configure({\n contextTracker,\n dialect\n });\n\n const completions = config.completions || [\n snippetCompletion(snippets),\n keywordCompletions,\n ].flat();\n\n return new LanguageSupport(contextualLang, [\n ...(\n completions.map(autocomplete => contextualLang.data.of({\n autocomplete\n }))\n )\n ]);\n\n}"],"names":["snippets","snippetCompletion","label","detail","type","contextualKeyword","options","context","nodes","after","before","keyword","ifInside","completeFromList","boost","keywordCompletions","dontComplete","doComplete","ifExpression","completionSource","allNodes","state","pos","match","matchUp","syntaxTree","resolveInner","_","name","includes","map","s","_extends","matchLeft","node","position","matchChildren","matchRight","direction","child","isError","firstChild","nodeNames","Array","isArray","parent","nodeType","matchedName","find","is","isTop","source","feelLanguage","LRLanguage","define","parser","configure","props","indentNodeProp","add","delimitedIndent","closing","continuedIndent","except","foldNodeProp","Context","foldInside","List","ParenthesizedExpression","FunctionDefinition","last","getChild","from","to","languageData","indentOnInput","commentTokens","line","block","open","close","unaryTestsLanguage","top","expressionLanguage","feel","config","language","dialect","parserDialect","contextTracker","trackVariables","contextualLang","completions","flat","LanguageSupport","autocomplete","data","of"],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "lang-feel",
3
- "version": "2.1.1",
3
+ "version": "2.3.0",
4
4
  "description": "FEEL language support for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "all": "run-s lint build test",
7
7
  "test": "karma start karma.conf.cjs",
8
+ "start": "SINGLE_START=1 npm run dev",
8
9
  "dev": "run-p 'build -- watch' 'test -- --no-single-run --auto-watch'",
9
10
  "lint": "eslint . --ext ts",
10
11
  "build": "microbundle -f modern,cjs --target node",
@@ -30,37 +31,38 @@
30
31
  "sideEffects": false,
31
32
  "license": "MIT",
32
33
  "dependencies": {
33
- "@codemirror/autocomplete": "^6.16.2",
34
- "@codemirror/language": "^6.10.2",
35
- "@codemirror/state": "^6.4.1",
36
- "@codemirror/view": "^6.28.1",
37
- "@lezer/common": "^1.2.1",
38
- "lezer-feel": "^1.2.9"
34
+ "@codemirror/autocomplete": "^6.18.4",
35
+ "@codemirror/language": "^6.10.8",
36
+ "@lezer/common": "^1.2.3",
37
+ "lezer-feel": "^1.7.0"
39
38
  },
40
39
  "devDependencies": {
41
- "@lezer/lr": "^1.4.1",
42
- "@types/karma-chai": "^0.1.6",
40
+ "@codemirror/state": "^6.5.1",
41
+ "@codemirror/view": "^6.36.2",
42
+ "@lezer/lr": "^1.4.2",
43
+ "@types/karma-chai": "^0.1.7",
43
44
  "@types/karma-mocha": "^1.3.4",
44
- "@types/mocha": "^10.0.6",
45
- "@typescript-eslint/eslint-plugin": "^7.13.0",
46
- "@typescript-eslint/parser": "^7.13.0",
47
- "chai": "^4.4.1",
45
+ "@types/mocha": "^10.0.10",
46
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
47
+ "@typescript-eslint/parser": "^7.18.0",
48
+ "chai": "^4.5.0",
48
49
  "codemirror": "^6.0.1",
49
50
  "eslint": "^8.57.0",
50
51
  "eslint-plugin-bpmn-io": "^1.0.0",
51
- "karma": "^6.4.3",
52
+ "karma": "^6.4.4",
52
53
  "karma-chai": "^0.1.0",
53
54
  "karma-chrome-launcher": "^3.2.0",
54
55
  "karma-debug-launcher": "^0.0.5",
56
+ "karma-env-preprocessor": "^0.1.1",
55
57
  "karma-mocha": "^2.0.1",
56
58
  "karma-webpack": "^5.0.1",
57
59
  "microbundle": "^0.15.1",
58
- "mocha": "^10.4.0",
59
- "npm-run-all2": "^6.2.0",
60
- "puppeteer": "^22.11.0",
61
- "ts-loader": "^9.5.1",
62
- "typescript": "^5.4.5",
63
- "webpack": "^5.92.0"
60
+ "mocha": "^10.8.2",
61
+ "npm-run-all2": "^7.0.2",
62
+ "puppeteer": "^23.11.1",
63
+ "ts-loader": "^9.5.2",
64
+ "typescript": "^5.7.3",
65
+ "webpack": "^5.97.1"
64
66
  },
65
67
  "repository": {
66
68
  "type": "git",
package/dist/context.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { EditorState } from '@codemirror/state';
2
- export declare function getContextAtPos(state: EditorState, variables: Record<string, any>, pos: number): null | undefined;