ember-eslint-parser 0.2.6 → 0.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/package.json +5 -3
- package/src/parser/gjs-gts-parser.js +1 -0
- package/src/parser/transforms.js +57 -67
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-eslint-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"eslint-plugin-promise": "^6.0.0",
|
|
31
31
|
"execa": "^8.0.1",
|
|
32
32
|
"fs-extra": "^11.2.0",
|
|
33
|
-
"
|
|
33
|
+
"vite": "^5.0.12",
|
|
34
|
+
"vitest": "^1.2.2",
|
|
34
35
|
"prettier": "^3.1.1",
|
|
35
36
|
"publint": "^0.2.6",
|
|
36
37
|
"release-plan": "^0.6.0",
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
},
|
|
39
40
|
"dependencies": {
|
|
40
41
|
"@babel/eslint-parser": "^7.23.3",
|
|
41
|
-
"@glimmer/syntax": "^0.
|
|
42
|
+
"@glimmer/syntax": "^0.88.0",
|
|
42
43
|
"@typescript-eslint/scope-manager": "^6.15.0",
|
|
43
44
|
"content-tag": "^1.2.2",
|
|
44
45
|
"eslint-scope": "^7.2.2",
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"typescript": "^5.3.3"
|
|
54
55
|
},
|
|
55
56
|
"scripts": {
|
|
57
|
+
"test": "vitest run",
|
|
56
58
|
"lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
|
|
57
59
|
"lint:js": "eslint .",
|
|
58
60
|
"lint:package": "pnpm publint",
|
|
@@ -52,6 +52,7 @@ module.exports = {
|
|
|
52
52
|
return result;
|
|
53
53
|
}
|
|
54
54
|
const preprocessedResult = preprocessGlimmerTemplates(info, code);
|
|
55
|
+
preprocessedResult.code = code;
|
|
55
56
|
const { templateVisitorKeys } = preprocessedResult;
|
|
56
57
|
const visitorKeys = { ...result.visitorKeys, ...templateVisitorKeys };
|
|
57
58
|
result.isTypescript = isTypescript;
|
package/src/parser/transforms.js
CHANGED
|
@@ -240,15 +240,12 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
240
240
|
for (const tpl of templateInfos) {
|
|
241
241
|
const currentComments = [];
|
|
242
242
|
const textNodes = [];
|
|
243
|
-
const
|
|
244
|
-
const
|
|
243
|
+
const emptyTextNodes = [];
|
|
244
|
+
const range = tpl.utf16Range;
|
|
245
|
+
const template = code.slice(...range);
|
|
245
246
|
const docLines = new DocumentLines(template);
|
|
246
247
|
const ast = glimmer.preprocess(template, { mode: 'codemod' });
|
|
247
|
-
ast.tokens = tokenize(
|
|
248
|
-
sliceByteRange(code, ...tpl.templateRange),
|
|
249
|
-
codeLines,
|
|
250
|
-
tpl.templateRange[0]
|
|
251
|
-
);
|
|
248
|
+
ast.tokens = tokenize(sliceByteRange(code, ...tpl.templateRange), codeLines, tpl.utf16Range[0]);
|
|
252
249
|
const allNodes = [];
|
|
253
250
|
glimmer.traverse(ast, {
|
|
254
251
|
All(node, path) {
|
|
@@ -261,7 +258,13 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
261
258
|
}
|
|
262
259
|
if (node.type === 'TextNode') {
|
|
263
260
|
n.value = node.chars;
|
|
264
|
-
|
|
261
|
+
// empty text nodes are not allowed, it's empty if its only whitespace or line terminators
|
|
262
|
+
// it's okay for AttrNodes
|
|
263
|
+
if (n.value.trim().length !== 0 || n.parent.type === 'AttrNode') {
|
|
264
|
+
textNodes.push(node);
|
|
265
|
+
} else {
|
|
266
|
+
emptyTextNodes.push(node);
|
|
267
|
+
}
|
|
265
268
|
}
|
|
266
269
|
},
|
|
267
270
|
});
|
|
@@ -280,12 +283,11 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
280
283
|
}
|
|
281
284
|
n.range =
|
|
282
285
|
n.type === 'Template'
|
|
283
|
-
? [tpl.
|
|
286
|
+
? [tpl.utf16Range[0], tpl.utf16Range[1]]
|
|
284
287
|
: [
|
|
285
288
|
range[0] + docLines.positionToOffset(n.loc.start),
|
|
286
289
|
range[0] + docLines.positionToOffset(n.loc.end),
|
|
287
290
|
];
|
|
288
|
-
|
|
289
291
|
n.start = n.range[0];
|
|
290
292
|
n.end = n.range[1];
|
|
291
293
|
n.loc = {
|
|
@@ -293,70 +295,39 @@ module.exports.preprocessGlimmerTemplates = function preprocessGlimmerTemplates(
|
|
|
293
295
|
end: codeLines.offsetToPosition(n.range[1]),
|
|
294
296
|
};
|
|
295
297
|
if (n.type === 'Template') {
|
|
296
|
-
n.loc.start = codeLines.offsetToPosition(tpl.
|
|
297
|
-
n.loc.end = codeLines.offsetToPosition(tpl.
|
|
298
|
+
n.loc.start = codeLines.offsetToPosition(tpl.utf16Range[0]);
|
|
299
|
+
n.loc.end = codeLines.offsetToPosition(tpl.utf16Range[1]);
|
|
298
300
|
}
|
|
299
|
-
|
|
300
|
-
// parts <Foo.Bar /> -> nodes for `Foo` and `Bar`
|
|
301
|
+
|
|
301
302
|
if (n.type === 'ElementNode') {
|
|
302
303
|
n.name = n.tag;
|
|
303
|
-
n.parts =
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
range[1] = range[0] + part.length;
|
|
310
|
-
codeSlice = sliceByteRange(code, range[1], n.range[1]);
|
|
311
|
-
start = range[1];
|
|
312
|
-
n.parts.push({
|
|
313
|
-
type: 'GlimmerElementNodePart',
|
|
314
|
-
name: part,
|
|
315
|
-
range,
|
|
316
|
-
parent: n,
|
|
317
|
-
loc: {
|
|
318
|
-
start: codeLines.offsetToPosition(range[0]),
|
|
319
|
-
end: codeLines.offsetToPosition(range[1]),
|
|
320
|
-
},
|
|
321
|
-
});
|
|
322
|
-
}
|
|
304
|
+
n.parts = n.parts.map((p) => ({
|
|
305
|
+
...p,
|
|
306
|
+
parent: n,
|
|
307
|
+
type: 'GlimmerElementNodePart',
|
|
308
|
+
name: p.value,
|
|
309
|
+
}));
|
|
323
310
|
}
|
|
324
|
-
|
|
325
|
-
// add our own nodes so we can reference them
|
|
311
|
+
|
|
326
312
|
if ('blockParams' in n) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
let part = sliceByteRange(code, ...blockRange);
|
|
334
|
-
let start = blockRange[0];
|
|
335
|
-
let idx = part.indexOf('|') + 1;
|
|
336
|
-
start += idx;
|
|
337
|
-
part = part.slice(idx, -1);
|
|
338
|
-
idx = part.indexOf('|');
|
|
339
|
-
part = part.slice(0, idx);
|
|
340
|
-
for (const param of n.blockParams) {
|
|
341
|
-
const regex = new RegExp(`\\b${param}\\b`);
|
|
342
|
-
const match = part.match(regex);
|
|
343
|
-
const range = [start + match.index, 0];
|
|
344
|
-
range[1] = range[0] + param.length;
|
|
345
|
-
n.params.push({
|
|
346
|
-
type: 'BlockParam',
|
|
347
|
-
name: param,
|
|
348
|
-
range,
|
|
349
|
-
parent: n,
|
|
350
|
-
loc: {
|
|
351
|
-
start: codeLines.offsetToPosition(range[0]),
|
|
352
|
-
end: codeLines.offsetToPosition(range[1]),
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
}
|
|
313
|
+
// program does have blockParams but not blockParamNodes
|
|
314
|
+
n.params = (n.blockParamNodes || []).map((p) => ({
|
|
315
|
+
...p,
|
|
316
|
+
parent: n,
|
|
317
|
+
name: p.value,
|
|
318
|
+
}));
|
|
356
319
|
}
|
|
357
320
|
n.type = `Glimmer${n.type}`;
|
|
358
321
|
allNodeTypes.add(n.type);
|
|
359
322
|
}
|
|
323
|
+
|
|
324
|
+
// ast should not contains empty text nodes
|
|
325
|
+
for (const node of emptyTextNodes) {
|
|
326
|
+
const children = node.parent.children || node.parent.body;
|
|
327
|
+
const idx = children.indexOf(node);
|
|
328
|
+
children.splice(idx, 1);
|
|
329
|
+
}
|
|
330
|
+
|
|
360
331
|
// ast should not contain comment nodes
|
|
361
332
|
for (const comment of currentComments) {
|
|
362
333
|
const parentBody = comment.parent.body || comment.parent.children;
|
|
@@ -416,8 +387,8 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
416
387
|
result.ast.comments.push(...preprocessedResult.comments);
|
|
417
388
|
|
|
418
389
|
for (const ti of templateInfos) {
|
|
419
|
-
const firstIdx = result.ast.tokens.findIndex((t) => t.range[0] === ti.
|
|
420
|
-
const lastIdx = result.ast.tokens.findIndex((t) => t.range[1] === ti.
|
|
390
|
+
const firstIdx = result.ast.tokens.findIndex((t) => t.range[0] === ti.utf16Range[0]);
|
|
391
|
+
const lastIdx = result.ast.tokens.findIndex((t) => t.range[1] === ti.utf16Range[1]);
|
|
421
392
|
result.ast.tokens.splice(firstIdx, lastIdx - firstIdx + 1, ...ti.ast.tokens);
|
|
422
393
|
}
|
|
423
394
|
|
|
@@ -425,6 +396,7 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
425
396
|
traverse(visitorKeys, result.ast, (path) => {
|
|
426
397
|
const node = path.node;
|
|
427
398
|
if (!node) return null;
|
|
399
|
+
|
|
428
400
|
if (
|
|
429
401
|
node.type === 'ExpressionStatement' ||
|
|
430
402
|
node.type === 'StaticBlock' ||
|
|
@@ -504,6 +476,21 @@ module.exports.convertAst = function convertAst(result, preprocessedResult, visi
|
|
|
504
476
|
return null;
|
|
505
477
|
});
|
|
506
478
|
|
|
479
|
+
traverse(visitorKeys, result.ast, (path) => {
|
|
480
|
+
const node = path.node;
|
|
481
|
+
if (!node) return null;
|
|
482
|
+
|
|
483
|
+
if (
|
|
484
|
+
['GlimmerMustacheStatement', 'GlimmerBlockStatement', 'GlimmerSubExpression'].includes(
|
|
485
|
+
node.type
|
|
486
|
+
)
|
|
487
|
+
) {
|
|
488
|
+
if (node.hash && node.hash.pairs.length === 0) {
|
|
489
|
+
node.hash = null;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
|
|
507
494
|
if (counter !== templateInfos.length) {
|
|
508
495
|
throw new Error('failed to process all templates');
|
|
509
496
|
}
|
|
@@ -572,3 +559,6 @@ module.exports.transformForLint = function transformForLint(code) {
|
|
|
572
559
|
output: jsCode,
|
|
573
560
|
};
|
|
574
561
|
};
|
|
562
|
+
|
|
563
|
+
module.exports.traverse = traverse;
|
|
564
|
+
module.exports.tokenize = tokenize;
|