@valtzu/codemirror-lang-el 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ 1.2
5
+ ---
6
+
7
+ * Add support for typed arrays
8
+ * Add Codex CLI and Docker Compose integration
9
+
10
+ 1.1
11
+ ---
12
+
13
+ * Lint right-side argument type for `in` operator
14
+ * Fix `undefined` in completion keyword tooltip (#19)
15
+
4
16
  1.0
5
17
  ---
6
18
 
package/README.md CHANGED
@@ -36,6 +36,16 @@
36
36
 
37
37
  ### Installation
38
38
 
39
+ #### Web Component
40
+
41
+ If you're using Bootstrap UI, check the [Web Component](https://github.com/valtzu/symfony-expression-editor) to hide all CodeMirror stuff.
42
+
43
+ ```html
44
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
45
+ <script type="module" src="https://esm.sh/symfony-expression-editor"></script>
46
+ <textarea class="form-control" is="expression-editor" rows="1">'foobar' starts with 'foo'</textarea>
47
+ ```
48
+
39
49
  #### Symfony AssetMapper
40
50
 
41
51
  ```
@@ -62,7 +72,7 @@ See [CONFIGURATION.md](CONFIGURATION.md)
62
72
 
63
73
  ### Example
64
74
 
65
- [Live demo](https://jsfiddle.net/turse2xq/)
75
+ [Live demo](https://jsfiddle.net/32ybaetz/)
66
76
 
67
77
  ```html
68
78
  <div id="editor"></div>
@@ -108,6 +118,15 @@ See [CONFIGURATION.md](CONFIGURATION.md)
108
118
  </script>
109
119
  ```
110
120
 
121
+ ### Using OpenAI codex
122
+
123
+ Create `.env` file with
124
+ ```
125
+ OPENAI_API_KEY="..."
126
+ ```
127
+
128
+ Then use `docker compose run --rm codex` to develop with AI.
129
+
111
130
  ### Contributing
112
131
 
113
132
  Contributions are welcome.
package/dist/index.cjs CHANGED
@@ -46,6 +46,8 @@ exports.ELScalar = void 0;
46
46
  ELScalar["String"] = "string";
47
47
  /** Equivalent to PHP `null` */
48
48
  ELScalar["Null"] = "null";
49
+ /** Equivalent to PHP `array` */
50
+ ELScalar["Array"] = "array";
49
51
  /** Equivalent to PHP `mixed` */
50
52
  ELScalar["Any"] = "any";
51
53
  })(exports.ELScalar || (exports.ELScalar = {}));
@@ -77,9 +79,12 @@ const createInfoElement = (html) => {
77
79
  return dom;
78
80
  };
79
81
  const createCompletionInfoElement = (html) => {
82
+ if (!html) {
83
+ return undefined;
84
+ }
80
85
  const dom = document.createElement("div");
81
86
  dom.innerHTML = html;
82
- return dom;
87
+ return { dom };
83
88
  };
84
89
  function resolveFunctionDefinition(node, state, config) {
85
90
  var _a;
@@ -149,6 +154,18 @@ function resolveTypes(state, node, config) {
149
154
  (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
150
155
  });
151
156
  }
157
+ // Array indexing: for typed arrays (e.g. Foo[]) return element type, for generic arrays return any
158
+ else if (node.type.is(ArrayAccess) && node.firstChild) {
159
+ const left = node.firstChild.node;
160
+ resolveTypes(state, left, config).forEach(baseType => {
161
+ if (baseType.endsWith('[]')) {
162
+ types.add(baseType.slice(0, -2));
163
+ }
164
+ else if (baseType === exports.ELScalar.Array) {
165
+ types.add(exports.ELScalar.Any);
166
+ }
167
+ });
168
+ }
152
169
  else if (node.type.is(Application) && node.firstChild) {
153
170
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
154
171
  }
@@ -282,6 +299,19 @@ const expressionLanguageLinterSource = (state) => {
282
299
  diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} <code>${identifier}</code> not found` });
283
300
  }
284
301
  break;
302
+ case BinaryExpression:
303
+ const operatorNode = node.node.getChild(OperatorKeyword);
304
+ if (operatorNode) {
305
+ const operator = state.sliceDoc(operatorNode.from, operatorNode.to);
306
+ if (operator === 'in') {
307
+ const rightArgument = node.node.lastChild;
308
+ const types = resolveTypes(state, rightArgument, config);
309
+ if (!types.has(exports.ELScalar.Array)) {
310
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>${exports.ELScalar.Array}</code> expected, got <code>${[...types].join('|')}</code>` });
311
+ }
312
+ }
313
+ }
314
+ break;
285
315
  }
286
316
  if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
287
317
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
@@ -313,7 +343,7 @@ const autocompleteFunction = (x) => {
313
343
  view.dispatch(Object.assign(Object.assign({}, autocomplete.insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ? 1 : 2) } }));
314
344
  },
315
345
  detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
316
- info: () => ({ dom: createCompletionInfoElement(x.info) }),
346
+ info: () => createCompletionInfoElement(x.info),
317
347
  type: "function",
318
348
  });
319
349
  };
@@ -322,7 +352,7 @@ const autocompleteIdentifier = (x) => {
322
352
  return ({
323
353
  label: x.name,
324
354
  apply: x.name,
325
- info: () => ({ dom: createCompletionInfoElement(x.info) }),
355
+ info: () => createCompletionInfoElement(x.info),
326
356
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
327
357
  type: 'variable',
328
358
  });
@@ -335,7 +365,7 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
335
365
  options: (_a = keywords.map(({ name, info, detail }) => ({
336
366
  label: name,
337
367
  apply: `${name} `,
338
- info: () => ({ dom: createCompletionInfoElement(info) }),
368
+ info: () => createCompletionInfoElement(info),
339
369
  detail,
340
370
  type: "keyword"
341
371
  }))) !== null && _a !== void 0 ? _a : [],
package/dist/index.d.cts CHANGED
@@ -66,6 +66,8 @@ declare enum ELScalar {
66
66
  String = "string",
67
67
  /** Equivalent to PHP `null` */
68
68
  Null = "null",
69
+ /** Equivalent to PHP `array` */
70
+ Array = "array",
69
71
  /** Equivalent to PHP `mixed` */
70
72
  Any = "any"
71
73
  }
@@ -78,14 +80,18 @@ declare function expressionLanguageCompletion(context: CompletionContext): Compl
78
80
 
79
81
  declare const complete_d_expressionLanguageCompletion: typeof expressionLanguageCompletion;
80
82
  declare namespace complete_d {
81
- export { complete_d_expressionLanguageCompletion as expressionLanguageCompletion };
83
+ export {
84
+ complete_d_expressionLanguageCompletion as expressionLanguageCompletion,
85
+ };
82
86
  }
83
87
 
84
88
  declare const expressionLanguageLinter: _codemirror_state.Extension;
85
89
 
86
90
  declare const linter_d_expressionLanguageLinter: typeof expressionLanguageLinter;
87
91
  declare namespace linter_d {
88
- export { linter_d_expressionLanguageLinter as expressionLanguageLinter };
92
+ export {
93
+ linter_d_expressionLanguageLinter as expressionLanguageLinter,
94
+ };
89
95
  }
90
96
 
91
97
  declare const Function: number;
@@ -94,7 +100,9 @@ declare const Property: number;
94
100
  declare const Variable: number;
95
101
 
96
102
  declare const createInfoElement: (html: string) => HTMLDivElement;
97
- declare const createCompletionInfoElement: (html: string) => HTMLDivElement;
103
+ declare const createCompletionInfoElement: (html: string) => {
104
+ dom: HTMLDivElement;
105
+ } | undefined;
98
106
  declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
99
107
  declare const resolveIdentifier: (nodeTypeId: typeof Method | typeof Property | typeof Function | typeof Variable, identifier?: string, config?: {
100
108
  identifiers?: ELIdentifier[];
@@ -112,7 +120,15 @@ declare const utils_d_resolveFunctionDefinition: typeof resolveFunctionDefinitio
112
120
  declare const utils_d_resolveIdentifier: typeof resolveIdentifier;
113
121
  declare const utils_d_resolveTypes: typeof resolveTypes;
114
122
  declare namespace utils_d {
115
- export { utils_d_createCompletionInfoElement as createCompletionInfoElement, utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
123
+ export {
124
+ utils_d_createCompletionInfoElement as createCompletionInfoElement,
125
+ utils_d_createInfoElement as createInfoElement,
126
+ utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig,
127
+ utils_d_keywords as keywords,
128
+ utils_d_resolveFunctionDefinition as resolveFunctionDefinition,
129
+ utils_d_resolveIdentifier as resolveIdentifier,
130
+ utils_d_resolveTypes as resolveTypes,
131
+ };
116
132
  }
117
133
 
118
134
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
@@ -123,10 +139,14 @@ declare const keywordTooltip: _codemirror_state.Extension & {
123
139
  declare const tooltip_d_cursorTooltipField: typeof cursorTooltipField;
124
140
  declare const tooltip_d_keywordTooltip: typeof keywordTooltip;
125
141
  declare namespace tooltip_d {
126
- export { tooltip_d_cursorTooltipField as cursorTooltipField, tooltip_d_keywordTooltip as keywordTooltip };
142
+ export {
143
+ tooltip_d_cursorTooltipField as cursorTooltipField,
144
+ tooltip_d_keywordTooltip as keywordTooltip,
145
+ };
127
146
  }
128
147
 
129
148
  declare const ELLanguage: LRLanguage;
130
149
  declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Extension[]): LanguageSupport;
131
150
 
132
- export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ELTypeName, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
151
+ export { ELLanguage, ELScalar, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
152
+ export type { ELFunction, ELIdentifier, ELKeyword, ELParameter, ELType, ELTypeName, ExpressionLanguageConfig };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,8 @@ declare enum ELScalar {
66
66
  String = "string",
67
67
  /** Equivalent to PHP `null` */
68
68
  Null = "null",
69
+ /** Equivalent to PHP `array` */
70
+ Array = "array",
69
71
  /** Equivalent to PHP `mixed` */
70
72
  Any = "any"
71
73
  }
@@ -78,14 +80,18 @@ declare function expressionLanguageCompletion(context: CompletionContext): Compl
78
80
 
79
81
  declare const complete_d_expressionLanguageCompletion: typeof expressionLanguageCompletion;
80
82
  declare namespace complete_d {
81
- export { complete_d_expressionLanguageCompletion as expressionLanguageCompletion };
83
+ export {
84
+ complete_d_expressionLanguageCompletion as expressionLanguageCompletion,
85
+ };
82
86
  }
83
87
 
84
88
  declare const expressionLanguageLinter: _codemirror_state.Extension;
85
89
 
86
90
  declare const linter_d_expressionLanguageLinter: typeof expressionLanguageLinter;
87
91
  declare namespace linter_d {
88
- export { linter_d_expressionLanguageLinter as expressionLanguageLinter };
92
+ export {
93
+ linter_d_expressionLanguageLinter as expressionLanguageLinter,
94
+ };
89
95
  }
90
96
 
91
97
  declare const Function: number;
@@ -94,7 +100,9 @@ declare const Property: number;
94
100
  declare const Variable: number;
95
101
 
96
102
  declare const createInfoElement: (html: string) => HTMLDivElement;
97
- declare const createCompletionInfoElement: (html: string) => HTMLDivElement;
103
+ declare const createCompletionInfoElement: (html: string) => {
104
+ dom: HTMLDivElement;
105
+ } | undefined;
98
106
  declare function resolveFunctionDefinition(node: SyntaxNode | null, state: EditorState, config: ExpressionLanguageConfig): ELFunction | undefined;
99
107
  declare const resolveIdentifier: (nodeTypeId: typeof Method | typeof Property | typeof Function | typeof Variable, identifier?: string, config?: {
100
108
  identifiers?: ELIdentifier[];
@@ -112,7 +120,15 @@ declare const utils_d_resolveFunctionDefinition: typeof resolveFunctionDefinitio
112
120
  declare const utils_d_resolveIdentifier: typeof resolveIdentifier;
113
121
  declare const utils_d_resolveTypes: typeof resolveTypes;
114
122
  declare namespace utils_d {
115
- export { utils_d_createCompletionInfoElement as createCompletionInfoElement, utils_d_createInfoElement as createInfoElement, utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig, utils_d_keywords as keywords, utils_d_resolveFunctionDefinition as resolveFunctionDefinition, utils_d_resolveIdentifier as resolveIdentifier, utils_d_resolveTypes as resolveTypes };
123
+ export {
124
+ utils_d_createCompletionInfoElement as createCompletionInfoElement,
125
+ utils_d_createInfoElement as createInfoElement,
126
+ utils_d_getExpressionLanguageConfig as getExpressionLanguageConfig,
127
+ utils_d_keywords as keywords,
128
+ utils_d_resolveFunctionDefinition as resolveFunctionDefinition,
129
+ utils_d_resolveIdentifier as resolveIdentifier,
130
+ utils_d_resolveTypes as resolveTypes,
131
+ };
116
132
  }
117
133
 
118
134
  declare const cursorTooltipField: StateField<readonly Tooltip[]>;
@@ -123,10 +139,14 @@ declare const keywordTooltip: _codemirror_state.Extension & {
123
139
  declare const tooltip_d_cursorTooltipField: typeof cursorTooltipField;
124
140
  declare const tooltip_d_keywordTooltip: typeof keywordTooltip;
125
141
  declare namespace tooltip_d {
126
- export { tooltip_d_cursorTooltipField as cursorTooltipField, tooltip_d_keywordTooltip as keywordTooltip };
142
+ export {
143
+ tooltip_d_cursorTooltipField as cursorTooltipField,
144
+ tooltip_d_keywordTooltip as keywordTooltip,
145
+ };
127
146
  }
128
147
 
129
148
  declare const ELLanguage: LRLanguage;
130
149
  declare function expressionlanguage(config?: ExpressionLanguageConfig, extensions?: Extension[]): LanguageSupport;
131
150
 
132
- export { type ELFunction, type ELIdentifier, type ELKeyword, ELLanguage, type ELParameter, ELScalar, type ELType, type ELTypeName, type ExpressionLanguageConfig, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
151
+ export { ELLanguage, ELScalar, complete_d as _complete, linter_d as _linter, tooltip_d as _tooltip, utils_d as _utils, expressionlanguage };
152
+ export type { ELFunction, ELIdentifier, ELKeyword, ELParameter, ELType, ELTypeName, ExpressionLanguageConfig };
package/dist/index.js CHANGED
@@ -43,6 +43,8 @@ var ELScalar = /*@__PURE__*/(function (ELScalar) {
43
43
  ELScalar["String"] = "string";
44
44
  /** Equivalent to PHP `null` */
45
45
  ELScalar["Null"] = "null";
46
+ /** Equivalent to PHP `array` */
47
+ ELScalar["Array"] = "array";
46
48
  /** Equivalent to PHP `mixed` */
47
49
  ELScalar["Any"] = "any";
48
50
  return ELScalar})(ELScalar || (ELScalar = {}));
@@ -74,9 +76,12 @@ const createInfoElement = (html) => {
74
76
  return dom;
75
77
  };
76
78
  const createCompletionInfoElement = (html) => {
79
+ if (!html) {
80
+ return undefined;
81
+ }
77
82
  const dom = document.createElement("div");
78
83
  dom.innerHTML = html;
79
- return dom;
84
+ return { dom };
80
85
  };
81
86
  function resolveFunctionDefinition(node, state, config) {
82
87
  var _a;
@@ -146,6 +151,18 @@ function resolveTypes(state, node, config) {
146
151
  (_d = (_c = resolveIdentifier((_a = node.lastChild) === null || _a === void 0 ? void 0 : _a.type.id, varName, (_b = config.types) === null || _b === void 0 ? void 0 : _b[baseType])) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
147
152
  });
148
153
  }
154
+ // Array indexing: for typed arrays (e.g. Foo[]) return element type, for generic arrays return any
155
+ else if (node.type.is(ArrayAccess) && node.firstChild) {
156
+ const left = node.firstChild.node;
157
+ resolveTypes(state, left, config).forEach(baseType => {
158
+ if (baseType.endsWith('[]')) {
159
+ types.add(baseType.slice(0, -2));
160
+ }
161
+ else if (baseType === ELScalar.Array) {
162
+ types.add(ELScalar.Any);
163
+ }
164
+ });
165
+ }
149
166
  else if (node.type.is(Application) && node.firstChild) {
150
167
  resolveTypes(state, node.firstChild, config).forEach(x => types.add(x));
151
168
  }
@@ -279,6 +296,19 @@ const expressionLanguageLinterSource = (state) => {
279
296
  diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} <code>${identifier}</code> not found` });
280
297
  }
281
298
  break;
299
+ case BinaryExpression:
300
+ const operatorNode = node.node.getChild(OperatorKeyword);
301
+ if (operatorNode) {
302
+ const operator = state.sliceDoc(operatorNode.from, operatorNode.to);
303
+ if (operator === 'in') {
304
+ const rightArgument = node.node.lastChild;
305
+ const types = resolveTypes(state, rightArgument, config);
306
+ if (!types.has(ELScalar.Array)) {
307
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>${ELScalar.Array}</code> expected, got <code>${[...types].join('|')}</code>` });
308
+ }
309
+ }
310
+ }
311
+ break;
282
312
  }
283
313
  if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
284
314
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
@@ -310,7 +340,7 @@ const autocompleteFunction = (x) => {
310
340
  view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, `${x.name}()`, from, to)), { selection: { anchor: from + x.name.length + (((_b = (_a = x.args) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ? 1 : 2) } }));
311
341
  },
312
342
  detail: (_c = x.returnType) === null || _c === void 0 ? void 0 : _c.join('|'),
313
- info: () => ({ dom: createCompletionInfoElement(x.info) }),
343
+ info: () => createCompletionInfoElement(x.info),
314
344
  type: "function",
315
345
  });
316
346
  };
@@ -319,7 +349,7 @@ const autocompleteIdentifier = (x) => {
319
349
  return ({
320
350
  label: x.name,
321
351
  apply: x.name,
322
- info: () => ({ dom: createCompletionInfoElement(x.info) }),
352
+ info: () => createCompletionInfoElement(x.info),
323
353
  detail: x.detail || ((_a = x.type) === null || _a === void 0 ? void 0 : _a.join('|')),
324
354
  type: 'variable',
325
355
  });
@@ -332,7 +362,7 @@ function completeOperatorKeyword(state, config, tree, from, to, explicit) {
332
362
  options: (_a = keywords.map(({ name, info, detail }) => ({
333
363
  label: name,
334
364
  apply: `${name} `,
335
- info: () => ({ dom: createCompletionInfoElement(info) }),
365
+ info: () => createCompletionInfoElement(info),
336
366
  detail,
337
367
  type: "keyword"
338
368
  }))) !== null && _a !== void 0 ? _a : [],
package/package.json CHANGED
@@ -39,5 +39,5 @@
39
39
  "access": "public",
40
40
  "registry": "https://registry.npmjs.org/"
41
41
  },
42
- "version": "1.0.0"
42
+ "version": "1.2.0"
43
43
  }