@valtzu/codemirror-lang-el 0.2.3 → 0.4.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 +64 -32
- package/dist/index.cjs +157 -50
- package/dist/index.d.cts +24 -8
- package/dist/index.d.ts +24 -8
- package/dist/index.js +158 -51
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,44 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
### Symfony Expression Language support for CodeMirror
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
#### Features
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
1. Autocompletion for variables, functions, operator keywords – with (some) type resolving
|
|
6
|
+
2. Hover tooltip
|
|
7
|
+
3. Linting
|
|
6
8
|
|
|
9
|
+
#### Example
|
|
10
|
+
|
|
11
|
+

|
|
7
12
|
|
|
8
13
|
```html
|
|
9
14
|
<div id="editor"></div>
|
|
10
15
|
<script type="importmap">
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
{
|
|
17
|
+
"imports": {
|
|
18
|
+
"codemirror": "https://esm.sh/*codemirror@6.0.1",
|
|
19
|
+
"@codemirror/state": "https://esm.sh/*@codemirror/state@6.4.1",
|
|
20
|
+
"@codemirror/search": "https://esm.sh/*@codemirror/search@6.5.6",
|
|
21
|
+
"@codemirror/autocomplete": "https://esm.sh/*@codemirror/autocomplete@6.9.0",
|
|
22
|
+
"@codemirror/view": "https://esm.sh/*@codemirror/view@6.17.1",
|
|
23
|
+
"@codemirror/commands": "https://esm.sh/*@codemirror/commands@6.2.5",
|
|
24
|
+
"@codemirror/language": "https://esm.sh/*@codemirror/language@6.9.0",
|
|
25
|
+
"@codemirror/lint": "https://esm.sh/*@codemirror/lint@6.4.1",
|
|
26
|
+
"@lezer/lr": "https://esm.sh/*@lezer/lr@1.3.9",
|
|
27
|
+
"@lezer/highlight": "https://esm.sh/*@lezer/highlight@1.1.6",
|
|
28
|
+
"@lezer/common": "https://esm.sh/*@lezer/common@1.2.1",
|
|
29
|
+
"style-mod": "https://esm.sh/*style-mod@4.1.2",
|
|
30
|
+
"w3c-keyname": "https://esm.sh/*w3c-keyname@2.2.8",
|
|
31
|
+
"crelt": "https://esm.sh/*crelt@1.0.6",
|
|
32
|
+
"@valtzu/codemirror-lang-el": "https://esm.sh/*@valtzu/codemirror-lang-el@0.4.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
19
35
|
</script>
|
|
20
36
|
<script type="module">
|
|
21
|
-
import {EditorView, basicSetup} from "codemirror";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
37
|
+
import { EditorView, basicSetup } from "codemirror";
|
|
38
|
+
import { acceptCompletion } from "@codemirror/autocomplete";
|
|
39
|
+
import { keymap } from "@codemirror/view";
|
|
40
|
+
import { expressionlanguage } from "@valtzu/codemirror-lang-el";
|
|
41
|
+
|
|
25
42
|
|
|
26
|
-
let editor = new EditorView({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
+
let editor = new EditorView({
|
|
44
|
+
extensions: [
|
|
45
|
+
basicSetup,
|
|
46
|
+
keymap.of([...defaultKeymap, {key: "Tab", run: acceptCompletion}]),
|
|
47
|
+
expressionlanguage({
|
|
48
|
+
types: {
|
|
49
|
+
"User": {
|
|
50
|
+
identifiers: [
|
|
51
|
+
{ name: "self", type: ["User"], info: 'Self-reference for property-access demonstration purposes' },
|
|
52
|
+
{ name: "name", type: ["string"] },
|
|
53
|
+
{ name: "age", type: ["int"], info: "Years since birthday", detail: "years" },
|
|
54
|
+
],
|
|
55
|
+
functions: [
|
|
56
|
+
{ name: "isActive", returnType: ["bool"] },
|
|
57
|
+
{ name: "getGroup", args: [], returnType: ["Group"], info: 'Get the user group' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
"Group": {
|
|
61
|
+
identifiers: [{ name: "name", type: ["string"] }]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
identifiers: [
|
|
65
|
+
{ name: "user", type: ["User"], info: 'This is the user' },
|
|
66
|
+
],
|
|
67
|
+
functions: [
|
|
68
|
+
{ name: "is_granted", args: ["subject", "object"], info: 'Check if subject has permission to the object', returnType: ['bool'] },
|
|
69
|
+
],
|
|
70
|
+
})
|
|
71
|
+
],
|
|
72
|
+
parent: document.getElementById('editor'),
|
|
73
|
+
doc: 'is_granted(user, user.self.getGroup())',
|
|
74
|
+
});
|
|
43
75
|
</script>
|
|
44
76
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -11,30 +11,63 @@ var view = require('@codemirror/view');
|
|
|
11
11
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
12
12
|
const parser = lr.LRParser.deserialize({
|
|
13
13
|
version: 14,
|
|
14
|
-
states: "
|
|
15
|
-
stateData: "
|
|
16
|
-
goto: "!
|
|
17
|
-
nodeNames: "⚠
|
|
18
|
-
maxTerm:
|
|
19
|
-
nodeProps: [
|
|
20
|
-
["openedBy", 15,"OpeningBracket"],
|
|
21
|
-
["closedBy", 16,"ClosingBracket"]
|
|
22
|
-
],
|
|
14
|
+
states: "'[OVQPOOQtQQO'#C^O!YQQOOO#TQPO'#ChO#[QPO'#CiOVQPO'#CnOOQO'#Cu'#CuOVQPO'#CuO#cQPO,58xOVQPO,58|OVQPO,59UOVQPO,59VO#hQPO,58}O#oQQO,59SOOQO,59S,59SO#vQQO,59TOOQO,59T,59TO$QQQO,59YO$hQQO,59aOOQO1G.d1G.dO$oQQO1G.hO$vQQO1G.pO$}QQO1G.qO%eQQO1G.iOOQO1G.i1G.iOVQPO1G.nOVQPO'#CpO%oQPO1G.oOOQO1G.o1G.oOOQO1G.{1G.{OOQO7+$S7+$SOVQPO7+$[O%wQPO7+$TOOQO7+$T7+$TO&PQQO7+$YO&ZQQO,59[OOQO-E6n-E6nOOQO7+$Z7+$ZO&hQQO<<GvOOQO<<Go<<GoOVQPO'#CqO'OQPO<<GtOOQO<<Gt<<GtO'WQQO,59]OOQO-E6o-E6oOOQOAN=`AN=`OVQPO1G.wO'_QQO7+$c",
|
|
15
|
+
stateData: "'s~OhOS~OTQOWUOXUOYUOZUOcTOkSOmVOpRO~ORWOSWO`ZOaZOkXOrYO~Om[ORiXSiX`iXaiXfiXkiXriXqiXjiXniXliXoiX~Oo^O~PVOj`O~PVOTcO~OlhO~PVOqiO~PtOjlOnjO~PtOfbaqbajbanbalbaoba~PtOlmO~PtOjnO~PtOqoO~PtOf_iq_ij_in_il_io_i~PtOlqOnjO~PtOjuOnjO~OlwOnjO~OnxOozO~PtOjdandalda~PtOf^yq^yj^yn^yl^yo^y~PtOnxOo}O~Oq!OO~PtOneqoeq~PtORSc`YZWTY~",
|
|
16
|
+
goto: "#ijPPkPPP{{PPPP{{{{PP{P!]!gPPP!mmQORSTVXYZ[ijox!OmUORSTVXYZ[ijox!OQk_QpgTtkpQyrR|yQPOQ]RQ_SQaTQbVQdXQeYQfZQg[QriQsjQvoQ{xR!P!O",
|
|
17
|
+
nodeNames: "⚠ Expression ObjectAccess NullSafeMemberOf MemberOf Identifier ArrayAccess FunctionCall Number String Boolean Null Object Array TernaryExpression BinaryExpression OperatorKeyword Operator UnaryExpression UnaryOperator",
|
|
18
|
+
maxTerm: 34,
|
|
23
19
|
skippedNodes: [0],
|
|
24
20
|
repeatNodeCount: 2,
|
|
25
|
-
tokenData: "
|
|
21
|
+
tokenData: "AZ~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Ruv$|vw&{wx'Txy(xyz(}z{)S{|)[|})c}!O)[!O!P)h!P!Q$|!Q![)p![!],V!^!_$t!_!`,[!`!a$t!a!b,b!c!},u!}#O-W#P#Q-]#Q#R$|#R#S,u#T#U-b#U#V,u#V#W.u#W#X,u#X#Y2Z#Y#Z4u#Z#],u#]#^7V#^#a,u#a#b7n#b#c:S#c#d=c#d#g,u#g#h=z#h#i?w#i#o,u#o#p@w#p#q@|#q#rAU#r#s$|~$^Sh~XY$XYZ$X]^$Xpq$XR$qPaQcP!_!`$tQ$yPaQ!_!`$|Q%ROaQ~%UXOr%Rrs%qs#O%R#O#P%v#P;'S%R;'S;=`&u<%l~%R~O%R~~%q~%vOX~~%yRO;'S%R;'S;=`&S;=`O%R~&VYOr%Rrs%qs#O%R#O#P%v#P;'S%R;'S;=`&u;=`<%l%R<%l~%R~O%R~~%q~&xP;=`<%l%RQ'QPaQvw$|~'WXOw'Twx%qx#O'T#O#P's#P;'S'T;'S;=`(r<%l~'T~O'T~~%q~'vRO;'S'T;'S;=`(P;=`O'T~(SYOw'Twx%qx#O'T#O#P's#P;'S'T;'S;=`(r;=`<%l'T<%l~'T~O'T~~%q~(uP;=`<%l'T~(}Om~~)SOl~Q)XPaQz{$|R)cOaQcP~)hOn~~)mPS~!O!P$|~)uTW~!O!P*U!Q![)p!g!h+U#R#S,P#X#Y+U~*XSO!O*e!P;'S*e;'S;=`+y<%lO*e~*jRW~!Q![*s!g!h+U#X#Y+U~*xSW~!Q![*s!g!h+U#R#S+s#X#Y+U~+XR{|+b}!O+b!Q![+h~+eP!Q![+h~+mQW~!Q![+h#R#S+b~+vP!Q![*s~+|P;=`<%l*e~,SP!Q![)p~,[Oq~Q,_P!_!`$t~,gRr~!O!P,p![!]$|!a!b$|~,uOR~~,zST~!Q![,u!c!},u#R#S,u#T#o,u~-]Ok~~-bOj~~-gUT~!Q![,u!c!},u#R#S,u#T#b,u#b#c-y#c#o,u~.OUT~!Q![,u!c!},u#R#S,u#T#W,u#W#X.b#X#o,u~.iS`~T~!Q![,u!c!},u#R#S,u#T#o,u~.zUT~!Q![,u!c!},u#R#S,u#T#c,u#c#d/^#d#o,u~/cUT~!Q![,u!c!},u#R#S,u#T#b,u#b#c/u#c#o,u~/zUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i0^#i#o,u~0cTT~!Q![,u!c!},u#R#S,u#T#U0r#U#o,u~0wUT~!Q![,u!c!},u#R#S,u#T#],u#]#^1Z#^#o,u~1`UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c1r#c#o,u~1wUT~!Q![,u!c!},u#R#S,u#T#g,u#g#h.b#h#o,u~2`UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c2r#c#o,u~2wUT~!Q![,u!c!},u#R#S,u#T#W,u#W#X3Z#X#o,u~3`UT~!Q![,u!c!},u#R#S,u#T#g,u#g#h3r#h#o,u~3wTT~pq4W!Q![,u!c!},u#R#S,u#T#o,u~4ZP#k#l4^~4aP#]#^4d~4gP#h#i4j~4mP#[#]4p~4uO`~~4zTT~!Q![,u!c!},u#R#S,u#T#U5Z#U#o,u~5`UT~!Q![,u!c!},u#R#S,u#T#`,u#`#a5r#a#o,u~5wUT~!Q![,u!c!},u#R#S,u#T#g,u#g#h6Z#h#o,u~6`UT~!Q![,u!c!},u#R#S,u#T#X,u#X#Y6r#Y#o,u~6ySY~T~!Q![,u!c!},u#R#S,u#T#o,u~7[UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c.b#c#o,u~7sTT~!Q![,u!c!},u#R#S,u#T#U8S#U#o,u~8XUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i8k#i#o,u~8pUT~!Q![,u!c!},u#R#S,u#T#V,u#V#W9S#W#o,u~9XUT~!Q![,u!c!},u#R#S,u#T#[,u#[#]9k#]#o,u~9pUT~!Q![,u!c!},u#R#S,u#T#X,u#X#Y1r#Y#o,u~:XWT~!Q![,u!c!},u#R#S,u#T#c,u#c#d:q#d#i,u#i#j<O#j#o,u~:vUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i;Y#i#o,u~;cTcP`~T~pq;r!Q![,u!c!},u#R#S,u#T#o,u~;uP#]#^;x~;{P#b#c4p~<TUT~!Q![,u!c!},u#R#S,u#T#`,u#`#a<g#a#o,u~<lUT~!Q![,u!c!},u#R#S,u#T#`,u#`#a=O#a#o,u~=VSZ~T~!Q![,u!c!},u#R#S,u#T#o,u~=hUT~!Q![,u!c!},u#R#S,u#T#f,u#f#g.b#g#o,u~>PUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i>c#i#o,u~>hTT~!Q![,u!c!},u#R#S,u#T#U>w#U#o,u~>|UT~!Q![,u!c!},u#R#S,u#T#f,u#f#g?`#g#o,u~?eUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i3Z#i#o,u~?|UT~!Q![,u!c!},u#R#S,u#T#f,u#f#g@`#g#o,u~@eUT~!Q![,u!c!},u#R#S,u#T#i,u#i#j6Z#j#o,u~@|Op~QARPaQ#p#q$|~AZOo~",
|
|
26
22
|
tokenizers: [0, 1],
|
|
27
|
-
topRules: {"
|
|
28
|
-
tokenPrec:
|
|
23
|
+
topRules: {"Expression":[0,1]},
|
|
24
|
+
tokenPrec: 301
|
|
29
25
|
});
|
|
30
26
|
|
|
31
|
-
const identifier = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/;
|
|
32
27
|
const isFunction = (identifier, config) => { var _a; return (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(fn => fn.name === identifier); };
|
|
33
28
|
const isVariable = (identifier, config) => { var _a; return (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.find(variable => variable.name === identifier); };
|
|
29
|
+
const autocompleteFunction = (x) => { var _a, _b, _c; return ({ label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`, apply: `${x.name}(${!((_b = x.args) === null || _b === void 0 ? void 0 : _b.length) ? ')' : ''}`, detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'), info: x.info, type: "function" }); };
|
|
30
|
+
const autocompleteIdentifier = (x) => { var _a; return ({ label: x.name, apply: x.name, info: x.info, detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')), type: 'variable' }); };
|
|
34
31
|
const expressionLanguageLinter = (config) => lint.linter(view => {
|
|
35
32
|
let diagnostics = [];
|
|
33
|
+
let previousNode = null;
|
|
36
34
|
language.syntaxTree(view.state).cursor().iterate(node => {
|
|
35
|
+
var _a, _b, _c, _d, _e;
|
|
36
|
+
if (((_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ((_b = node.node.parent) === null || _b === void 0 ? void 0 : _b.firstChild) && node.name == "Identifier" && node.node.prevSibling) {
|
|
37
|
+
const leftArgument = node.node.parent.firstChild.node;
|
|
38
|
+
const types = resolveTypes(view.state, leftArgument, config, true);
|
|
39
|
+
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
40
|
+
if (((_d = (_c = node.node.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.name) === 'FunctionCall') {
|
|
41
|
+
if (!Array.from(types).find(type => { var _a, _b, _c; return (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === identifier); })) {
|
|
42
|
+
diagnostics.push({
|
|
43
|
+
from: node.from,
|
|
44
|
+
to: node.to,
|
|
45
|
+
severity: 'error',
|
|
46
|
+
message: `Method '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (types.size > 0) {
|
|
51
|
+
if (!Array.from(types).find(type => { var _a, _b, _c; return (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === identifier); })) {
|
|
52
|
+
diagnostics.push({
|
|
53
|
+
from: node.from,
|
|
54
|
+
to: node.to,
|
|
55
|
+
severity: 'warning',
|
|
56
|
+
message: `Property '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
37
62
|
if (node.name == "Identifier") {
|
|
63
|
+
if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.name) == "Identifier" && !['Array', 'FunctionCall'].includes(((_e = node.node.parent) === null || _e === void 0 ? void 0 : _e.name) || '')) {
|
|
64
|
+
diagnostics.push({
|
|
65
|
+
from: node.from,
|
|
66
|
+
to: node.to,
|
|
67
|
+
severity: 'error',
|
|
68
|
+
message: `Unexpected identifier after another identifier`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
38
71
|
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
39
72
|
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
40
73
|
diagnostics.push({
|
|
@@ -45,28 +78,40 @@ const expressionLanguageLinter = (config) => lint.linter(view => {
|
|
|
45
78
|
});
|
|
46
79
|
}
|
|
47
80
|
}
|
|
81
|
+
previousNode = node.node;
|
|
48
82
|
});
|
|
49
83
|
return diagnostics;
|
|
50
84
|
});
|
|
51
85
|
const keywordTooltip = (config) => view.hoverTooltip((view, pos, side) => {
|
|
52
|
-
var _a, _b;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
while (start > from && /\w/.test(text[start - from - 1]))
|
|
56
|
-
start--;
|
|
57
|
-
while (end < to && /\w/.test(text[end - from]))
|
|
58
|
-
end++;
|
|
59
|
-
if (start == pos && side < 0 || end == pos && side > 0) {
|
|
86
|
+
var _a, _b, _c, _d, _e, _f;
|
|
87
|
+
const tree = language.syntaxTree(view.state).resolveInner(pos, side);
|
|
88
|
+
if (tree.name !== 'Identifier') {
|
|
60
89
|
return null;
|
|
61
90
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
91
|
+
const skipEmpty = (x) => x;
|
|
92
|
+
let info;
|
|
93
|
+
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.firstChild) && ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) === 'ObjectAccess' && tree.prevSibling) {
|
|
94
|
+
const node = tree.parent.firstChild;
|
|
95
|
+
const types = resolveTypes(view.state, node, config, true);
|
|
96
|
+
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
97
|
+
info = [
|
|
98
|
+
...Array.from(types).map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
99
|
+
...Array.from(types).map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
104
|
+
info = [
|
|
105
|
+
...[(_d = (_c = config.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info].filter(skipEmpty),
|
|
106
|
+
...[(_f = (_e = config.functions) === null || _e === void 0 ? void 0 : _e.find(x => x.name === name)) === null || _f === void 0 ? void 0 : _f.info].filter(skipEmpty),
|
|
107
|
+
].join('\n');
|
|
108
|
+
}
|
|
64
109
|
if (!info) {
|
|
65
110
|
return null;
|
|
66
111
|
}
|
|
67
112
|
return {
|
|
68
|
-
pos:
|
|
69
|
-
end,
|
|
113
|
+
pos: tree.from,
|
|
114
|
+
end: tree.to,
|
|
70
115
|
above: true,
|
|
71
116
|
create(view) {
|
|
72
117
|
let dom = document.createElement("div");
|
|
@@ -90,62 +135,124 @@ const ELLanguage = language.LRLanguage.define({
|
|
|
90
135
|
Boolean: highlight.tags.bool,
|
|
91
136
|
String: highlight.tags.string,
|
|
92
137
|
Number: highlight.tags.number,
|
|
93
|
-
|
|
94
|
-
|
|
138
|
+
'(': highlight.tags.paren,
|
|
139
|
+
')': highlight.tags.paren,
|
|
95
140
|
'[': highlight.tags.squareBracket,
|
|
96
141
|
']': highlight.tags.squareBracket,
|
|
97
142
|
OperatorKeyword: highlight.tags.operatorKeyword,
|
|
98
143
|
Operator: highlight.tags.operator,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Punctuation: highlight.tags.punctuation,
|
|
144
|
+
MemberOf: highlight.tags.operator,
|
|
145
|
+
NullSafeMemberOf: highlight.tags.operator,
|
|
102
146
|
})
|
|
103
147
|
]
|
|
104
148
|
}),
|
|
105
149
|
languageData: {}
|
|
106
150
|
});
|
|
107
|
-
function completeOperatorKeyword(state, config, tree, from, to) {
|
|
151
|
+
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
108
152
|
var _a, _b;
|
|
109
153
|
const text = state.sliceDoc(from, to);
|
|
110
154
|
return {
|
|
111
155
|
from,
|
|
112
156
|
to,
|
|
113
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(
|
|
114
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(
|
|
157
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text)).map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
158
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : false; },
|
|
115
159
|
};
|
|
116
160
|
}
|
|
117
|
-
function completeIdentifier(state, config, tree, from, to) {
|
|
118
|
-
var _a, _b, _c, _d
|
|
119
|
-
const text = state.sliceDoc(from, to);
|
|
120
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
121
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
161
|
+
function completeIdentifier(state, config, tree, from, to, explicit) {
|
|
162
|
+
var _a, _b, _c, _d;
|
|
163
|
+
const text = state.sliceDoc(from, to).toLowerCase();
|
|
164
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
165
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
166
|
+
return {
|
|
167
|
+
from,
|
|
168
|
+
to,
|
|
169
|
+
options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
|
|
170
|
+
// validFor: identifier,
|
|
171
|
+
filter: false,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function resolveTypes(state, node, config, matchExact) {
|
|
175
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
176
|
+
let types = new Set();
|
|
177
|
+
if (node.name === 'FunctionCall' && node.firstChild && node.lastChild) {
|
|
178
|
+
resolveTypes(state, node.firstChild, config, matchExact).forEach(x => types.add(x));
|
|
179
|
+
}
|
|
180
|
+
else if (node.name === 'Identifier') {
|
|
181
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
182
|
+
(_c = (_b = (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(x => x.name == varName)) === null || _b === void 0 ? void 0 : _b.returnType) === null || _c === void 0 ? void 0 : _c.forEach(x => types.add(x));
|
|
183
|
+
(_f = (_e = (_d = config.identifiers) === null || _d === void 0 ? void 0 : _d.find(x => x.name == varName)) === null || _e === void 0 ? void 0 : _e.type) === null || _f === void 0 ? void 0 : _f.forEach(x => types.add(x));
|
|
184
|
+
}
|
|
185
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Identifier') {
|
|
186
|
+
const baseTypes = resolveTypes(state, node.firstChild, config, matchExact);
|
|
187
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
188
|
+
for (const baseType of baseTypes) {
|
|
189
|
+
const type = (_h = config.types) === null || _h === void 0 ? void 0 : _h[baseType];
|
|
190
|
+
(_k = (_j = type === null || type === void 0 ? void 0 : type.functions) === null || _j === void 0 ? void 0 : _j.filter(x => matchExact ? x.name === varName : x.name.startsWith(varName))) === null || _k === void 0 ? void 0 : _k.forEach(def => (def.returnType || ['any']).forEach(x => types.add(x)));
|
|
191
|
+
(_m = (_l = type === null || type === void 0 ? void 0 : type.identifiers) === null || _l === void 0 ? void 0 : _l.filter(x => matchExact ? x.name === varName : x.name.startsWith(varName))) === null || _m === void 0 ? void 0 : _m.forEach(def => (def.type || ['any']).forEach(x => types.add(x)));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (types.size === 0) {
|
|
195
|
+
types.add('any');
|
|
196
|
+
}
|
|
197
|
+
return types;
|
|
198
|
+
}
|
|
199
|
+
function completeMember(state, config, tree, from, to, explicit) {
|
|
200
|
+
var _a, _b, _c, _d;
|
|
201
|
+
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const types = resolveTypes(state, tree.parent.firstChild.node, config, false);
|
|
205
|
+
if (!(types === null || types === void 0 ? void 0 : types.size)) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const varName = state.sliceDoc(from, to);
|
|
209
|
+
let options = [];
|
|
210
|
+
for (const type of types) {
|
|
211
|
+
const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
|
|
212
|
+
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.filter(x => x.name.startsWith(varName)).map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.filter(x => x.name.startsWith(varName)).map(autocompleteFunction)) || []));
|
|
213
|
+
}
|
|
122
214
|
return {
|
|
123
215
|
from,
|
|
124
216
|
to,
|
|
125
|
-
options
|
|
126
|
-
|
|
127
|
-
...((_f = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _f !== void 0 ? _f : []),
|
|
128
|
-
],
|
|
129
|
-
validFor: identifier,
|
|
217
|
+
options,
|
|
218
|
+
filter: false,
|
|
130
219
|
};
|
|
131
220
|
}
|
|
132
221
|
function expressionLanguageCompletionFor(config, context) {
|
|
133
|
-
|
|
134
|
-
|
|
222
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
223
|
+
const { state, pos, explicit } = context;
|
|
224
|
+
const tree = language.syntaxTree(state).resolveInner(pos, -1);
|
|
225
|
+
const isOperator = (node) => node && ['Operator', 'OperatorKeyword'].includes(node.name);
|
|
226
|
+
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.name) === 'Identifier';
|
|
227
|
+
const prevNode = ((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.node.type.isError) ? tree.parent.prevSibling : tree.prevSibling;
|
|
135
228
|
if (tree.name == 'String') {
|
|
136
229
|
return null;
|
|
137
230
|
}
|
|
138
|
-
if (tree.
|
|
139
|
-
return
|
|
231
|
+
if (((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Identifier', 'FunctionCall'].includes(((_c = tree.parent.firstChild) === null || _c === void 0 ? void 0 : _c.name) || '')) {
|
|
232
|
+
return completeMember(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos);
|
|
140
233
|
}
|
|
141
|
-
|
|
142
|
-
|
|
234
|
+
// No idea what's going on here, just added conditions until all the tests passed :)
|
|
235
|
+
if (prevNode && !isOperator(prevNode.node) && (((_d = tree.parent) === null || _d === void 0 ? void 0 : _d.node.type.isError) || ((_e = tree.node.parent) === null || _e === void 0 ? void 0 : _e.name) === 'BinaryExpression') || (tree.name === 'Expression' && !((_g = (_f = tree.lastChild) === null || _f === void 0 ? void 0 : _f.type) === null || _g === void 0 ? void 0 : _g.isError) && !isOperator((_h = tree.lastChild) === null || _h === void 0 ? void 0 : _h.node))) {
|
|
236
|
+
return completeOperatorKeyword(state, config, tree, tree.name !== 'Expression' ? tree.from : pos, pos, explicit);
|
|
237
|
+
}
|
|
238
|
+
if (tree.name === 'Expression' || isIdentifier(tree.node) || (tree.name === 'BinaryExpression' && isOperator((_k = (_j = tree.lastChild) === null || _j === void 0 ? void 0 : _j.prevSibling) === null || _k === void 0 ? void 0 : _k.node) && explicit)) {
|
|
239
|
+
return completeIdentifier(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos, explicit);
|
|
143
240
|
}
|
|
144
241
|
return null;
|
|
145
242
|
}
|
|
146
243
|
function expressionLanguageCompletionSourceWith(config) {
|
|
147
244
|
var _a;
|
|
148
|
-
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
245
|
+
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
246
|
+
{ name: 'starts with' },
|
|
247
|
+
{ name: 'ends with' },
|
|
248
|
+
{ name: 'contains' },
|
|
249
|
+
{ name: 'matches' },
|
|
250
|
+
{ name: 'not in' },
|
|
251
|
+
{ name: 'in' },
|
|
252
|
+
{ name: 'not' },
|
|
253
|
+
{ name: 'or' },
|
|
254
|
+
{ name: 'and' },
|
|
255
|
+
]);
|
|
149
256
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
150
257
|
}
|
|
151
258
|
function expressionlanguage(config = {}, extensions = []) {
|
package/dist/index.d.cts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
|
+
interface ELIdentifier {
|
|
3
|
+
name: string;
|
|
4
|
+
detail?: string;
|
|
5
|
+
info?: string;
|
|
6
|
+
type?: string[];
|
|
7
|
+
}
|
|
8
|
+
interface ELFunction {
|
|
9
|
+
name: string;
|
|
10
|
+
args: string[];
|
|
11
|
+
info?: string;
|
|
12
|
+
returnType?: string[];
|
|
13
|
+
}
|
|
2
14
|
interface ExpressionLanguageConfig {
|
|
3
|
-
|
|
15
|
+
types?: {
|
|
16
|
+
[key: string]: {
|
|
17
|
+
identifiers?: ELIdentifier[];
|
|
18
|
+
functions?: ELFunction[];
|
|
19
|
+
type?: string;
|
|
20
|
+
info?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
identifiers?: ELIdentifier[];
|
|
24
|
+
functions?: ELFunction[];
|
|
25
|
+
operatorKeywords?: readonly {
|
|
4
26
|
name: string;
|
|
5
27
|
detail?: string;
|
|
6
28
|
info?: string;
|
|
7
29
|
}[];
|
|
8
|
-
functions?: readonly {
|
|
9
|
-
name: string;
|
|
10
|
-
args: string[];
|
|
11
|
-
info?: string;
|
|
12
|
-
}[];
|
|
13
|
-
operatorKeywords?: readonly string[];
|
|
14
30
|
}
|
|
15
31
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
16
32
|
declare const ELLanguage: LRLanguage;
|
|
17
33
|
declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Array<any>): LanguageSupport;
|
|
18
|
-
export { ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
|
34
|
+
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { LRLanguage, LanguageSupport } from "@codemirror/language";
|
|
2
|
+
interface ELIdentifier {
|
|
3
|
+
name: string;
|
|
4
|
+
detail?: string;
|
|
5
|
+
info?: string;
|
|
6
|
+
type?: string[];
|
|
7
|
+
}
|
|
8
|
+
interface ELFunction {
|
|
9
|
+
name: string;
|
|
10
|
+
args: string[];
|
|
11
|
+
info?: string;
|
|
12
|
+
returnType?: string[];
|
|
13
|
+
}
|
|
2
14
|
interface ExpressionLanguageConfig {
|
|
3
|
-
|
|
15
|
+
types?: {
|
|
16
|
+
[key: string]: {
|
|
17
|
+
identifiers?: ELIdentifier[];
|
|
18
|
+
functions?: ELFunction[];
|
|
19
|
+
type?: string;
|
|
20
|
+
info?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
identifiers?: ELIdentifier[];
|
|
24
|
+
functions?: ELFunction[];
|
|
25
|
+
operatorKeywords?: readonly {
|
|
4
26
|
name: string;
|
|
5
27
|
detail?: string;
|
|
6
28
|
info?: string;
|
|
7
29
|
}[];
|
|
8
|
-
functions?: readonly {
|
|
9
|
-
name: string;
|
|
10
|
-
args: string[];
|
|
11
|
-
info?: string;
|
|
12
|
-
}[];
|
|
13
|
-
operatorKeywords?: readonly string[];
|
|
14
30
|
}
|
|
15
31
|
declare const keywordTooltip: (config: ExpressionLanguageConfig) => import("@codemirror/state").Extension;
|
|
16
32
|
declare const ELLanguage: LRLanguage;
|
|
17
33
|
declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Array<any>): LanguageSupport;
|
|
18
|
-
export { ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
|
34
|
+
export { ELIdentifier, ELFunction, ExpressionLanguageConfig, keywordTooltip, ELLanguage, expressionlanguage };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LRParser } from '@lezer/lr';
|
|
2
|
-
import { LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, foldInside,
|
|
2
|
+
import { LRLanguage, indentNodeProp, delimitedIndent, foldNodeProp, foldInside, syntaxTree, LanguageSupport } from '@codemirror/language';
|
|
3
3
|
import { styleTags, tags } from '@lezer/highlight';
|
|
4
4
|
import { linter } from '@codemirror/lint';
|
|
5
5
|
import { hoverTooltip } from '@codemirror/view';
|
|
@@ -7,30 +7,63 @@ import { hoverTooltip } from '@codemirror/view';
|
|
|
7
7
|
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
|
8
8
|
const parser = LRParser.deserialize({
|
|
9
9
|
version: 14,
|
|
10
|
-
states: "
|
|
11
|
-
stateData: "
|
|
12
|
-
goto: "!
|
|
13
|
-
nodeNames: "⚠
|
|
14
|
-
maxTerm:
|
|
15
|
-
nodeProps: [
|
|
16
|
-
["openedBy", 15,"OpeningBracket"],
|
|
17
|
-
["closedBy", 16,"ClosingBracket"]
|
|
18
|
-
],
|
|
10
|
+
states: "'[OVQPOOQtQQO'#C^O!YQQOOO#TQPO'#ChO#[QPO'#CiOVQPO'#CnOOQO'#Cu'#CuOVQPO'#CuO#cQPO,58xOVQPO,58|OVQPO,59UOVQPO,59VO#hQPO,58}O#oQQO,59SOOQO,59S,59SO#vQQO,59TOOQO,59T,59TO$QQQO,59YO$hQQO,59aOOQO1G.d1G.dO$oQQO1G.hO$vQQO1G.pO$}QQO1G.qO%eQQO1G.iOOQO1G.i1G.iOVQPO1G.nOVQPO'#CpO%oQPO1G.oOOQO1G.o1G.oOOQO1G.{1G.{OOQO7+$S7+$SOVQPO7+$[O%wQPO7+$TOOQO7+$T7+$TO&PQQO7+$YO&ZQQO,59[OOQO-E6n-E6nOOQO7+$Z7+$ZO&hQQO<<GvOOQO<<Go<<GoOVQPO'#CqO'OQPO<<GtOOQO<<Gt<<GtO'WQQO,59]OOQO-E6o-E6oOOQOAN=`AN=`OVQPO1G.wO'_QQO7+$c",
|
|
11
|
+
stateData: "'s~OhOS~OTQOWUOXUOYUOZUOcTOkSOmVOpRO~ORWOSWO`ZOaZOkXOrYO~Om[ORiXSiX`iXaiXfiXkiXriXqiXjiXniXliXoiX~Oo^O~PVOj`O~PVOTcO~OlhO~PVOqiO~PtOjlOnjO~PtOfbaqbajbanbalbaoba~PtOlmO~PtOjnO~PtOqoO~PtOf_iq_ij_in_il_io_i~PtOlqOnjO~PtOjuOnjO~OlwOnjO~OnxOozO~PtOjdandalda~PtOf^yq^yj^yn^yl^yo^y~PtOnxOo}O~Oq!OO~PtOneqoeq~PtORSc`YZWTY~",
|
|
12
|
+
goto: "#ijPPkPPP{{PPPP{{{{PP{P!]!gPPP!mmQORSTVXYZ[ijox!OmUORSTVXYZ[ijox!OQk_QpgTtkpQyrR|yQPOQ]RQ_SQaTQbVQdXQeYQfZQg[QriQsjQvoQ{xR!P!O",
|
|
13
|
+
nodeNames: "⚠ Expression ObjectAccess NullSafeMemberOf MemberOf Identifier ArrayAccess FunctionCall Number String Boolean Null Object Array TernaryExpression BinaryExpression OperatorKeyword Operator UnaryExpression UnaryOperator",
|
|
14
|
+
maxTerm: 34,
|
|
19
15
|
skippedNodes: [0],
|
|
20
16
|
repeatNodeCount: 2,
|
|
21
|
-
tokenData: "
|
|
17
|
+
tokenData: "AZ~R!QXY$XYZ$X]^$Xpq$Xqr$jrs%Ruv$|vw&{wx'Txy(xyz(}z{)S{|)[|})c}!O)[!O!P)h!P!Q$|!Q![)p![!],V!^!_$t!_!`,[!`!a$t!a!b,b!c!},u!}#O-W#P#Q-]#Q#R$|#R#S,u#T#U-b#U#V,u#V#W.u#W#X,u#X#Y2Z#Y#Z4u#Z#],u#]#^7V#^#a,u#a#b7n#b#c:S#c#d=c#d#g,u#g#h=z#h#i?w#i#o,u#o#p@w#p#q@|#q#rAU#r#s$|~$^Sh~XY$XYZ$X]^$Xpq$XR$qPaQcP!_!`$tQ$yPaQ!_!`$|Q%ROaQ~%UXOr%Rrs%qs#O%R#O#P%v#P;'S%R;'S;=`&u<%l~%R~O%R~~%q~%vOX~~%yRO;'S%R;'S;=`&S;=`O%R~&VYOr%Rrs%qs#O%R#O#P%v#P;'S%R;'S;=`&u;=`<%l%R<%l~%R~O%R~~%q~&xP;=`<%l%RQ'QPaQvw$|~'WXOw'Twx%qx#O'T#O#P's#P;'S'T;'S;=`(r<%l~'T~O'T~~%q~'vRO;'S'T;'S;=`(P;=`O'T~(SYOw'Twx%qx#O'T#O#P's#P;'S'T;'S;=`(r;=`<%l'T<%l~'T~O'T~~%q~(uP;=`<%l'T~(}Om~~)SOl~Q)XPaQz{$|R)cOaQcP~)hOn~~)mPS~!O!P$|~)uTW~!O!P*U!Q![)p!g!h+U#R#S,P#X#Y+U~*XSO!O*e!P;'S*e;'S;=`+y<%lO*e~*jRW~!Q![*s!g!h+U#X#Y+U~*xSW~!Q![*s!g!h+U#R#S+s#X#Y+U~+XR{|+b}!O+b!Q![+h~+eP!Q![+h~+mQW~!Q![+h#R#S+b~+vP!Q![*s~+|P;=`<%l*e~,SP!Q![)p~,[Oq~Q,_P!_!`$t~,gRr~!O!P,p![!]$|!a!b$|~,uOR~~,zST~!Q![,u!c!},u#R#S,u#T#o,u~-]Ok~~-bOj~~-gUT~!Q![,u!c!},u#R#S,u#T#b,u#b#c-y#c#o,u~.OUT~!Q![,u!c!},u#R#S,u#T#W,u#W#X.b#X#o,u~.iS`~T~!Q![,u!c!},u#R#S,u#T#o,u~.zUT~!Q![,u!c!},u#R#S,u#T#c,u#c#d/^#d#o,u~/cUT~!Q![,u!c!},u#R#S,u#T#b,u#b#c/u#c#o,u~/zUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i0^#i#o,u~0cTT~!Q![,u!c!},u#R#S,u#T#U0r#U#o,u~0wUT~!Q![,u!c!},u#R#S,u#T#],u#]#^1Z#^#o,u~1`UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c1r#c#o,u~1wUT~!Q![,u!c!},u#R#S,u#T#g,u#g#h.b#h#o,u~2`UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c2r#c#o,u~2wUT~!Q![,u!c!},u#R#S,u#T#W,u#W#X3Z#X#o,u~3`UT~!Q![,u!c!},u#R#S,u#T#g,u#g#h3r#h#o,u~3wTT~pq4W!Q![,u!c!},u#R#S,u#T#o,u~4ZP#k#l4^~4aP#]#^4d~4gP#h#i4j~4mP#[#]4p~4uO`~~4zTT~!Q![,u!c!},u#R#S,u#T#U5Z#U#o,u~5`UT~!Q![,u!c!},u#R#S,u#T#`,u#`#a5r#a#o,u~5wUT~!Q![,u!c!},u#R#S,u#T#g,u#g#h6Z#h#o,u~6`UT~!Q![,u!c!},u#R#S,u#T#X,u#X#Y6r#Y#o,u~6ySY~T~!Q![,u!c!},u#R#S,u#T#o,u~7[UT~!Q![,u!c!},u#R#S,u#T#b,u#b#c.b#c#o,u~7sTT~!Q![,u!c!},u#R#S,u#T#U8S#U#o,u~8XUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i8k#i#o,u~8pUT~!Q![,u!c!},u#R#S,u#T#V,u#V#W9S#W#o,u~9XUT~!Q![,u!c!},u#R#S,u#T#[,u#[#]9k#]#o,u~9pUT~!Q![,u!c!},u#R#S,u#T#X,u#X#Y1r#Y#o,u~:XWT~!Q![,u!c!},u#R#S,u#T#c,u#c#d:q#d#i,u#i#j<O#j#o,u~:vUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i;Y#i#o,u~;cTcP`~T~pq;r!Q![,u!c!},u#R#S,u#T#o,u~;uP#]#^;x~;{P#b#c4p~<TUT~!Q![,u!c!},u#R#S,u#T#`,u#`#a<g#a#o,u~<lUT~!Q![,u!c!},u#R#S,u#T#`,u#`#a=O#a#o,u~=VSZ~T~!Q![,u!c!},u#R#S,u#T#o,u~=hUT~!Q![,u!c!},u#R#S,u#T#f,u#f#g.b#g#o,u~>PUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i>c#i#o,u~>hTT~!Q![,u!c!},u#R#S,u#T#U>w#U#o,u~>|UT~!Q![,u!c!},u#R#S,u#T#f,u#f#g?`#g#o,u~?eUT~!Q![,u!c!},u#R#S,u#T#h,u#h#i3Z#i#o,u~?|UT~!Q![,u!c!},u#R#S,u#T#f,u#f#g@`#g#o,u~@eUT~!Q![,u!c!},u#R#S,u#T#i,u#i#j6Z#j#o,u~@|Op~QARPaQ#p#q$|~AZOo~",
|
|
22
18
|
tokenizers: [0, 1],
|
|
23
|
-
topRules: {"
|
|
24
|
-
tokenPrec:
|
|
19
|
+
topRules: {"Expression":[0,1]},
|
|
20
|
+
tokenPrec: 301
|
|
25
21
|
});
|
|
26
22
|
|
|
27
|
-
const identifier = /^[a-zA-Z_]+[a-zA-Z_0-9]*$/;
|
|
28
23
|
const isFunction = (identifier, config) => { var _a; return (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(fn => fn.name === identifier); };
|
|
29
24
|
const isVariable = (identifier, config) => { var _a; return (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.find(variable => variable.name === identifier); };
|
|
25
|
+
const autocompleteFunction = (x) => { var _a, _b, _c; return ({ label: `${x.name}(${((_a = x.args) === null || _a === void 0 ? void 0 : _a.join(',')) || ''})`, apply: `${x.name}(${!((_b = x.args) === null || _b === void 0 ? void 0 : _b.length) ? ')' : ''}`, detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'), info: x.info, type: "function" }); };
|
|
26
|
+
const autocompleteIdentifier = (x) => { var _a; return ({ label: x.name, apply: x.name, info: x.info, detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')), type: 'variable' }); };
|
|
30
27
|
const expressionLanguageLinter = (config) => linter(view => {
|
|
31
28
|
let diagnostics = [];
|
|
29
|
+
let previousNode = null;
|
|
32
30
|
syntaxTree(view.state).cursor().iterate(node => {
|
|
31
|
+
var _a, _b, _c, _d, _e;
|
|
32
|
+
if (((_a = node.node.parent) === null || _a === void 0 ? void 0 : _a.name) == 'ObjectAccess' && ((_b = node.node.parent) === null || _b === void 0 ? void 0 : _b.firstChild) && node.name == "Identifier" && node.node.prevSibling) {
|
|
33
|
+
const leftArgument = node.node.parent.firstChild.node;
|
|
34
|
+
const types = resolveTypes(view.state, leftArgument, config, true);
|
|
35
|
+
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
36
|
+
if (((_d = (_c = node.node.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.name) === 'FunctionCall') {
|
|
37
|
+
if (!Array.from(types).find(type => { var _a, _b, _c; return (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === identifier); })) {
|
|
38
|
+
diagnostics.push({
|
|
39
|
+
from: node.from,
|
|
40
|
+
to: node.to,
|
|
41
|
+
severity: 'error',
|
|
42
|
+
message: `Method '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (types.size > 0) {
|
|
47
|
+
if (!Array.from(types).find(type => { var _a, _b, _c; return (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === identifier); })) {
|
|
48
|
+
diagnostics.push({
|
|
49
|
+
from: node.from,
|
|
50
|
+
to: node.to,
|
|
51
|
+
severity: 'warning',
|
|
52
|
+
message: `Property '${identifier}' not found in ${Array.from(types).join('|')}`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
33
58
|
if (node.name == "Identifier") {
|
|
59
|
+
if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.name) == "Identifier" && !['Array', 'FunctionCall'].includes(((_e = node.node.parent) === null || _e === void 0 ? void 0 : _e.name) || '')) {
|
|
60
|
+
diagnostics.push({
|
|
61
|
+
from: node.from,
|
|
62
|
+
to: node.to,
|
|
63
|
+
severity: 'error',
|
|
64
|
+
message: `Unexpected identifier after another identifier`,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
34
67
|
const identifier = view.state.sliceDoc(node.from, node.to);
|
|
35
68
|
if (!isFunction(identifier, config) && !isVariable(identifier, config)) {
|
|
36
69
|
diagnostics.push({
|
|
@@ -41,28 +74,40 @@ const expressionLanguageLinter = (config) => linter(view => {
|
|
|
41
74
|
});
|
|
42
75
|
}
|
|
43
76
|
}
|
|
77
|
+
previousNode = node.node;
|
|
44
78
|
});
|
|
45
79
|
return diagnostics;
|
|
46
80
|
});
|
|
47
81
|
const keywordTooltip = (config) => hoverTooltip((view, pos, side) => {
|
|
48
|
-
var _a, _b;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
while (start > from && /\w/.test(text[start - from - 1]))
|
|
52
|
-
start--;
|
|
53
|
-
while (end < to && /\w/.test(text[end - from]))
|
|
54
|
-
end++;
|
|
55
|
-
if (start == pos && side < 0 || end == pos && side > 0) {
|
|
82
|
+
var _a, _b, _c, _d, _e, _f;
|
|
83
|
+
const tree = syntaxTree(view.state).resolveInner(pos, side);
|
|
84
|
+
if (tree.name !== 'Identifier') {
|
|
56
85
|
return null;
|
|
57
86
|
}
|
|
58
|
-
const
|
|
59
|
-
|
|
87
|
+
const skipEmpty = (x) => x;
|
|
88
|
+
let info;
|
|
89
|
+
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.firstChild) && ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) === 'ObjectAccess' && tree.prevSibling) {
|
|
90
|
+
const node = tree.parent.firstChild;
|
|
91
|
+
const types = resolveTypes(view.state, node, config, true);
|
|
92
|
+
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
93
|
+
info = [
|
|
94
|
+
...Array.from(types).map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
95
|
+
...Array.from(types).map(type => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.types) === null || _a === void 0 ? void 0 : _a[type]) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info; }).filter(skipEmpty),
|
|
96
|
+
].join('\n');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const name = view.state.sliceDoc(tree.from, tree.to);
|
|
100
|
+
info = [
|
|
101
|
+
...[(_d = (_c = config.identifiers) === null || _c === void 0 ? void 0 : _c.find(x => x.name === name)) === null || _d === void 0 ? void 0 : _d.info].filter(skipEmpty),
|
|
102
|
+
...[(_f = (_e = config.functions) === null || _e === void 0 ? void 0 : _e.find(x => x.name === name)) === null || _f === void 0 ? void 0 : _f.info].filter(skipEmpty),
|
|
103
|
+
].join('\n');
|
|
104
|
+
}
|
|
60
105
|
if (!info) {
|
|
61
106
|
return null;
|
|
62
107
|
}
|
|
63
108
|
return {
|
|
64
|
-
pos:
|
|
65
|
-
end,
|
|
109
|
+
pos: tree.from,
|
|
110
|
+
end: tree.to,
|
|
66
111
|
above: true,
|
|
67
112
|
create(view) {
|
|
68
113
|
let dom = document.createElement("div");
|
|
@@ -86,62 +131,124 @@ const ELLanguage = LRLanguage.define({
|
|
|
86
131
|
Boolean: tags.bool,
|
|
87
132
|
String: tags.string,
|
|
88
133
|
Number: tags.number,
|
|
89
|
-
|
|
90
|
-
|
|
134
|
+
'(': tags.paren,
|
|
135
|
+
')': tags.paren,
|
|
91
136
|
'[': tags.squareBracket,
|
|
92
137
|
']': tags.squareBracket,
|
|
93
138
|
OperatorKeyword: tags.operatorKeyword,
|
|
94
139
|
Operator: tags.operator,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Punctuation: tags.punctuation,
|
|
140
|
+
MemberOf: tags.operator,
|
|
141
|
+
NullSafeMemberOf: tags.operator,
|
|
98
142
|
})
|
|
99
143
|
]
|
|
100
144
|
}),
|
|
101
145
|
languageData: {}
|
|
102
146
|
});
|
|
103
|
-
function completeOperatorKeyword(state, config, tree, from, to) {
|
|
147
|
+
function completeOperatorKeyword(state, config, tree, from, to, explicit) {
|
|
104
148
|
var _a, _b;
|
|
105
149
|
const text = state.sliceDoc(from, to);
|
|
106
150
|
return {
|
|
107
151
|
from,
|
|
108
152
|
to,
|
|
109
|
-
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(
|
|
110
|
-
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(
|
|
153
|
+
options: (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.startsWith(text)).map(({ name, info, detail }) => ({ label: name, apply: `${name} `, info, detail, type: "keyword" }))) !== null && _b !== void 0 ? _b : [],
|
|
154
|
+
validFor: (text) => { var _a, _b; return (_b = (_a = config.operatorKeywords) === null || _a === void 0 ? void 0 : _a.some(({ name }) => explicit || name.startsWith(text))) !== null && _b !== void 0 ? _b : false; },
|
|
111
155
|
};
|
|
112
156
|
}
|
|
113
|
-
function completeIdentifier(state, config, tree, from, to) {
|
|
114
|
-
var _a, _b, _c, _d
|
|
115
|
-
const text = state.sliceDoc(from, to);
|
|
116
|
-
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => name.startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
117
|
-
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => name.startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
157
|
+
function completeIdentifier(state, config, tree, from, to, explicit) {
|
|
158
|
+
var _a, _b, _c, _d;
|
|
159
|
+
const text = state.sliceDoc(from, to).toLowerCase();
|
|
160
|
+
const identifiers = (_b = (_a = config.identifiers) === null || _a === void 0 ? void 0 : _a.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _b !== void 0 ? _b : [];
|
|
161
|
+
const functions = (_d = (_c = config.functions) === null || _c === void 0 ? void 0 : _c.filter(({ name }) => explicit || name.toLowerCase().startsWith(text))) !== null && _d !== void 0 ? _d : [];
|
|
162
|
+
return {
|
|
163
|
+
from,
|
|
164
|
+
to,
|
|
165
|
+
options: [...(identifiers.map(autocompleteIdentifier)), ...(functions.map(autocompleteFunction))],
|
|
166
|
+
// validFor: identifier,
|
|
167
|
+
filter: false,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function resolveTypes(state, node, config, matchExact) {
|
|
171
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
172
|
+
let types = new Set();
|
|
173
|
+
if (node.name === 'FunctionCall' && node.firstChild && node.lastChild) {
|
|
174
|
+
resolveTypes(state, node.firstChild, config, matchExact).forEach(x => types.add(x));
|
|
175
|
+
}
|
|
176
|
+
else if (node.name === 'Identifier') {
|
|
177
|
+
const varName = state.sliceDoc(node.from, node.to) || '';
|
|
178
|
+
(_c = (_b = (_a = config.functions) === null || _a === void 0 ? void 0 : _a.find(x => x.name == varName)) === null || _b === void 0 ? void 0 : _b.returnType) === null || _c === void 0 ? void 0 : _c.forEach(x => types.add(x));
|
|
179
|
+
(_f = (_e = (_d = config.identifiers) === null || _d === void 0 ? void 0 : _d.find(x => x.name == varName)) === null || _e === void 0 ? void 0 : _e.type) === null || _f === void 0 ? void 0 : _f.forEach(x => types.add(x));
|
|
180
|
+
}
|
|
181
|
+
else if (node.name === 'ObjectAccess' && node.firstChild && ((_g = node.lastChild) === null || _g === void 0 ? void 0 : _g.name) === 'Identifier') {
|
|
182
|
+
const baseTypes = resolveTypes(state, node.firstChild, config, matchExact);
|
|
183
|
+
const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
|
|
184
|
+
for (const baseType of baseTypes) {
|
|
185
|
+
const type = (_h = config.types) === null || _h === void 0 ? void 0 : _h[baseType];
|
|
186
|
+
(_k = (_j = type === null || type === void 0 ? void 0 : type.functions) === null || _j === void 0 ? void 0 : _j.filter(x => matchExact ? x.name === varName : x.name.startsWith(varName))) === null || _k === void 0 ? void 0 : _k.forEach(def => (def.returnType || ['any']).forEach(x => types.add(x)));
|
|
187
|
+
(_m = (_l = type === null || type === void 0 ? void 0 : type.identifiers) === null || _l === void 0 ? void 0 : _l.filter(x => matchExact ? x.name === varName : x.name.startsWith(varName))) === null || _m === void 0 ? void 0 : _m.forEach(def => (def.type || ['any']).forEach(x => types.add(x)));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (types.size === 0) {
|
|
191
|
+
types.add('any');
|
|
192
|
+
}
|
|
193
|
+
return types;
|
|
194
|
+
}
|
|
195
|
+
function completeMember(state, config, tree, from, to, explicit) {
|
|
196
|
+
var _a, _b, _c, _d;
|
|
197
|
+
if (((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.name) != 'ObjectAccess' || !tree.parent.firstChild) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
const types = resolveTypes(state, tree.parent.firstChild.node, config, false);
|
|
201
|
+
if (!(types === null || types === void 0 ? void 0 : types.size)) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const varName = state.sliceDoc(from, to);
|
|
205
|
+
let options = [];
|
|
206
|
+
for (const type of types) {
|
|
207
|
+
const typeDeclaration = (_b = config.types) === null || _b === void 0 ? void 0 : _b[type];
|
|
208
|
+
options.push(...(((_c = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _c === void 0 ? void 0 : _c.filter(x => x.name.startsWith(varName)).map(autocompleteIdentifier)) || []), ...(((_d = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _d === void 0 ? void 0 : _d.filter(x => x.name.startsWith(varName)).map(autocompleteFunction)) || []));
|
|
209
|
+
}
|
|
118
210
|
return {
|
|
119
211
|
from,
|
|
120
212
|
to,
|
|
121
|
-
options
|
|
122
|
-
|
|
123
|
-
...((_f = functions.map(({ name, args = [], info }) => ({ label: name, detail: `(${args.join(',')})`, apply: `${name}(${args.length == 0 ? ')' : ''}`, info, type: "function" }))) !== null && _f !== void 0 ? _f : []),
|
|
124
|
-
],
|
|
125
|
-
validFor: identifier,
|
|
213
|
+
options,
|
|
214
|
+
filter: false,
|
|
126
215
|
};
|
|
127
216
|
}
|
|
128
217
|
function expressionLanguageCompletionFor(config, context) {
|
|
129
|
-
|
|
130
|
-
|
|
218
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
219
|
+
const { state, pos, explicit } = context;
|
|
220
|
+
const tree = syntaxTree(state).resolveInner(pos, -1);
|
|
221
|
+
const isOperator = (node) => node && ['Operator', 'OperatorKeyword'].includes(node.name);
|
|
222
|
+
const isIdentifier = (node) => (node === null || node === void 0 ? void 0 : node.name) === 'Identifier';
|
|
223
|
+
const prevNode = ((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.node.type.isError) ? tree.parent.prevSibling : tree.prevSibling;
|
|
131
224
|
if (tree.name == 'String') {
|
|
132
225
|
return null;
|
|
133
226
|
}
|
|
134
|
-
if (tree.
|
|
135
|
-
return
|
|
227
|
+
if (((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.name) == 'ObjectAccess' && ['ObjectAccess', 'ArrayAccess', 'Identifier', 'FunctionCall'].includes(((_c = tree.parent.firstChild) === null || _c === void 0 ? void 0 : _c.name) || '')) {
|
|
228
|
+
return completeMember(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos);
|
|
136
229
|
}
|
|
137
|
-
|
|
138
|
-
|
|
230
|
+
// No idea what's going on here, just added conditions until all the tests passed :)
|
|
231
|
+
if (prevNode && !isOperator(prevNode.node) && (((_d = tree.parent) === null || _d === void 0 ? void 0 : _d.node.type.isError) || ((_e = tree.node.parent) === null || _e === void 0 ? void 0 : _e.name) === 'BinaryExpression') || (tree.name === 'Expression' && !((_g = (_f = tree.lastChild) === null || _f === void 0 ? void 0 : _f.type) === null || _g === void 0 ? void 0 : _g.isError) && !isOperator((_h = tree.lastChild) === null || _h === void 0 ? void 0 : _h.node))) {
|
|
232
|
+
return completeOperatorKeyword(state, config, tree, tree.name !== 'Expression' ? tree.from : pos, pos, explicit);
|
|
233
|
+
}
|
|
234
|
+
if (tree.name === 'Expression' || isIdentifier(tree.node) || (tree.name === 'BinaryExpression' && isOperator((_k = (_j = tree.lastChild) === null || _j === void 0 ? void 0 : _j.prevSibling) === null || _k === void 0 ? void 0 : _k.node) && explicit)) {
|
|
235
|
+
return completeIdentifier(state, config, tree, isIdentifier(tree.node) ? tree.from : pos, pos, explicit);
|
|
139
236
|
}
|
|
140
237
|
return null;
|
|
141
238
|
}
|
|
142
239
|
function expressionLanguageCompletionSourceWith(config) {
|
|
143
240
|
var _a;
|
|
144
|
-
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
241
|
+
(_a = config.operatorKeywords) !== null && _a !== void 0 ? _a : (config.operatorKeywords = [
|
|
242
|
+
{ name: 'starts with' },
|
|
243
|
+
{ name: 'ends with' },
|
|
244
|
+
{ name: 'contains' },
|
|
245
|
+
{ name: 'matches' },
|
|
246
|
+
{ name: 'not in' },
|
|
247
|
+
{ name: 'in' },
|
|
248
|
+
{ name: 'not' },
|
|
249
|
+
{ name: 'or' },
|
|
250
|
+
{ name: 'and' },
|
|
251
|
+
]);
|
|
145
252
|
return (context) => expressionLanguageCompletionFor(config, context);
|
|
146
253
|
}
|
|
147
254
|
function expressionlanguage(config = {}, extensions = []) {
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"description": "Symfony Expression Language language support for CodeMirror",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"test": "mocha test/test.js test/test-complete.js",
|
|
6
|
+
"dev": "rollup -c -w",
|
|
6
7
|
"prepare": "rollup -c"
|
|
7
8
|
},
|
|
8
9
|
"type": "module",
|
|
@@ -41,5 +42,5 @@
|
|
|
41
42
|
"access": "public",
|
|
42
43
|
"registry": "https://registry.npmjs.org/"
|
|
43
44
|
},
|
|
44
|
-
"version": "0.
|
|
45
|
+
"version": "0.4.0"
|
|
45
46
|
}
|