@valtzu/codemirror-lang-el 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ 1.3
5
+ ---
6
+
7
+ * Lint left- and right-side arguments of `contains`, `starts with`, `ends with` and `matches` operators
8
+ * Add eslint to make contributing/review easier
9
+ * Add type checking for left-side argument in `in` expression
10
+
4
11
  1.2
5
12
  ---
6
13
 
package/dist/index.cjs CHANGED
@@ -8,7 +8,7 @@ var autocomplete = require('@codemirror/autocomplete');
8
8
  var state = require('@codemirror/state');
9
9
  var view = require('@codemirror/view');
10
10
 
11
- // @ts-ignore
11
+ // @ts-expect-error TS2739
12
12
  const t = {
13
13
  deserialize: (str) => str,
14
14
  };
@@ -117,7 +117,7 @@ const resolveIdentifier = (nodeTypeId, identifier, config) => {
117
117
  };
118
118
  function resolveTypes(state, node, config) {
119
119
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
120
- let types = new Set();
120
+ const types = new Set();
121
121
  if (!node) {
122
122
  return types;
123
123
  }
@@ -130,19 +130,19 @@ function resolveTypes(state, node, config) {
130
130
  }
131
131
  else if (node.type.is(Variable)) {
132
132
  const varName = state.sliceDoc(node.from, node.to) || '';
133
- // @ts-ignore
133
+ // @ts-expect-error TS2339
134
134
  (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
135
135
  }
136
136
  else if (node.type.is(Function)) {
137
137
  const varName = state.sliceDoc(node.from, node.to) || '';
138
- // @ts-ignore
138
+ // @ts-expect-error TS2339
139
139
  (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
140
140
  }
141
141
  else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.type.is(Property))) {
142
142
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
143
143
  (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
144
144
  var _a, _b, _c, _d;
145
- // @ts-ignore
145
+ // @ts-expect-error TS2339
146
146
  (_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.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
147
147
  });
148
148
  }
@@ -150,7 +150,7 @@ function resolveTypes(state, node, config) {
150
150
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
151
151
  (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
152
152
  var _a, _b, _c, _d;
153
- // @ts-ignore
153
+ // @ts-expect-error TS2339
154
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));
155
155
  });
156
156
  }
@@ -234,13 +234,13 @@ var utils = /*#__PURE__*/Object.freeze({
234
234
  */
235
235
  const expressionLanguageLinterSource = (state) => {
236
236
  const config = getExpressionLanguageConfig(state);
237
- let diagnostics = [];
237
+ const diagnostics = [];
238
238
  language.syntaxTree(state).cursor().iterate(node => {
239
239
  var _a, _b, _c, _d, _e, _f;
240
240
  const { from, to, type: { id } } = node;
241
241
  let identifier;
242
242
  switch (id) {
243
- case 0:
243
+ case 0: {
244
244
  if (state.doc.length === 0 || from === 0) {
245
245
  // Don't show error on empty doc (even though it is an error)
246
246
  return;
@@ -254,7 +254,8 @@ const expressionLanguageLinterSource = (state) => {
254
254
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected ${type} <code>${identifier}</code>` });
255
255
  }
256
256
  return;
257
- case Arguments:
257
+ }
258
+ case Arguments: {
258
259
  const fn = resolveFunctionDefinition(node.node.prevSibling, state, config);
259
260
  const args = fn === null || fn === void 0 ? void 0 : fn.args;
260
261
  if (!args) {
@@ -275,7 +276,12 @@ const expressionLanguageLinterSource = (state) => {
275
276
  const typesUsed = Array.from(resolveTypes(state, n, config));
276
277
  const typesExpected = args[i].type;
277
278
  if (typesExpected && !typesExpected.includes(exports.ELScalar.Any) && !typesUsed.some(x => typesExpected.includes(x))) {
278
- diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `<code>${typesExpected.join('|')}</code> expected, got <code>${typesUsed.join('|')}</code>` });
279
+ diagnostics.push({
280
+ from: n.from,
281
+ to: n.to,
282
+ severity: 'error',
283
+ message: `<code>${typesExpected.join('|')}</code> expected, got <code>${typesUsed.join('|')}</code>`
284
+ });
279
285
  }
280
286
  i++;
281
287
  }
@@ -283,8 +289,9 @@ const expressionLanguageLinterSource = (state) => {
283
289
  diagnostics.push({ from: node.from, to: node.to, severity: 'error', message: `Too few arguments – ${argumentCountHintFn()}` });
284
290
  }
285
291
  break;
292
+ }
286
293
  case Property:
287
- case Method:
294
+ case Method: {
288
295
  const leftArgument = (_e = (_d = node.node.parent) === null || _d === void 0 ? void 0 : _d.firstChild) === null || _e === void 0 ? void 0 : _e.node;
289
296
  const types = Array.from(resolveTypes(state, leftArgument, config));
290
297
  identifier = state.sliceDoc(from, to);
@@ -292,26 +299,46 @@ const expressionLanguageLinterSource = (state) => {
292
299
  diagnostics.push({ from, to, severity: 'error', message: `${node.name} <code>${identifier}</code> not found in <code>${types.join('|')}</code>` });
293
300
  }
294
301
  break;
302
+ }
295
303
  case Variable:
296
- case Function:
304
+ case Function: {
297
305
  identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
298
306
  if (!resolveIdentifier(id, identifier, config)) {
299
307
  diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} <code>${identifier}</code> not found` });
300
308
  }
301
309
  break;
302
- case BinaryExpression:
310
+ }
311
+ case BinaryExpression: {
303
312
  const operatorNode = node.node.getChild(OperatorKeyword);
304
313
  if (operatorNode) {
305
314
  const operator = state.sliceDoc(operatorNode.from, operatorNode.to);
315
+ const leftArgument = node.node.firstChild;
316
+ const rightArgument = node.node.lastChild;
306
317
  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>` });
318
+ const leftTypes = resolveTypes(state, leftArgument, config);
319
+ const rightTypes = resolveTypes(state, rightArgument, config);
320
+ const allowsAny = rightTypes.has(exports.ELScalar.Array) || rightTypes.has(exports.ELScalar.Any);
321
+ if (!allowsAny && ![...rightTypes].some(x => x.endsWith('[]'))) {
322
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>${exports.ELScalar.Array}</code> expected, got <code>${[...rightTypes].join('|')}</code>` });
323
+ }
324
+ else if (!allowsAny && !rightTypes.has(`${exports.ELScalar.Any}[]`) && ![...leftTypes].some(type => rightTypes.has(`${type}[]`))) {
325
+ diagnostics.push({ from: leftArgument.from, to: rightArgument.to, severity: 'warning', message: `Expression is always <code>false</code> because <code>${[...leftTypes].join('|')}</code> not found in <code>${[...rightTypes].join('|')}</code>` });
326
+ }
327
+ }
328
+ else if (["contains", "starts with", "ends with", "matches"].includes(operator)) {
329
+ // Both sides must be string
330
+ const leftTypes = resolveTypes(state, leftArgument, config);
331
+ const rightTypes = resolveTypes(state, rightArgument, config);
332
+ if (!leftTypes.has(exports.ELScalar.String)) {
333
+ diagnostics.push({ from: leftArgument.from, to: leftArgument.to, severity: 'error', message: `<code>string</code> expected, got <code>${[...leftTypes].join('|')}</code>` });
334
+ }
335
+ if (!rightTypes.has(exports.ELScalar.String)) {
336
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>string</code> expected, got <code>${[...rightTypes].join('|')}</code>` });
311
337
  }
312
338
  }
313
339
  }
314
340
  break;
341
+ }
315
342
  }
316
343
  if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
317
344
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
@@ -383,7 +410,7 @@ function completeIdentifier(state, config, tree, from, to) {
383
410
  validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
384
411
  };
385
412
  }
386
- function completeMember(state, config, tree, from, to, explicit) {
413
+ function completeMember(state, config, tree, from, to) {
387
414
  var _a, _b, _c, _d, _e, _f;
388
415
  if (!(((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.firstChild)) {
389
416
  return null;
@@ -392,7 +419,7 @@ function completeMember(state, config, tree, from, to, explicit) {
392
419
  if (!(types === null || types === void 0 ? void 0 : types.size)) {
393
420
  return null;
394
421
  }
395
- let options = [];
422
+ const options = [];
396
423
  for (const type of types) {
397
424
  const typeDeclaration = (_d = config.types) === null || _d === void 0 ? void 0 : _d[type];
398
425
  options.push(...(((_e = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _e === void 0 ? void 0 : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _f === void 0 ? void 0 : _f.map(autocompleteFunction)) || []));
@@ -454,7 +481,6 @@ function resolveArguments(node) {
454
481
  }
455
482
  function getCursorTooltips(state) {
456
483
  const config = getExpressionLanguageConfig(state);
457
- // @ts-ignore
458
484
  return state.selection.ranges
459
485
  .filter(range => range.empty)
460
486
  .map(range => {
@@ -480,7 +506,7 @@ function getCursorTooltips(state) {
480
506
  strictSide: false,
481
507
  arrow: true,
482
508
  create: () => {
483
- let dom = document.createElement("div");
509
+ const dom = document.createElement("div");
484
510
  dom.className = "cm-tooltip-cursor";
485
511
  dom.textContent = `${argName}`;
486
512
  return { dom };
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { insertCompletionText } from '@codemirror/autocomplete';
6
6
  import { StateField } from '@codemirror/state';
7
7
  import { showTooltip, hoverTooltip, EditorView } from '@codemirror/view';
8
8
 
9
- // @ts-ignore
9
+ // @ts-expect-error TS2739
10
10
  const t = {
11
11
  deserialize: (str) => str,
12
12
  };
@@ -114,7 +114,7 @@ const resolveIdentifier = (nodeTypeId, identifier, config) => {
114
114
  };
115
115
  function resolveTypes(state, node, config) {
116
116
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
117
- let types = new Set();
117
+ const types = new Set();
118
118
  if (!node) {
119
119
  return types;
120
120
  }
@@ -127,19 +127,19 @@ function resolveTypes(state, node, config) {
127
127
  }
128
128
  else if (node.type.is(Variable)) {
129
129
  const varName = state.sliceDoc(node.from, node.to) || '';
130
- // @ts-ignore
130
+ // @ts-expect-error TS2339
131
131
  (_b = (_a = resolveIdentifier(node.type.id, varName, config)) === null || _a === void 0 ? void 0 : _a.type) === null || _b === void 0 ? void 0 : _b.forEach((x) => types.add(x));
132
132
  }
133
133
  else if (node.type.is(Function)) {
134
134
  const varName = state.sliceDoc(node.from, node.to) || '';
135
- // @ts-ignore
135
+ // @ts-expect-error TS2339
136
136
  (_d = (_c = resolveIdentifier(node.type.id, varName, config)) === null || _c === void 0 ? void 0 : _c.returnType) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
137
137
  }
138
138
  else if (node.type.is(PropertyAccess) && node.firstChild && ((_e = node.lastChild) === null || _e === void 0 ? void 0 : _e.type.is(Property))) {
139
139
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
140
140
  (_f = resolveTypes(state, node.firstChild, config)) === null || _f === void 0 ? void 0 : _f.forEach(baseType => {
141
141
  var _a, _b, _c, _d;
142
- // @ts-ignore
142
+ // @ts-expect-error TS2339
143
143
  (_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.type) === null || _d === void 0 ? void 0 : _d.forEach((x) => types.add(x));
144
144
  });
145
145
  }
@@ -147,7 +147,7 @@ function resolveTypes(state, node, config) {
147
147
  const varName = state.sliceDoc(node.lastChild.from, node.lastChild.to) || '';
148
148
  (_h = resolveTypes(state, node.firstChild, config)) === null || _h === void 0 ? void 0 : _h.forEach(baseType => {
149
149
  var _a, _b, _c, _d;
150
- // @ts-ignore
150
+ // @ts-expect-error TS2339
151
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));
152
152
  });
153
153
  }
@@ -231,13 +231,13 @@ var utils = /*#__PURE__*//*@__PURE__*/Object.freeze({
231
231
  */
232
232
  const expressionLanguageLinterSource = (state) => {
233
233
  const config = getExpressionLanguageConfig(state);
234
- let diagnostics = [];
234
+ const diagnostics = [];
235
235
  syntaxTree(state).cursor().iterate(node => {
236
236
  var _a, _b, _c, _d, _e, _f;
237
237
  const { from, to, type: { id } } = node;
238
238
  let identifier;
239
239
  switch (id) {
240
- case 0:
240
+ case 0: {
241
241
  if (state.doc.length === 0 || from === 0) {
242
242
  // Don't show error on empty doc (even though it is an error)
243
243
  return;
@@ -251,7 +251,8 @@ const expressionLanguageLinterSource = (state) => {
251
251
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected ${type} <code>${identifier}</code>` });
252
252
  }
253
253
  return;
254
- case Arguments:
254
+ }
255
+ case Arguments: {
255
256
  const fn = resolveFunctionDefinition(node.node.prevSibling, state, config);
256
257
  const args = fn === null || fn === void 0 ? void 0 : fn.args;
257
258
  if (!args) {
@@ -272,7 +273,12 @@ const expressionLanguageLinterSource = (state) => {
272
273
  const typesUsed = Array.from(resolveTypes(state, n, config));
273
274
  const typesExpected = args[i].type;
274
275
  if (typesExpected && !typesExpected.includes(ELScalar.Any) && !typesUsed.some(x => typesExpected.includes(x))) {
275
- diagnostics.push({ from: n.from, to: n.to, severity: 'error', message: `<code>${typesExpected.join('|')}</code> expected, got <code>${typesUsed.join('|')}</code>` });
276
+ diagnostics.push({
277
+ from: n.from,
278
+ to: n.to,
279
+ severity: 'error',
280
+ message: `<code>${typesExpected.join('|')}</code> expected, got <code>${typesUsed.join('|')}</code>`
281
+ });
276
282
  }
277
283
  i++;
278
284
  }
@@ -280,8 +286,9 @@ const expressionLanguageLinterSource = (state) => {
280
286
  diagnostics.push({ from: node.from, to: node.to, severity: 'error', message: `Too few arguments – ${argumentCountHintFn()}` });
281
287
  }
282
288
  break;
289
+ }
283
290
  case Property:
284
- case Method:
291
+ case Method: {
285
292
  const leftArgument = (_e = (_d = node.node.parent) === null || _d === void 0 ? void 0 : _d.firstChild) === null || _e === void 0 ? void 0 : _e.node;
286
293
  const types = Array.from(resolveTypes(state, leftArgument, config));
287
294
  identifier = state.sliceDoc(from, to);
@@ -289,26 +296,46 @@ const expressionLanguageLinterSource = (state) => {
289
296
  diagnostics.push({ from, to, severity: 'error', message: `${node.name} <code>${identifier}</code> not found in <code>${types.join('|')}</code>` });
290
297
  }
291
298
  break;
299
+ }
292
300
  case Variable:
293
- case Function:
301
+ case Function: {
294
302
  identifier = state.sliceDoc(from, node.node.firstChild ? node.node.firstChild.from - 1 : to);
295
303
  if (!resolveIdentifier(id, identifier, config)) {
296
304
  diagnostics.push({ from, to, severity: 'error', message: `${node.node.name} <code>${identifier}</code> not found` });
297
305
  }
298
306
  break;
299
- case BinaryExpression:
307
+ }
308
+ case BinaryExpression: {
300
309
  const operatorNode = node.node.getChild(OperatorKeyword);
301
310
  if (operatorNode) {
302
311
  const operator = state.sliceDoc(operatorNode.from, operatorNode.to);
312
+ const leftArgument = node.node.firstChild;
313
+ const rightArgument = node.node.lastChild;
303
314
  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>` });
315
+ const leftTypes = resolveTypes(state, leftArgument, config);
316
+ const rightTypes = resolveTypes(state, rightArgument, config);
317
+ const allowsAny = rightTypes.has(ELScalar.Array) || rightTypes.has(ELScalar.Any);
318
+ if (!allowsAny && ![...rightTypes].some(x => x.endsWith('[]'))) {
319
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>${ELScalar.Array}</code> expected, got <code>${[...rightTypes].join('|')}</code>` });
320
+ }
321
+ else if (!allowsAny && !rightTypes.has(`${ELScalar.Any}[]`) && ![...leftTypes].some(type => rightTypes.has(`${type}[]`))) {
322
+ diagnostics.push({ from: leftArgument.from, to: rightArgument.to, severity: 'warning', message: `Expression is always <code>false</code> because <code>${[...leftTypes].join('|')}</code> not found in <code>${[...rightTypes].join('|')}</code>` });
323
+ }
324
+ }
325
+ else if (["contains", "starts with", "ends with", "matches"].includes(operator)) {
326
+ // Both sides must be string
327
+ const leftTypes = resolveTypes(state, leftArgument, config);
328
+ const rightTypes = resolveTypes(state, rightArgument, config);
329
+ if (!leftTypes.has(ELScalar.String)) {
330
+ diagnostics.push({ from: leftArgument.from, to: leftArgument.to, severity: 'error', message: `<code>string</code> expected, got <code>${[...leftTypes].join('|')}</code>` });
331
+ }
332
+ if (!rightTypes.has(ELScalar.String)) {
333
+ diagnostics.push({ from: rightArgument.from, to: rightArgument.to, severity: 'error', message: `<code>string</code> expected, got <code>${[...rightTypes].join('|')}</code>` });
308
334
  }
309
335
  }
310
336
  }
311
337
  break;
338
+ }
312
339
  }
313
340
  if (identifier && ((_f = node.node.parent) === null || _f === void 0 ? void 0 : _f.type.isError)) {
314
341
  diagnostics.push({ from, to, severity: 'error', message: `Unexpected identifier <code>${identifier}</code>` });
@@ -380,7 +407,7 @@ function completeIdentifier(state, config, tree, from, to) {
380
407
  validFor: /^[a-zA-Z_]+[a-zA-Z_0-9]*$/,
381
408
  };
382
409
  }
383
- function completeMember(state, config, tree, from, to, explicit) {
410
+ function completeMember(state, config, tree, from, to) {
384
411
  var _a, _b, _c, _d, _e, _f;
385
412
  if (!(((_a = tree.parent) === null || _a === void 0 ? void 0 : _a.type.is(PropertyAccess)) || ((_b = tree.parent) === null || _b === void 0 ? void 0 : _b.type.is(MethodAccess))) || !((_c = tree.parent) === null || _c === void 0 ? void 0 : _c.firstChild)) {
386
413
  return null;
@@ -389,7 +416,7 @@ function completeMember(state, config, tree, from, to, explicit) {
389
416
  if (!(types === null || types === void 0 ? void 0 : types.size)) {
390
417
  return null;
391
418
  }
392
- let options = [];
419
+ const options = [];
393
420
  for (const type of types) {
394
421
  const typeDeclaration = (_d = config.types) === null || _d === void 0 ? void 0 : _d[type];
395
422
  options.push(...(((_e = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.identifiers) === null || _e === void 0 ? void 0 : _e.map(autocompleteIdentifier)) || []), ...(((_f = typeDeclaration === null || typeDeclaration === void 0 ? void 0 : typeDeclaration.functions) === null || _f === void 0 ? void 0 : _f.map(autocompleteFunction)) || []));
@@ -451,7 +478,6 @@ function resolveArguments(node) {
451
478
  }
452
479
  function getCursorTooltips(state) {
453
480
  const config = getExpressionLanguageConfig(state);
454
- // @ts-ignore
455
481
  return state.selection.ranges
456
482
  .filter(range => range.empty)
457
483
  .map(range => {
@@ -477,7 +503,7 @@ function getCursorTooltips(state) {
477
503
  strictSide: false,
478
504
  arrow: true,
479
505
  create: () => {
480
- let dom = document.createElement("div");
506
+ const dom = document.createElement("div");
481
507
  dom.className = "cm-tooltip-cursor";
482
508
  dom.textContent = `${argName}`;
483
509
  return { dom };
package/package.json CHANGED
@@ -4,7 +4,9 @@
4
4
  "scripts": {
5
5
  "pretest": "npm run-script prepare",
6
6
  "test": "cm-runtests",
7
- "prepare": "cm-buildhelper src/index.ts"
7
+ "prepare": "cm-buildhelper src/index.ts",
8
+ "lint-fix": "eslint . --fix --ext .ts,.js",
9
+ "lint": "eslint . --ext .ts,.js"
8
10
  },
9
11
  "type": "module",
10
12
  "main": "dist/index.cjs",
@@ -28,7 +30,10 @@
28
30
  "@codemirror/buildhelper": "^1.0.0",
29
31
  "@types/mocha": "^10.0.10",
30
32
  "@types/node": "^22.10.5",
31
- "tsdoc-markdown": "^1.1.1"
33
+ "tsdoc-markdown": "^1.1.1",
34
+ "eslint": "^8.48.0",
35
+ "@typescript-eslint/parser": "^6.5.0",
36
+ "@typescript-eslint/eslint-plugin": "^6.5.0"
32
37
  },
33
38
  "license": "MIT",
34
39
  "repository": {
@@ -39,5 +44,5 @@
39
44
  "access": "public",
40
45
  "registry": "https://registry.npmjs.org/"
41
46
  },
42
- "version": "1.2.0"
47
+ "version": "1.3.0"
43
48
  }