lang-feel 1.1.0 → 2.1.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/README.md CHANGED
@@ -8,4 +8,9 @@ This package implements the [DMN](https://www.omg.org/spec/DMN/) FEEL language s
8
8
  ## Related
9
9
 
10
10
  * [lezer-feel](https://github.com/nikku/lezer-feel) - FEEL grammar
11
- * [feelin](https://github.com/nikku/feelin) - FEEL parser + interpreter
11
+ * [feelin](https://github.com/nikku/feelin) - FEEL parser + interpreter
12
+
13
+
14
+ ## License
15
+
16
+ MIT
@@ -0,0 +1,20 @@
1
+ import { SyntaxNode } from '@lezer/common';
2
+ import { CompletionSource, Completion } from '@codemirror/autocomplete';
3
+ export declare function contextualKeyword(options: {
4
+ before?: string;
5
+ after?: string;
6
+ context: string;
7
+ keyword: string;
8
+ }): CompletionSource;
9
+ export declare const keywordCompletions: CompletionSource[];
10
+ export declare const dontComplete: string[];
11
+ export declare function snippetCompletion(snippets: readonly Completion[]): CompletionSource;
12
+ export declare function matchLeft(node: SyntaxNode, position: number, nodes: (string | undefined)[]): SyntaxNode | null;
13
+ export declare function matchRight(node: SyntaxNode, position: number, nodes: (string | undefined)[]): SyntaxNode | null;
14
+ export declare function matchChildren(node: SyntaxNode, position: number, nodes: (string | undefined)[], direction: 1 | -1): SyntaxNode | null;
15
+ export declare function ifInside(options: {
16
+ nodes: string | string[];
17
+ keyword: string;
18
+ before?: string;
19
+ after?: string;
20
+ }, source: CompletionSource): CompletionSource;
package/dist/feel.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { LRLanguage, LanguageSupport } from '@codemirror/language';
2
+ import { CompletionSource } from '@codemirror/autocomplete';
3
+ /**
4
+ * A FEEL language provider based on the
5
+ * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),
6
+ * extended with highlighting and indentation information.
7
+ */
8
+ export declare const feelLanguage: LRLanguage;
9
+ /**
10
+ * A language provider for FEEL Unary Tests
11
+ */
12
+ export declare const unaryTestsLanguage: LRLanguage;
13
+ /**
14
+ * Language provider for FEEL Expression
15
+ */
16
+ export declare const expressionLanguage: LRLanguage;
17
+ /**
18
+ * Feel language support for CodeMirror.
19
+ *
20
+ * Includes [snippet](#lang-feel.snippets)
21
+ */
22
+ export declare function feel(config?: {
23
+ dialect?: 'expression' | 'unaryTests';
24
+ completions?: CompletionSource[];
25
+ context?: Record<string, any>;
26
+ }): LanguageSupport;
package/dist/index.cjs CHANGED
@@ -1,114 +1,232 @@
1
- 'use strict';
2
-
3
1
  var lezerFeel = require('lezer-feel');
4
2
  var language = require('@codemirror/language');
5
3
  var autocomplete = require('@codemirror/autocomplete');
6
4
 
7
- // / A collection of FEEL-related
8
- // / [snippets](#autocomplete.snippet).
9
- const snippets = [
10
- autocomplete.snippetCompletion('function(${params}) ${body}', {
11
- label: 'function',
12
- detail: 'definition',
13
- type: 'keyword'
14
- }),
15
- autocomplete.snippetCompletion('for ${var} in ${collection} return ${value}', {
16
- label: 'for',
17
- detail: 'expression',
18
- type: 'keyword'
19
- }),
20
- autocomplete.snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {
21
- label: 'every',
22
- detail: 'quantified expression',
23
- type: 'keyword'
24
- }),
25
- autocomplete.snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {
26
- label: 'some',
27
- detail: 'quantified expression',
28
- type: 'keyword'
29
- }),
30
- autocomplete.snippetCompletion('if ${condition} then ${value} else ${other value}', {
31
- label: 'if',
32
- detail: 'block',
33
- type: 'keyword'
34
- })
35
- ];
5
+ /**
6
+ * A collection of FEEL-related [snippets](#autocomplete.snippet).
7
+ */
8
+ const snippets = [autocomplete.snippetCompletion('function(${params}) ${body}', {
9
+ label: 'function',
10
+ detail: 'definition',
11
+ type: 'keyword'
12
+ }), autocomplete.snippetCompletion('for ${var} in ${collection} return ${value}', {
13
+ label: 'for',
14
+ detail: 'expression',
15
+ type: 'keyword'
16
+ }), autocomplete.snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {
17
+ label: 'every',
18
+ detail: 'quantified expression',
19
+ type: 'keyword'
20
+ }), autocomplete.snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {
21
+ label: 'some',
22
+ detail: 'quantified expression',
23
+ type: 'keyword'
24
+ }), autocomplete.snippetCompletion('if ${condition} then ${value} else ${other value}', {
25
+ label: 'if',
26
+ detail: 'block',
27
+ type: 'keyword'
28
+ }), autocomplete.snippetCompletion('{ ${key}: ${value} }', {
29
+ label: 'context',
30
+ detail: 'block',
31
+ type: 'keyword'
32
+ })];
33
+
34
+ function contextualKeyword(options) {
35
+ const {
36
+ context: nodes,
37
+ after,
38
+ before,
39
+ keyword
40
+ } = options;
41
+ return ifInside({
42
+ nodes,
43
+ before,
44
+ after,
45
+ keyword
46
+ }, autocomplete.completeFromList([{
47
+ label: keyword,
48
+ type: 'keyword',
49
+ boost: 10
50
+ }]));
51
+ }
52
+ const keywordCompletions = [contextualKeyword({
53
+ context: 'InExpression',
54
+ keyword: 'in'
55
+ }), contextualKeyword({
56
+ context: 'IfExpression',
57
+ keyword: 'then',
58
+ after: 'if',
59
+ before: 'else'
60
+ }), contextualKeyword({
61
+ context: 'IfExpression',
62
+ keyword: 'else',
63
+ after: 'then'
64
+ }), contextualKeyword({
65
+ context: 'QuantifiedExpression',
66
+ keyword: 'satisfies'
67
+ }), contextualKeyword({
68
+ context: 'ForExpression',
69
+ after: 'InExpressions',
70
+ keyword: 'return'
71
+ })];
72
+ const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment'];
73
+ function snippetCompletion(snippets) {
74
+ return autocomplete.ifNotIn(dontComplete, autocomplete.completeFromList(snippets.map(s => ({
75
+ ...s,
76
+ type: 'text'
77
+ }))));
78
+ }
79
+ function matchLeft(node, position, nodes) {
80
+ return matchChildren(node, position, nodes, -1);
81
+ }
82
+ function matchRight(node, position, nodes) {
83
+ return matchChildren(node, position, nodes, 1);
84
+ }
85
+ function matchChildren(node, position, nodes, direction) {
86
+ let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);
87
+ while (child) {
88
+ if (nodes.includes(child.name)) {
89
+ return child;
90
+ }
91
+ if (child.type.isError && child.firstChild) {
92
+ if (nodes.includes(child.firstChild.name)) {
93
+ return child.firstChild;
94
+ }
95
+ }
96
+ child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];
97
+ }
98
+ return null;
99
+ }
100
+ function matchUp(node, nodeNames) {
101
+ if (!Array.isArray(nodeNames)) {
102
+ nodeNames = [nodeNames];
103
+ }
104
+ for (; node; node = node.parent) {
105
+ if (nodeNames.includes(node.name)) {
106
+ return node;
107
+ }
108
+ if (node.type.isTop) {
109
+ break;
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ function ifInside(options, source) {
115
+ const {
116
+ nodes,
117
+ before,
118
+ after,
119
+ keyword
120
+ } = options;
121
+ return context => {
122
+ const {
123
+ state,
124
+ pos
125
+ } = context;
126
+ const node = matchUp(language.syntaxTree(state).resolveInner(pos, -1), nodes);
127
+ if (!node) {
128
+ return null;
129
+ }
130
+ if (matchLeft(node, pos, [keyword, before])) {
131
+ return null;
132
+ }
133
+ if (matchRight(node, pos, [keyword, after])) {
134
+ return null;
135
+ }
136
+ if (after && !matchLeft(node, pos, [after])) {
137
+ return null;
138
+ }
139
+ return source(context);
140
+ };
141
+ }
36
142
 
37
- // / A language provider based on the [Lezer FEEL
38
- // / parser](https://github.com/nikku/lezer-feel), extended with
39
- // / highlighting and indentation information.
143
+ /**
144
+ * A FEEL language provider based on the
145
+ * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),
146
+ * extended with highlighting and indentation information.
147
+ */
40
148
  const feelLanguage = language.LRLanguage.define({
41
- parser: lezerFeel.parser.configure({
42
- props: [
43
- language.indentNodeProp.add({
44
- 'Context': language.delimitedIndent({
45
- closing: '}'
46
- }),
47
- 'List FilterExpression': language.delimitedIndent({
48
- closing: ']'
49
- }),
50
- 'ParenthesizedExpression FunctionInvocation': language.continuedIndent({
51
- except: /^\s*\)/
52
- }),
53
- 'ForExpression QuantifiedExpression IfExpression': language.continuedIndent({
54
- except: /^\s*(then|else|return|satisfies)\b/
55
- }),
56
- 'FunctionDefinition': language.continuedIndent({
57
- except: /^\s*(\(|\))/
58
- })
59
- }),
60
- language.foldNodeProp.add({
61
- Context: language.foldInside,
62
- List: language.foldInside,
63
- ParenthesizedExpression: language.foldInside,
64
- FunctionDefinition(node) {
65
- const last = node.getChild(')');
66
- if (!last)
67
- return null;
68
- return {
69
- from: last.to,
70
- to: node.to
71
- };
72
- }
73
- })
74
- ]
75
- }),
76
- languageData: {
77
- indentOnInput: /^\s*(\)|\}|\]|then|else|return|satisfies)$/,
78
- commentTokens: {
79
- line: '//',
80
- block: {
81
- open: '/*',
82
- close: '*/'
83
- }
84
- }
149
+ parser: lezerFeel.parser.configure({
150
+ props: [language.indentNodeProp.add({
151
+ 'Context': language.delimitedIndent({
152
+ closing: '}'
153
+ }),
154
+ 'List FilterExpression': language.delimitedIndent({
155
+ closing: ']'
156
+ }),
157
+ 'ParenthesizedExpression FunctionInvocation': language.continuedIndent({
158
+ except: /^\s*\)/
159
+ }),
160
+ 'ForExpression QuantifiedExpression IfExpression': language.continuedIndent({
161
+ except: /^\s*(then|else|return|satisfies)\b/
162
+ }),
163
+ 'FunctionDefinition': language.continuedIndent({
164
+ except: /^\s*(\(|\))/
165
+ })
166
+ }), language.foldNodeProp.add({
167
+ Context: language.foldInside,
168
+ List: language.foldInside,
169
+ ParenthesizedExpression: language.foldInside,
170
+ FunctionDefinition(node) {
171
+ const last = node.getChild(')');
172
+ if (!last) return null;
173
+ return {
174
+ from: last.to,
175
+ to: node.to
176
+ };
177
+ }
178
+ })]
179
+ }),
180
+ languageData: {
181
+ indentOnInput: /^\s*(\)|\}|\]|then|else|return|satisfies)$/,
182
+ commentTokens: {
183
+ line: '//',
184
+ block: {
185
+ open: '/*',
186
+ close: '*/'
187
+ }
85
188
  }
189
+ }
86
190
  });
87
- // / A language provider for TypeScript.
88
- const unaryTestsLanguage = feelLanguage.configure({ top: 'UnaryTests' });
89
- // / Language provider for JSX.
90
- const expressionLanguage = feelLanguage.configure({ top: 'Expression' });
91
- const keywords = 'return satisfies then in'.split(' ').map(kw => ({ label: kw, type: 'keyword' }));
92
- const dontComplete = [
93
- 'StringLiteral', 'Name',
94
- 'LineComment', 'BlockComment'
95
- ];
96
- // / FEEL support. Includes [snippet](#lang-feel.snippets)
97
- // / completion.
191
+ /**
192
+ * A language provider for FEEL Unary Tests
193
+ */
194
+ const unaryTestsLanguage = feelLanguage.configure({
195
+ top: 'UnaryTests'
196
+ }, 'FEEL unary tests');
197
+ /**
198
+ * Language provider for FEEL Expression
199
+ */
200
+ const expressionLanguage = feelLanguage.configure({
201
+ top: 'Expression'
202
+ }, 'FEEL expression');
203
+ /**
204
+ * Feel language support for CodeMirror.
205
+ *
206
+ * Includes [snippet](#lang-feel.snippets)
207
+ */
98
208
  function feel(config = {}) {
99
- const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
100
- const contextualLang = lang.configure({
101
- contextTracker: lezerFeel.trackVariables(config.context)
102
- });
103
- return new language.LanguageSupport(contextualLang, [
104
- feelLanguage.data.of({
105
- autocomplete: autocomplete.ifNotIn(dontComplete, autocomplete.completeFromList(snippets.concat(keywords)))
106
- })
107
- ]);
209
+ const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
210
+ const contextualLang = lang.configure({
211
+ contextTracker: lezerFeel.trackVariables(config.context)
212
+ });
213
+ const completions = config.completions || [snippetCompletion(snippets), keywordCompletions].flat();
214
+ return new language.LanguageSupport(contextualLang, [...completions.map(autocomplete => contextualLang.data.of({
215
+ autocomplete
216
+ }))]);
108
217
  }
109
218
 
219
+ exports.contextualKeyword = contextualKeyword;
220
+ exports.dontComplete = dontComplete;
110
221
  exports.expressionLanguage = expressionLanguage;
111
222
  exports.feel = feel;
112
223
  exports.feelLanguage = feelLanguage;
224
+ exports.ifInside = ifInside;
225
+ exports.keywordCompletions = keywordCompletions;
226
+ exports.matchChildren = matchChildren;
227
+ exports.matchLeft = matchLeft;
228
+ exports.matchRight = matchRight;
229
+ exports.snippetCompletion = snippetCompletion;
113
230
  exports.snippets = snippets;
114
231
  exports.unaryTestsLanguage = unaryTestsLanguage;
232
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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];\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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"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,3 @@
1
- import { LRLanguage, LanguageSupport } from '@codemirror/language';
2
- import { Completion } from '@codemirror/autocomplete';
3
-
4
- declare const feelLanguage: LRLanguage;
5
- declare const unaryTestsLanguage: LRLanguage;
6
- declare const expressionLanguage: LRLanguage;
7
- declare function feel(config?: {
8
- dialect?: 'expression' | 'unaryTests';
9
- context?: Record<string, any>;
10
- }): LanguageSupport;
11
-
12
- declare const snippets: readonly Completion[];
13
-
14
- export { expressionLanguage, feel, feelLanguage, snippets, unaryTestsLanguage };
1
+ export { feel, feelLanguage, expressionLanguage, unaryTestsLanguage } from './feel';
2
+ export { snippets } from './snippets';
3
+ export * from './completion';
package/dist/index.js CHANGED
@@ -1,108 +1,234 @@
1
1
  import { parser, trackVariables } from 'lezer-feel';
2
- import { LRLanguage, indentNodeProp, delimitedIndent, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
3
- import { snippetCompletion, ifNotIn, completeFromList } from '@codemirror/autocomplete';
2
+ import { syntaxTree, LRLanguage, indentNodeProp, delimitedIndent, continuedIndent, foldNodeProp, foldInside, LanguageSupport } from '@codemirror/language';
3
+ import { snippetCompletion as snippetCompletion$1, completeFromList, ifNotIn } from '@codemirror/autocomplete';
4
4
 
5
- // / A collection of FEEL-related
6
- // / [snippets](#autocomplete.snippet).
7
- const snippets = [
8
- /*@__PURE__*/snippetCompletion('function(${params}) ${body}', {
9
- label: 'function',
10
- detail: 'definition',
11
- type: 'keyword'
12
- }),
13
- /*@__PURE__*/snippetCompletion('for ${var} in ${collection} return ${value}', {
14
- label: 'for',
15
- detail: 'expression',
16
- type: 'keyword'
17
- }),
18
- /*@__PURE__*/snippetCompletion('every ${var} in ${collection} satisfies ${condition}', {
19
- label: 'every',
20
- detail: 'quantified expression',
21
- type: 'keyword'
22
- }),
23
- /*@__PURE__*/snippetCompletion('some ${var} in ${collection} satisfies ${condition}', {
24
- label: 'some',
25
- detail: 'quantified expression',
26
- type: 'keyword'
27
- }),
28
- /*@__PURE__*/snippetCompletion('if ${condition} then ${value} else ${other value}', {
29
- label: 'if',
30
- detail: 'block',
31
- type: 'keyword'
32
- })
33
- ];
5
+ /**
6
+ * A collection of FEEL-related [snippets](#autocomplete.snippet).
7
+ */
8
+ const snippets = [snippetCompletion$1('function(${params}) ${body}', {
9
+ label: 'function',
10
+ detail: 'definition',
11
+ type: 'keyword'
12
+ }), snippetCompletion$1('for ${var} in ${collection} return ${value}', {
13
+ label: 'for',
14
+ detail: 'expression',
15
+ type: 'keyword'
16
+ }), snippetCompletion$1('every ${var} in ${collection} satisfies ${condition}', {
17
+ label: 'every',
18
+ detail: 'quantified expression',
19
+ type: 'keyword'
20
+ }), snippetCompletion$1('some ${var} in ${collection} satisfies ${condition}', {
21
+ label: 'some',
22
+ detail: 'quantified expression',
23
+ type: 'keyword'
24
+ }), snippetCompletion$1('if ${condition} then ${value} else ${other value}', {
25
+ label: 'if',
26
+ detail: 'block',
27
+ type: 'keyword'
28
+ }), snippetCompletion$1('{ ${key}: ${value} }', {
29
+ label: 'context',
30
+ detail: 'block',
31
+ type: 'keyword'
32
+ })];
34
33
 
35
- // / A language provider based on the [Lezer FEEL
36
- // / parser](https://github.com/nikku/lezer-feel), extended with
37
- // / highlighting and indentation information.
38
- const feelLanguage = /*@__PURE__*/LRLanguage.define({
39
- parser: /*@__PURE__*/parser.configure({
40
- props: [
41
- /*@__PURE__*/indentNodeProp.add({
42
- 'Context': /*@__PURE__*/delimitedIndent({
43
- closing: '}'
44
- }),
45
- 'List FilterExpression': /*@__PURE__*/delimitedIndent({
46
- closing: ']'
47
- }),
48
- 'ParenthesizedExpression FunctionInvocation': /*@__PURE__*/continuedIndent({
49
- except: /^\s*\)/
50
- }),
51
- 'ForExpression QuantifiedExpression IfExpression': /*@__PURE__*/continuedIndent({
52
- except: /^\s*(then|else|return|satisfies)\b/
53
- }),
54
- 'FunctionDefinition': /*@__PURE__*/continuedIndent({
55
- except: /^\s*(\(|\))/
56
- })
57
- }),
58
- /*@__PURE__*/foldNodeProp.add({
59
- Context: foldInside,
60
- List: foldInside,
61
- ParenthesizedExpression: foldInside,
62
- FunctionDefinition(node) {
63
- const last = node.getChild(')');
64
- if (!last)
65
- return null;
66
- return {
67
- from: last.to,
68
- to: node.to
69
- };
70
- }
71
- })
72
- ]
73
- }),
74
- languageData: {
75
- indentOnInput: /^\s*(\)|\}|\]|then|else|return|satisfies)$/,
76
- commentTokens: {
77
- line: '//',
78
- block: {
79
- open: '/*',
80
- close: '*/'
81
- }
34
+ function _extends() {
35
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
36
+ for (var i = 1; i < arguments.length; i++) {
37
+ var source = arguments[i];
38
+ for (var key in source) {
39
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
40
+ target[key] = source[key];
82
41
  }
42
+ }
83
43
  }
44
+ return target;
45
+ };
46
+ return _extends.apply(this, arguments);
47
+ }
48
+
49
+ function contextualKeyword(options) {
50
+ const {
51
+ context: nodes,
52
+ after,
53
+ before,
54
+ keyword
55
+ } = options;
56
+ return ifInside({
57
+ nodes,
58
+ before,
59
+ after,
60
+ keyword
61
+ }, completeFromList([{
62
+ label: keyword,
63
+ type: 'keyword',
64
+ boost: 10
65
+ }]));
66
+ }
67
+ const keywordCompletions = [contextualKeyword({
68
+ context: 'InExpression',
69
+ keyword: 'in'
70
+ }), contextualKeyword({
71
+ context: 'IfExpression',
72
+ keyword: 'then',
73
+ after: 'if',
74
+ before: 'else'
75
+ }), contextualKeyword({
76
+ context: 'IfExpression',
77
+ keyword: 'else',
78
+ after: 'then'
79
+ }), contextualKeyword({
80
+ context: 'QuantifiedExpression',
81
+ keyword: 'satisfies'
82
+ }), contextualKeyword({
83
+ context: 'ForExpression',
84
+ after: 'InExpressions',
85
+ keyword: 'return'
86
+ })];
87
+ const dontComplete = ['StringLiteral', 'Identifier', 'LineComment', 'BlockComment'];
88
+ function snippetCompletion(snippets) {
89
+ return ifNotIn(dontComplete, completeFromList(snippets.map(s => _extends({}, s, {
90
+ type: 'text'
91
+ }))));
92
+ }
93
+ function matchLeft(node, position, nodes) {
94
+ return matchChildren(node, position, nodes, -1);
95
+ }
96
+ function matchRight(node, position, nodes) {
97
+ return matchChildren(node, position, nodes, 1);
98
+ }
99
+ function matchChildren(node, position, nodes, direction) {
100
+ let child = node[direction > 0 ? 'childAfter' : 'childBefore'](position);
101
+ while (child) {
102
+ if (nodes.includes(child.name)) {
103
+ return child;
104
+ }
105
+ if (child.type.isError && child.firstChild) {
106
+ if (nodes.includes(child.firstChild.name)) {
107
+ return child.firstChild;
108
+ }
109
+ }
110
+ child = child[direction > 0 ? 'nextSibling' : 'prevSibling'];
111
+ }
112
+ return null;
113
+ }
114
+ function matchUp(node, nodeNames) {
115
+ if (!Array.isArray(nodeNames)) {
116
+ nodeNames = [nodeNames];
117
+ }
118
+ for (; node; node = node.parent) {
119
+ if (nodeNames.includes(node.name)) {
120
+ return node;
121
+ }
122
+ if (node.type.isTop) {
123
+ break;
124
+ }
125
+ }
126
+ return null;
127
+ }
128
+ function ifInside(options, source) {
129
+ const {
130
+ nodes,
131
+ before,
132
+ after,
133
+ keyword
134
+ } = options;
135
+ return context => {
136
+ const {
137
+ state,
138
+ pos
139
+ } = context;
140
+ const node = matchUp(syntaxTree(state).resolveInner(pos, -1), nodes);
141
+ if (!node) {
142
+ return null;
143
+ }
144
+ if (matchLeft(node, pos, [keyword, before])) {
145
+ return null;
146
+ }
147
+ if (matchRight(node, pos, [keyword, after])) {
148
+ return null;
149
+ }
150
+ if (after && !matchLeft(node, pos, [after])) {
151
+ return null;
152
+ }
153
+ return source(context);
154
+ };
155
+ }
156
+
157
+ /**
158
+ * A FEEL language provider based on the
159
+ * [Lezer FEEL parser](https://github.com/nikku/lezer-feel),
160
+ * extended with highlighting and indentation information.
161
+ */
162
+ const feelLanguage = LRLanguage.define({
163
+ parser: parser.configure({
164
+ props: [indentNodeProp.add({
165
+ 'Context': delimitedIndent({
166
+ closing: '}'
167
+ }),
168
+ 'List FilterExpression': delimitedIndent({
169
+ closing: ']'
170
+ }),
171
+ 'ParenthesizedExpression FunctionInvocation': continuedIndent({
172
+ except: /^\s*\)/
173
+ }),
174
+ 'ForExpression QuantifiedExpression IfExpression': continuedIndent({
175
+ except: /^\s*(then|else|return|satisfies)\b/
176
+ }),
177
+ 'FunctionDefinition': continuedIndent({
178
+ except: /^\s*(\(|\))/
179
+ })
180
+ }), foldNodeProp.add({
181
+ Context: foldInside,
182
+ List: foldInside,
183
+ ParenthesizedExpression: foldInside,
184
+ FunctionDefinition(node) {
185
+ const last = node.getChild(')');
186
+ if (!last) return null;
187
+ return {
188
+ from: last.to,
189
+ to: node.to
190
+ };
191
+ }
192
+ })]
193
+ }),
194
+ languageData: {
195
+ indentOnInput: /^\s*(\)|\}|\]|then|else|return|satisfies)$/,
196
+ commentTokens: {
197
+ line: '//',
198
+ block: {
199
+ open: '/*',
200
+ close: '*/'
201
+ }
202
+ }
203
+ }
84
204
  });
85
- // / A language provider for TypeScript.
86
- const unaryTestsLanguage = /*@__PURE__*/feelLanguage.configure({ top: 'UnaryTests' });
87
- // / Language provider for JSX.
88
- const expressionLanguage = /*@__PURE__*/feelLanguage.configure({ top: 'Expression' });
89
- const keywords = /*@__PURE__*/'return satisfies then in'.split(' ').map(kw => ({ label: kw, type: 'keyword' }));
90
- const dontComplete = [
91
- 'StringLiteral', 'Name',
92
- 'LineComment', 'BlockComment'
93
- ];
94
- // / FEEL support. Includes [snippet](#lang-feel.snippets)
95
- // / completion.
205
+ /**
206
+ * A language provider for FEEL Unary Tests
207
+ */
208
+ const unaryTestsLanguage = feelLanguage.configure({
209
+ top: 'UnaryTests'
210
+ }, 'FEEL unary tests');
211
+ /**
212
+ * Language provider for FEEL Expression
213
+ */
214
+ const expressionLanguage = feelLanguage.configure({
215
+ top: 'Expression'
216
+ }, 'FEEL expression');
217
+ /**
218
+ * Feel language support for CodeMirror.
219
+ *
220
+ * Includes [snippet](#lang-feel.snippets)
221
+ */
96
222
  function feel(config = {}) {
97
- const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
98
- const contextualLang = lang.configure({
99
- contextTracker: trackVariables(config.context)
100
- });
101
- return new LanguageSupport(contextualLang, [
102
- feelLanguage.data.of({
103
- autocomplete: ifNotIn(dontComplete, completeFromList(snippets.concat(keywords)))
104
- })
105
- ]);
223
+ const lang = config.dialect === 'unaryTests' ? unaryTestsLanguage : expressionLanguage;
224
+ const contextualLang = lang.configure({
225
+ contextTracker: trackVariables(config.context)
226
+ });
227
+ const completions = config.completions || [snippetCompletion(snippets), keywordCompletions].flat();
228
+ return new LanguageSupport(contextualLang, [...completions.map(autocomplete => contextualLang.data.of({
229
+ autocomplete
230
+ }))]);
106
231
  }
107
232
 
108
- export { expressionLanguage, feel, feelLanguage, snippets, unaryTestsLanguage };
233
+ export { contextualKeyword, dontComplete, expressionLanguage, feel, feelLanguage, ifInside, keywordCompletions, matchChildren, matchLeft, matchRight, snippetCompletion, snippets, unaryTestsLanguage };
234
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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];\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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"}
@@ -0,0 +1,5 @@
1
+ import { Completion } from '@codemirror/autocomplete';
2
+ /**
3
+ * A collection of FEEL-related [snippets](#autocomplete.snippet).
4
+ */
5
+ export declare const snippets: readonly Completion[];
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "lang-feel",
3
- "version": "1.1.0",
3
+ "version": "2.1.0",
4
4
  "description": "FEEL language support for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "all": "run-s lint build test",
7
- "test": "cm-runtests",
7
+ "test": "karma start karma.conf.cjs",
8
+ "dev": "run-p 'build -- watch' 'test -- --no-single-run --auto-watch'",
8
9
  "lint": "eslint . --ext ts",
9
- "build": "cm-buildhelper src/index.ts",
10
- "prepare": "npm run build",
11
- "dev": "chokidar 'src/*.ts' 'test/*.ts' --initial -c 'npm run build && npm test'"
10
+ "build": "microbundle -f modern,cjs --target node",
11
+ "prepare": "npm run build"
12
12
  },
13
13
  "keywords": [
14
14
  "editor",
@@ -19,6 +19,7 @@
19
19
  "url": "https://github.com/nikku"
20
20
  },
21
21
  "type": "module",
22
+ "source": "src/index.ts",
22
23
  "main": "dist/index.cjs",
23
24
  "exports": {
24
25
  "import": "./dist/index.js",
@@ -29,24 +30,37 @@
29
30
  "sideEffects": false,
30
31
  "license": "MIT",
31
32
  "dependencies": {
32
- "@codemirror/autocomplete": "^6.9.1",
33
- "@codemirror/language": "^6.9.1",
34
- "@codemirror/state": "^6.2.1",
35
- "@codemirror/view": "^6.21.0",
36
- "@lezer/common": "^1.1.0",
37
- "lezer-feel": "^1.2.0"
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"
38
39
  },
39
40
  "devDependencies": {
40
- "@codemirror/buildhelper": "^1.0.0",
41
- "@lezer/lr": "^1.3.12",
42
- "@typescript-eslint/eslint-plugin": "^6.7.3",
43
- "@typescript-eslint/parser": "^6.7.3",
44
- "chokidar": "^3.5.3",
45
- "chokidar-cli": "^3.0.0",
46
- "eslint": "^8.50.0",
41
+ "@lezer/lr": "^1.4.1",
42
+ "@types/karma-chai": "^0.1.6",
43
+ "@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",
48
+ "codemirror": "^6.0.1",
49
+ "eslint": "^8.57.0",
47
50
  "eslint-plugin-bpmn-io": "^1.0.0",
48
- "npm-run-all": "^4.1.5",
49
- "typescript": "^5.2.2"
51
+ "karma": "^6.4.3",
52
+ "karma-chai": "^0.1.0",
53
+ "karma-chrome-launcher": "^3.2.0",
54
+ "karma-debug-launcher": "^0.0.5",
55
+ "karma-mocha": "^2.0.1",
56
+ "karma-webpack": "^5.0.1",
57
+ "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"
50
64
  },
51
65
  "repository": {
52
66
  "type": "git",
package/dist/index.d.cts DELETED
@@ -1,14 +0,0 @@
1
- import { LRLanguage, LanguageSupport } from '@codemirror/language';
2
- import { Completion } from '@codemirror/autocomplete';
3
-
4
- declare const feelLanguage: LRLanguage;
5
- declare const unaryTestsLanguage: LRLanguage;
6
- declare const expressionLanguage: LRLanguage;
7
- declare function feel(config?: {
8
- dialect?: 'expression' | 'unaryTests';
9
- context?: Record<string, any>;
10
- }): LanguageSupport;
11
-
12
- declare const snippets: readonly Completion[];
13
-
14
- export { expressionLanguage, feel, feelLanguage, snippets, unaryTestsLanguage };