ember-codemod-remove-ember-css-modules 4.0.3 → 4.0.4
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.
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
|
|
2
1
|
import { readFileSync } from 'node:fs';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { AST } from '@codemod-utils/ast-javascript';
|
|
@@ -20,22 +19,25 @@ function removeTemplateOnlyComponentMethod(file, data) {
|
|
|
20
19
|
const traverse = AST.traverse(data.isTypeScript);
|
|
21
20
|
const ast = traverse(file, {
|
|
22
21
|
visitCallExpression(path) {
|
|
23
|
-
|
|
22
|
+
// @ts-expect-error: Incorrect type
|
|
23
|
+
if (path.node.callee.name !== 'templateOnlyComponent') {
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
26
|
const superClass = AST.builders.identifier('Component');
|
|
27
27
|
if (data.isTypeScript) {
|
|
28
|
-
|
|
28
|
+
// @ts-expect-error: Incorrect type
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
30
|
+
superClass.typeAnnotation = path.node.typeParameters;
|
|
29
31
|
}
|
|
30
32
|
return AST.builders.classExpression(null, AST.builders.classBody([
|
|
31
33
|
AST.builders.classProperty(AST.builders.identifier('styles'), AST.builders.identifier('styles')),
|
|
32
34
|
]), superClass);
|
|
33
35
|
},
|
|
34
36
|
visitImportDeclaration(path) {
|
|
35
|
-
if (path.
|
|
37
|
+
if (path.node.source.value !== '@ember/component/template-only') {
|
|
36
38
|
return false;
|
|
37
39
|
}
|
|
38
|
-
const defaultImport = path.
|
|
40
|
+
const defaultImport = path.node.specifiers?.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
|
|
39
41
|
if (defaultImport?.local?.name !== 'templateOnlyComponent') {
|
|
40
42
|
return false;
|
|
41
43
|
}
|
|
@@ -55,6 +57,7 @@ function importStylesInClass(file, data) {
|
|
|
55
57
|
if (!lastImportDeclarationPath) {
|
|
56
58
|
lastImportDeclarationPath = path;
|
|
57
59
|
// @ts-expect-error: Incorrect type
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
58
61
|
}
|
|
59
62
|
else if (path.node.start > lastImportDeclarationPath.node.start) {
|
|
60
63
|
lastImportDeclarationPath = path;
|
|
@@ -64,9 +67,12 @@ function importStylesInClass(file, data) {
|
|
|
64
67
|
});
|
|
65
68
|
// Append the styles import
|
|
66
69
|
// @ts-expect-error: Incorrect type
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
67
71
|
const nodes = ast.program.body;
|
|
68
72
|
// @ts-expect-error: Incorrect type
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
69
74
|
const index = lastImportDeclarationPath?.name ?? -1;
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
70
76
|
nodes.splice(index + 1, 0, AST.builders.importDeclaration([AST.builders.importDefaultSpecifier(AST.builders.identifier('styles'))], AST.builders.literal(`./${data.fileName}.css`)));
|
|
71
77
|
return AST.print(ast);
|
|
72
78
|
}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
|
|
2
1
|
import { readFileSync } from 'node:fs';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { AST } from '@codemod-utils/ast-template';
|
|
5
4
|
import { createFiles } from '@codemod-utils/files';
|
|
6
5
|
function sanitizeClassAndLocalClassAttributes(file) {
|
|
7
6
|
function removeAttributeWithoutValue(attributeName, attributes) {
|
|
8
|
-
const attributeIndex = attributes.findIndex(
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const attributeIndex = attributes.findIndex((attribute) => {
|
|
8
|
+
return attribute.name === attributeName;
|
|
9
|
+
});
|
|
11
10
|
if (attributeIndex === -1) {
|
|
12
11
|
return;
|
|
13
12
|
}
|
|
14
13
|
const attribute = attributes[attributeIndex];
|
|
15
|
-
// @ts-expect-error: Incorrect type
|
|
16
14
|
if (attribute.isValueless) {
|
|
17
15
|
attributes.splice(attributeIndex, 1);
|
|
18
16
|
return;
|
|
19
17
|
}
|
|
20
|
-
// @ts-expect-error: Incorrect type
|
|
21
18
|
if (attribute.value.type !== 'TextNode') {
|
|
22
19
|
return;
|
|
23
20
|
}
|
|
24
|
-
// @ts-expect-error: Incorrect type
|
|
25
21
|
const attributeValue = attribute.value.chars.trim();
|
|
26
22
|
if (attributeValue === '') {
|
|
27
23
|
attributes.splice(attributeIndex, 1);
|
|
@@ -44,8 +40,12 @@ function mergeClassAndLocalClassAttributes(file) {
|
|
|
44
40
|
ElementNode(node) {
|
|
45
41
|
// Check that both class and local-class attributes exist
|
|
46
42
|
const { attributes } = node;
|
|
47
|
-
const localClassAttributeIndex = attributes.findIndex((attribute) =>
|
|
48
|
-
|
|
43
|
+
const localClassAttributeIndex = attributes.findIndex((attribute) => {
|
|
44
|
+
return attribute.name === 'local-class';
|
|
45
|
+
});
|
|
46
|
+
const classAttributeIndex = attributes.findIndex((attribute) => {
|
|
47
|
+
return attribute.name === 'class';
|
|
48
|
+
});
|
|
49
49
|
if (localClassAttributeIndex === -1 || classAttributeIndex === -1) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
@@ -91,32 +91,33 @@ function removeLocalClassHelpers(file) {
|
|
|
91
91
|
*/
|
|
92
92
|
function canRemoveLocalClassHelper(path) {
|
|
93
93
|
// @ts-expect-error: Incorrect type
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
94
95
|
const hasFromArgument = path.hash.pairs.some((pair) => pair.key === 'from');
|
|
95
96
|
if (hasFromArgument) {
|
|
96
|
-
throw new RangeError(
|
|
97
|
-
// @ts-expect-error: Incorrect type
|
|
98
|
-
`Unable to handle the {{local-class}} helper's \`from\` key. See lines ${path.loc.start.line}-${path.loc.end.line}.`);
|
|
97
|
+
throw new RangeError(`Unable to handle the {{local-class}} helper's \`from\` key. See lines ${path.loc.start.line}-${path.loc.end.line}.`);
|
|
99
98
|
}
|
|
100
99
|
// @ts-expect-error: Incorrect type
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
101
101
|
const param = path.params[0];
|
|
102
102
|
if (param === undefined) {
|
|
103
103
|
return true;
|
|
104
104
|
}
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
105
106
|
if (param.type !== 'StringLiteral') {
|
|
106
107
|
return false;
|
|
107
108
|
}
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
108
110
|
const value = param.value.trim();
|
|
109
111
|
return value === '';
|
|
110
112
|
}
|
|
111
113
|
const traverse = AST.traverse();
|
|
112
114
|
const ast = traverse(file, {
|
|
113
|
-
// @ts-expect-error: Incorrect type
|
|
114
115
|
AttrNode(node) {
|
|
115
116
|
if (node.name !== 'class') {
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
118
119
|
const hasLocalClassHelper = node.value.type === 'MustacheStatement' &&
|
|
119
|
-
|
|
120
|
+
node.value.path.type === 'PathExpression' &&
|
|
120
121
|
node.value.path.original === 'local-class';
|
|
121
122
|
if (!hasLocalClassHelper) {
|
|
122
123
|
return;
|
|
@@ -125,23 +126,32 @@ function removeLocalClassHelpers(file) {
|
|
|
125
126
|
return null;
|
|
126
127
|
}
|
|
127
128
|
// @ts-expect-error: Incorrect type
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
128
130
|
const param = node.value.params[0];
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
129
132
|
if (param.type !== 'StringLiteral') {
|
|
130
133
|
return;
|
|
131
134
|
}
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
132
136
|
const localClassNames = param.value.trim().split(/\s+/);
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
133
138
|
if (localClassNames.length === 1) {
|
|
134
|
-
node.value = AST.builders.mustache(
|
|
139
|
+
node.value = AST.builders.mustache(
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
141
|
+
AST.builders.path(`this.styles.${localClassNames[0]}`));
|
|
135
142
|
return;
|
|
136
143
|
}
|
|
137
144
|
node.value = AST.builders.mustache(AST.builders.path('local'), [
|
|
138
145
|
AST.builders.path('this.styles'),
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
139
147
|
...localClassNames.map(AST.builders.string),
|
|
140
148
|
]);
|
|
149
|
+
return;
|
|
141
150
|
},
|
|
142
151
|
MustacheStatement(node) {
|
|
143
|
-
|
|
144
|
-
node.path.original
|
|
152
|
+
const hasLocalClassHelper = node.path.type === 'PathExpression' &&
|
|
153
|
+
node.path.original === 'local-class';
|
|
154
|
+
if (!hasLocalClassHelper) {
|
|
145
155
|
return;
|
|
146
156
|
}
|
|
147
157
|
const param = node.params[0];
|
|
@@ -158,8 +168,8 @@ function removeLocalClassHelpers(file) {
|
|
|
158
168
|
]);
|
|
159
169
|
},
|
|
160
170
|
SubExpression(node) {
|
|
161
|
-
|
|
162
|
-
|
|
171
|
+
const hasLocalClassHelper = node.path.type === 'PathExpression' &&
|
|
172
|
+
node.path.original === 'local-class';
|
|
163
173
|
if (!hasLocalClassHelper) {
|
|
164
174
|
return;
|
|
165
175
|
}
|
|
@@ -183,60 +193,56 @@ function removeLocalClassHelpers(file) {
|
|
|
183
193
|
return AST.print(ast);
|
|
184
194
|
}
|
|
185
195
|
function removeLocalClassAttributes(file) {
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
switch (param.type) {
|
|
196
|
+
function transformExpression(expression) {
|
|
197
|
+
switch (expression.type) {
|
|
189
198
|
case 'StringLiteral': {
|
|
190
|
-
|
|
191
|
-
const localClassNames = param.value.trim().split(/\s+/);
|
|
199
|
+
const localClassNames = expression.value.trim().split(/\s+/);
|
|
192
200
|
if (localClassNames.length === 1) {
|
|
193
|
-
|
|
194
|
-
param.value = localClassNames[0];
|
|
201
|
+
expression.value = localClassNames[0];
|
|
195
202
|
}
|
|
196
203
|
else {
|
|
197
|
-
|
|
204
|
+
expression = AST.builders.sexpr('array', localClassNames.map(AST.builders.string));
|
|
198
205
|
}
|
|
199
206
|
break;
|
|
200
207
|
}
|
|
201
208
|
case 'SubExpression': {
|
|
202
|
-
|
|
203
|
-
|
|
209
|
+
if (expression.path.type !== 'PathExpression') {
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
switch (expression.path.original) {
|
|
204
213
|
case 'if':
|
|
205
214
|
case 'unless': {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// @ts-expect-error: Incorrect type
|
|
209
|
-
param = AST.builders.sexpr(param.path.original, subparams);
|
|
215
|
+
const subparams = expression.params.map(transformExpression);
|
|
216
|
+
expression = AST.builders.sexpr(expression.path.original, subparams);
|
|
210
217
|
break;
|
|
211
218
|
}
|
|
212
219
|
}
|
|
213
220
|
break;
|
|
214
221
|
}
|
|
215
222
|
}
|
|
216
|
-
return
|
|
223
|
+
return expression;
|
|
217
224
|
}
|
|
218
|
-
// @ts-expect-error: Incorrect type
|
|
219
225
|
function transformPart(part) {
|
|
220
|
-
// @ts-expect-error: Incorrect type
|
|
221
226
|
switch (part.type) {
|
|
222
227
|
case 'MustacheStatement': {
|
|
223
|
-
|
|
228
|
+
if (part.path.type === 'SubExpression') {
|
|
229
|
+
return AST.builders.mustache(AST.builders.path('get'), [
|
|
230
|
+
AST.builders.path('this.styles'),
|
|
231
|
+
part.path,
|
|
232
|
+
]);
|
|
233
|
+
}
|
|
224
234
|
switch (part.path.original) {
|
|
225
235
|
case 'concat': {
|
|
226
236
|
function hasPathExpression(params) {
|
|
227
|
-
// @ts-expect-error: Incorrect type
|
|
228
237
|
return params.some((param) => param.type === 'PathExpression');
|
|
229
238
|
}
|
|
230
|
-
// @ts-expect-error: Incorrect type
|
|
231
239
|
if (hasPathExpression(part.params)) {
|
|
232
240
|
return AST.builders.mustache(AST.builders.path('get'), [
|
|
233
241
|
AST.builders.path('this.styles'),
|
|
234
|
-
// @ts-expect-error: Incorrect type
|
|
235
242
|
AST.builders.sexpr(part.path.original, part.params),
|
|
236
243
|
]);
|
|
237
244
|
}
|
|
238
|
-
|
|
239
|
-
const params = part.params.map(transformParam);
|
|
245
|
+
const params = part.params.map(transformExpression);
|
|
240
246
|
return AST.builders.mustache('local', [
|
|
241
247
|
AST.builders.path('this.styles'),
|
|
242
248
|
...params,
|
|
@@ -244,25 +250,21 @@ function removeLocalClassAttributes(file) {
|
|
|
244
250
|
}
|
|
245
251
|
case 'if':
|
|
246
252
|
case 'unless': {
|
|
247
|
-
|
|
248
|
-
const params = part.params.map(transformParam);
|
|
253
|
+
const params = part.params.map(transformExpression);
|
|
249
254
|
return AST.builders.mustache('local', [
|
|
250
255
|
AST.builders.path('this.styles'),
|
|
251
|
-
// @ts-expect-error: Incorrect type
|
|
252
256
|
AST.builders.sexpr(part.path.original, params),
|
|
253
257
|
]);
|
|
254
258
|
}
|
|
255
259
|
default: {
|
|
256
260
|
return AST.builders.mustache(AST.builders.path('get'), [
|
|
257
261
|
AST.builders.path('this.styles'),
|
|
258
|
-
// @ts-expect-error: Incorrect type
|
|
259
262
|
part.path,
|
|
260
263
|
]);
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
266
|
}
|
|
264
267
|
case 'TextNode': {
|
|
265
|
-
// @ts-expect-error: Incorrect type
|
|
266
268
|
const value = part.chars.trim();
|
|
267
269
|
if (value === '') {
|
|
268
270
|
return part;
|
|
@@ -281,10 +283,8 @@ function removeLocalClassAttributes(file) {
|
|
|
281
283
|
function transformParts(parts) {
|
|
282
284
|
const numParts = parts.length;
|
|
283
285
|
return parts.reduce((accumulator, part, index) => {
|
|
284
|
-
// @ts-expect-error: Incorrect type
|
|
285
286
|
accumulator.push(transformPart(part));
|
|
286
287
|
if (index < numParts - 1) {
|
|
287
|
-
// @ts-expect-error: Incorrect type
|
|
288
288
|
accumulator.push(AST.builders.text(' '));
|
|
289
289
|
}
|
|
290
290
|
return accumulator;
|
|
@@ -310,13 +310,11 @@ function removeLocalClassAttributes(file) {
|
|
|
310
310
|
}
|
|
311
311
|
case 'MustacheStatement': {
|
|
312
312
|
localClassAttribute.name = 'class';
|
|
313
|
-
// @ts-expect-error: Incorrect type
|
|
314
313
|
localClassAttribute.value = transformPart(localClassAttribute.value);
|
|
315
314
|
break;
|
|
316
315
|
}
|
|
317
316
|
case 'TextNode': {
|
|
318
317
|
localClassAttribute.name = 'class';
|
|
319
|
-
// @ts-expect-error: Incorrect type
|
|
320
318
|
localClassAttribute.value = transformPart(localClassAttribute.value);
|
|
321
319
|
break;
|
|
322
320
|
}
|
|
@@ -327,17 +325,13 @@ function removeLocalClassAttributes(file) {
|
|
|
327
325
|
return;
|
|
328
326
|
}
|
|
329
327
|
node.key = 'class';
|
|
330
|
-
const newValue =
|
|
331
|
-
// @ts-expect-error: Incorrect type
|
|
328
|
+
const newValue = transformExpression(node.value);
|
|
332
329
|
if (newValue.type === 'StringLiteral') {
|
|
333
|
-
node.value = AST.builders.path(
|
|
334
|
-
// @ts-expect-error: Incorrect type
|
|
335
|
-
`this.styles.${newValue.value}`);
|
|
330
|
+
node.value = AST.builders.path(`this.styles.${newValue.value}`);
|
|
336
331
|
return;
|
|
337
332
|
}
|
|
338
333
|
node.value = AST.builders.sexpr('local', [
|
|
339
334
|
AST.builders.path('this.styles'),
|
|
340
|
-
// @ts-expect-error: Incorrect type
|
|
341
335
|
newValue,
|
|
342
336
|
]);
|
|
343
337
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ember-codemod-remove-ember-css-modules",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "Codemod to replace ember-css-modules with embroider-css-modules",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codemod",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"eslint": "^9.39.4",
|
|
42
42
|
"prettier": "^3.8.3",
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
|
-
"@shared-configs/eslint-config-node": "0.0.0",
|
|
45
44
|
"@shared-configs/typescript": "0.0.0",
|
|
45
|
+
"@shared-configs/eslint-config-node": "0.0.0",
|
|
46
46
|
"@shared-configs/prettier": "0.0.0"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|