ember-codemod-remove-ember-css-modules 0.1.3 → 0.1.5

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 CHANGED
@@ -19,7 +19,7 @@ You can check [`ember-container-query`](https://github.com/ijlee2/ember-containe
19
19
  Step 1. Quickly migrate to [`embroider-css-modules`](https://github.com/ijlee2/embroider-css-modules).<sup>1</sup>
20
20
 
21
21
  ```sh
22
- cd <your/project/path>
22
+ cd <path/to/your/project>
23
23
  npx ember-codemod-remove-ember-css-modules <arguments>
24
24
  ```
25
25
 
@@ -29,9 +29,7 @@ Step 2. Review the project.
29
29
  - [x] Remove the remaining instances of `local-class` attributes and `{{local-class}}` helpers from `ember-css-modules`.
30
30
  - [x] Confirm that you can run all scripts in `package.json`.
31
31
 
32
- Step 3. Celebrate.
33
-
34
- <sup>1. Some prerequisites for running `ember-codemod-remove-ember-css-modules`: First, migrate to the Octane layout (flat or nested). You can leverage codemods for [classic](https://github.com/ember-codemods/ember-component-template-colocation-migrator) and [pod](https://github.com/ijlee2/ember-codemod-pod-to-octane) layouts. Second, [refactor code](#how-to-refactor-code) to help the codemod update templates correctly.</sup>
32
+ <sup>1. Some prerequisites for running the codemod: First, migrate to the Octane layout (flat or nested). You can leverage codemods for [classic](https://github.com/ember-codemods/ember-component-template-colocation-migrator) and [pod](https://github.com/ijlee2/ember-codemod-pod-to-octane) layouts. Second, [refactor code](#how-to-refactor-code) to help the codemod update templates correctly.</sup>
35
33
 
36
34
  <sup>2. Files such as `.eslintrc.js`, `.prettierrc.js`, `.stylelintrc.js`, `.template-lintrc.js`, `ember-cli-build.js`, `package.json`, `postcss.config.js`, `tsconfig.json`, etc.</sup>
37
35
 
@@ -55,7 +53,7 @@ npx ember-codemod-remove-ember-css-modules --component-structure="nested"
55
53
  Pass `--root` to run the codemod on a project somewhere else (i.e. not in the current directory).
56
54
 
57
55
  ```sh
58
- npx ember-codemod-remove-ember-css-modules --root=<your/project/path>
56
+ npx ember-codemod-remove-ember-css-modules --root=<path/to/your/project>
59
57
  ```
60
58
 
61
59
  </details>
@@ -68,8 +66,8 @@ The codemod is designed to cover typical uses of `ember-css-modules`. It is not
68
66
  To better meet your needs, consider cloning the repo and running the codemod locally.
69
67
 
70
68
  ```sh
71
- cd <your/cloned/repo>
72
- ./bin/ember-codemod-remove-ember-css-modules.js --root=<your/project/path>
69
+ cd <path/to/cloned/repo>
70
+ ./bin/ember-codemod-remove-ember-css-modules.js --root=<path/to/your/project>
73
71
  ```
74
72
 
75
73
 
@@ -181,7 +179,7 @@ In `ember-css-modules`, a string can represent multiple local class names via co
181
179
 
182
180
  </details>
183
181
 
184
- The codemod is not responsible for fixing complex expressions. Refactor templates to provide hints. For example, remove nested conditionals (apply them outside the HTML element) and use the `{{concat}}` helper to group substrings.
182
+ The codemod may fail to update complex expressions. Refactor templates to provide hints. For example, remove nested conditionals (apply them outside the HTML element) and use the `{{concat}}` helper to group substrings.
185
183
 
186
184
  <details>
187
185
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-codemod-remove-ember-css-modules",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Codemod to replace ember-css-modules with embroider-css-modules",
5
5
  "keywords": [
6
6
  "codemod",
@@ -27,19 +27,17 @@
27
27
  "test": "tests"
28
28
  },
29
29
  "dependencies": {
30
- "@babel/parser": "^7.21.9",
31
- "@codemod-utils/blueprints": "^0.1.1",
32
- "@codemod-utils/files": "^0.1.0",
33
- "@codemod-utils/json": "^0.1.1",
34
- "ember-template-recast": "^6.1.4",
35
- "recast": "^0.23.2",
30
+ "@codemod-utils/ast": "^0.1.1",
31
+ "@codemod-utils/blueprints": "^0.1.2",
32
+ "@codemod-utils/files": "^0.3.1",
33
+ "@codemod-utils/json": "^0.2.0",
36
34
  "yargs": "^17.7.2"
37
35
  },
38
36
  "devDependencies": {
39
- "@codemod-utils/tests": "^0.1.0",
37
+ "@codemod-utils/tests": "^0.1.2",
40
38
  "@sondr3/minitest": "^0.1.1",
41
- "concurrently": "^8.0.1",
42
- "eslint": "^8.41.0",
39
+ "concurrently": "^8.2.0",
40
+ "eslint": "^8.42.0",
43
41
  "prettier": "^2.8.8",
44
42
  "@shared-configs/eslint-config": "0.0.0",
45
43
  "@shared-configs/prettier": "0.0.0"
@@ -1,18 +1,18 @@
1
1
  import { join, parse } from 'node:path';
2
2
 
3
- import { findFiles, renameDirectory } from '@codemod-utils/files';
3
+ import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
4
4
 
5
5
  function findAndRenameFiles(findOptions, replaceOptions) {
6
6
  const { globPattern, ignoreList, projectRoot } = findOptions;
7
7
  const { from, to } = replaceOptions;
8
8
 
9
9
  const filePaths = findFiles(globPattern, {
10
- cwd: projectRoot,
11
10
  ignoreList,
11
+ projectRoot,
12
12
  });
13
13
 
14
14
  return filePaths.map((filePath) => {
15
- return renameDirectory(filePath, { from, to });
15
+ return renamePathByDirectory(filePath, { from, to });
16
16
  });
17
17
  }
18
18
 
@@ -1,33 +1,19 @@
1
- import { readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
1
+ import { readPackageJson } from '@codemod-utils/json';
3
2
 
4
3
  function analyzePackageJson(codemodOptions) {
5
- const { projectRoot } = codemodOptions;
6
-
7
- try {
8
- const packageJsonFile = readFileSync(
9
- join(projectRoot, 'package.json'),
10
- 'utf8',
11
- );
12
-
13
- const { dependencies, devDependencies } = JSON.parse(packageJsonFile);
14
-
15
- const projectDependencies = new Map([
16
- ...Object.entries(dependencies ?? {}),
17
- ...Object.entries(devDependencies ?? {}),
18
- ]);
19
-
20
- return {
21
- dependencies: projectDependencies,
22
- hasEmberCssModules: projectDependencies.has('ember-css-modules'),
23
- hasGlint: projectDependencies.has('@glint/core'),
24
- hasTypeScript: projectDependencies.has('typescript'),
25
- };
26
- } catch (e) {
27
- throw new SyntaxError(
28
- `ERROR: package.json is missing or is not valid. (${e.message})\n`,
29
- );
30
- }
4
+ const { dependencies, devDependencies } = readPackageJson(codemodOptions);
5
+
6
+ const projectDependencies = new Map([
7
+ ...Object.entries(dependencies ?? {}),
8
+ ...Object.entries(devDependencies ?? {}),
9
+ ]);
10
+
11
+ return {
12
+ dependencies: projectDependencies,
13
+ hasEmberCssModules: projectDependencies.has('ember-css-modules'),
14
+ hasGlint: projectDependencies.has('@glint/core'),
15
+ hasTypeScript: projectDependencies.has('typescript'),
16
+ };
31
17
  }
32
18
 
33
19
  export function createOptions(codemodOptions) {
@@ -9,8 +9,8 @@ function moveRouteStylesheets(options) {
9
9
  const { projectRoot } = options;
10
10
 
11
11
  const filePaths = findFiles('app/styles/**/*.css', {
12
- cwd: projectRoot,
13
12
  ignoreList: ['app/styles/app.css'],
13
+ projectRoot,
14
14
  });
15
15
 
16
16
  const pathMapping = mapFilePaths(filePaths, {
@@ -25,7 +25,7 @@ function moveAppCssToAssets(options) {
25
25
  const { projectRoot } = options;
26
26
 
27
27
  const filePaths = findFiles('app/styles/app.css', {
28
- cwd: projectRoot,
28
+ projectRoot,
29
29
  });
30
30
 
31
31
  const pathMapping = mapFilePaths(filePaths, {
@@ -1,15 +1,15 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { join, parse } from 'node:path';
3
3
 
4
+ import { ASTJavaScript as AST } from '@codemod-utils/ast';
4
5
  import { processTemplate } from '@codemod-utils/blueprints';
5
6
  import { createFiles } from '@codemod-utils/files';
6
7
 
7
- import { ASTJavaScript as AST } from '../../../../utils/abstract-syntax-tree.js';
8
8
  import { blueprintsRoot } from '../../../../utils/blueprints.js';
9
9
  import { parseEntityName } from '../../../../utils/string.js';
10
10
 
11
11
  function removeTemplateOnlyComponentMethod(file, data) {
12
- const traverse = AST.traverse(data.hasTypeScript);
12
+ const traverse = AST.traverse(data.isTypeScript);
13
13
 
14
14
  const ast = traverse(file, {
15
15
  visitCallExpression(path) {
@@ -19,7 +19,7 @@ function removeTemplateOnlyComponentMethod(file, data) {
19
19
 
20
20
  const superClass = AST.builders.identifier('Component');
21
21
 
22
- if (data.hasTypeScript) {
22
+ if (data.isTypeScript) {
23
23
  superClass.typeAnnotation = path.value.typeParameters;
24
24
  }
25
25
 
@@ -63,7 +63,7 @@ function removeTemplateOnlyComponentMethod(file, data) {
63
63
  }
64
64
 
65
65
  function importStylesInClass(file, data) {
66
- const traverse = AST.traverse(data.hasTypeScript);
66
+ const traverse = AST.traverse(data.isTypeScript);
67
67
 
68
68
  // Find the last import statement
69
69
  let lastImportDeclarationPath;
@@ -101,7 +101,7 @@ function importStylesInClass(file, data) {
101
101
  }
102
102
 
103
103
  function addStylesAsClassProperty(file, data) {
104
- const traverse = AST.traverse(data.hasTypeScript);
104
+ const traverse = AST.traverse(data.isTypeScript);
105
105
 
106
106
  const ast = traverse(file, {
107
107
  visitClassDeclaration(path) {
@@ -154,25 +154,25 @@ function updateClass(customizations, options) {
154
154
  const { __styles__, projectRoot } = options;
155
155
 
156
156
  const { ext: fileExtension, name: fileName } = parse(filePath);
157
- const hasTypeScript = fileExtension === '.ts';
157
+ const isTypeScript = fileExtension === '.ts';
158
158
 
159
159
  let file = readFileSync(join(projectRoot, filePath), 'utf8');
160
160
 
161
161
  try {
162
162
  file = removeTemplateOnlyComponentMethod(file, {
163
163
  __styles__,
164
- hasTypeScript,
164
+ isTypeScript,
165
165
  });
166
166
 
167
167
  file = importStylesInClass(file, {
168
168
  __styles__,
169
169
  fileName,
170
- hasTypeScript,
170
+ isTypeScript,
171
171
  });
172
172
 
173
173
  file = addStylesAsClassProperty(file, {
174
174
  __styles__,
175
- hasTypeScript,
175
+ isTypeScript,
176
176
  });
177
177
 
178
178
  const fileMapping = new Map([[filePath, file]]);
@@ -1,10 +1,9 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
 
4
+ import { ASTHandlebars as AST } from '@codemod-utils/ast';
4
5
  import { createFiles } from '@codemod-utils/files';
5
6
 
6
- import { ASTHandlebars as AST } from '../../../../utils/abstract-syntax-tree.js';
7
-
8
7
  function sanitizeClassAndLocalClassAttributes(file) {
9
8
  function removeAttributeWithoutValue(attributeName, attributes) {
10
9
  const attributeIndex = attributes.findIndex(
@@ -34,7 +33,9 @@ function sanitizeClassAndLocalClassAttributes(file) {
34
33
  }
35
34
  }
36
35
 
37
- const ast = AST.traverse(file, {
36
+ const traverse = AST.traverse();
37
+
38
+ const ast = traverse(file, {
38
39
  ElementNode(node) {
39
40
  const { attributes } = node;
40
41
 
@@ -47,7 +48,9 @@ function sanitizeClassAndLocalClassAttributes(file) {
47
48
  }
48
49
 
49
50
  function mergeClassAndLocalClassAttributes(file, data) {
50
- const ast = AST.traverse(file, {
51
+ const traverse = AST.traverse();
52
+
53
+ const ast = traverse(file, {
51
54
  ElementNode(node) {
52
55
  // Check that both class and local-class attributes exist
53
56
  const { attributes } = node;
@@ -139,7 +142,9 @@ function removeLocalClassHelpers(file, data) {
139
142
  return value === '';
140
143
  }
141
144
 
142
- const ast = AST.traverse(file, {
145
+ const traverse = AST.traverse();
146
+
147
+ const ast = traverse(file, {
143
148
  AttrNode(node) {
144
149
  if (node.name !== 'class') {
145
150
  return;
@@ -332,7 +337,9 @@ function removeLocalClassAttributes(file, data) {
332
337
  }, []);
333
338
  }
334
339
 
335
- const ast = AST.traverse(file, {
340
+ const traverse = AST.traverse();
341
+
342
+ const ast = traverse(file, {
336
343
  ElementNode(node) {
337
344
  // Check if the local-class attribute (still) exists
338
345
  const { attributes } = node;
@@ -1,12 +1,11 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { extname, join } from 'node:path';
3
3
 
4
+ import { ASTJavaScript as AST } from '@codemod-utils/ast';
4
5
  import { createFiles, findFiles } from '@codemod-utils/files';
5
6
 
6
- import { ASTJavaScript as AST } from '../../../utils/abstract-syntax-tree.js';
7
-
8
7
  function addCssEntryPoint(file, data) {
9
- const traverse = AST.traverse(data.hasTypeScript);
8
+ const traverse = AST.traverse(data.isTypeScript);
10
9
 
11
10
  const ast = traverse(file, {
12
11
  visitProgram(path) {
@@ -31,7 +30,7 @@ export function updateAppAppJs(options) {
31
30
  const { projectRoot } = options;
32
31
 
33
32
  const filePaths = findFiles('app/app.{js,ts}', {
34
- cwd: projectRoot,
33
+ projectRoot,
35
34
  });
36
35
 
37
36
  if (filePaths.length !== 1) {
@@ -45,13 +44,13 @@ export function updateAppAppJs(options) {
45
44
  const filePath = filePaths[0];
46
45
 
47
46
  const fileExtension = extname(filePath);
48
- const hasTypeScript = fileExtension === '.ts';
47
+ const isTypeScript = fileExtension === '.ts';
49
48
 
50
49
  let file = readFileSync(join(projectRoot, filePath), 'utf8');
51
50
 
52
51
  try {
53
52
  file = addCssEntryPoint(file, {
54
- hasTypeScript,
53
+ isTypeScript,
55
54
  });
56
55
 
57
56
  const fileMapping = new Map([[filePath, file]]);
@@ -1,7 +1,11 @@
1
- import { readFileSync, writeFileSync } from 'node:fs';
1
+ import { writeFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
 
4
- import { convertToMap, convertToObject } from '@codemod-utils/json';
4
+ import {
5
+ convertToMap,
6
+ convertToObject,
7
+ readPackageJson,
8
+ } from '@codemod-utils/json';
5
9
 
6
10
  import { getVersion } from '../../../utils/blueprints.js';
7
11
 
@@ -46,14 +50,12 @@ function updateScripts(packageJson, options) {
46
50
  export function updatePackageJson(options) {
47
51
  const { projectRoot } = options;
48
52
 
49
- const oldPath = join(projectRoot, 'package.json');
50
- const oldFile = readFileSync(oldPath, 'utf8');
51
- const packageJson = JSON.parse(oldFile);
52
-
53
+ const packageJson = readPackageJson(options);
53
54
  updateDevDependencies(packageJson, options);
54
55
  updateScripts(packageJson, options);
55
56
 
56
- const newFile = JSON.stringify(packageJson, null, 2) + '\n';
57
+ const destination = join(projectRoot, 'package.json');
58
+ const file = JSON.stringify(packageJson, null, 2) + '\n';
57
59
 
58
- writeFileSync(oldPath, newFile, 'utf8');
60
+ writeFileSync(destination, file, 'utf8');
59
61
  }
@@ -1,9 +1,9 @@
1
1
  import { decideVersion } from '@codemod-utils/blueprints';
2
2
 
3
3
  const latestVersions = new Map([
4
- ['embroider-css-modules', '0.1.1'],
5
- ['type-css-modules', '0.1.1'],
6
- ['webpack', '5.81.0'],
4
+ ['embroider-css-modules', '0.1.6'],
5
+ ['type-css-modules', '0.1.4'],
6
+ ['webpack', '5.86.0'],
7
7
  ]);
8
8
 
9
9
  export function getVersion(packageName, options) {
@@ -1,20 +0,0 @@
1
- import { builders, print, transform } from 'ember-template-recast';
2
-
3
- function traverseHandlebars(file, visitMethods = {}) {
4
- const { ast } = transform({
5
- plugin() {
6
- return visitMethods;
7
- },
8
- template: file,
9
- });
10
-
11
- return ast;
12
- }
13
-
14
- const tools = {
15
- builders,
16
- print,
17
- traverse: traverseHandlebars,
18
- };
19
-
20
- export default tools;
@@ -1,103 +0,0 @@
1
- import { parse as babelParser } from '@babel/parser';
2
- import { parse, print, types, visit } from 'recast';
3
-
4
- /* https://github.com/benjamn/recast/blob/v1.4.0/lib/options.ts */
5
- const formattingOptions = {
6
- quote: 'single',
7
- };
8
-
9
- /* https://github.com/facebook/jscodeshift/blob/v0.14.0/parser/babel5Compat.js */
10
- const jsOptions = {
11
- sourceType: 'module',
12
- allowHashBang: true,
13
- ecmaVersion: Infinity,
14
- allowImportExportEverywhere: true,
15
- allowReturnOutsideFunction: true,
16
- startLine: 1,
17
- tokens: true,
18
- plugins: [
19
- 'estree',
20
- 'jsx',
21
- 'asyncGenerators',
22
- 'classProperties',
23
- 'doExpressions',
24
- 'exportExtensions',
25
- 'functionBind',
26
- 'functionSent',
27
- 'objectRestSpread',
28
- 'dynamicImport',
29
- 'nullishCoalescingOperator',
30
- 'optionalChaining',
31
- [
32
- 'decorators',
33
- {
34
- decoratorsBeforeExport: false,
35
- },
36
- ],
37
- ],
38
- };
39
-
40
- /* https://github.com/facebook/jscodeshift/blob/v0.14.0/parser/tsOptions.js */
41
- const tsOptions = {
42
- sourceType: 'module',
43
- allowImportExportEverywhere: true,
44
- allowReturnOutsideFunction: true,
45
- startLine: 1,
46
- tokens: true,
47
- plugins: [
48
- 'asyncGenerators',
49
- 'bigInt',
50
- 'classPrivateMethods',
51
- 'classPrivateProperties',
52
- 'classProperties',
53
- 'decorators-legacy',
54
- 'doExpressions',
55
- 'dynamicImport',
56
- 'exportDefaultFrom',
57
- 'exportExtensions',
58
- 'exportNamespaceFrom',
59
- 'functionBind',
60
- 'functionSent',
61
- 'importMeta',
62
- 'nullishCoalescingOperator',
63
- 'numericSeparator',
64
- 'objectRestSpread',
65
- 'optionalCatchBinding',
66
- 'optionalChaining',
67
- ['pipelineOperator', { proposal: 'minimal' }],
68
- 'throwExpressions',
69
- 'typescript',
70
- ],
71
- };
72
-
73
- function getParseOptions(hasTypeScript) {
74
- const options = hasTypeScript ? tsOptions : jsOptions;
75
-
76
- return {
77
- parser: {
78
- parse(file) {
79
- return babelParser(file, options);
80
- },
81
- },
82
- };
83
- }
84
-
85
- function traverse(hasTypeScript) {
86
- return function (file, visitMethods) {
87
- const ast = parse(file, getParseOptions(hasTypeScript));
88
-
89
- visit(ast, visitMethods);
90
-
91
- return ast;
92
- };
93
- }
94
-
95
- const tools = {
96
- builders: types.builders,
97
- print(ast) {
98
- return print(ast, formattingOptions).code;
99
- },
100
- traverse,
101
- };
102
-
103
- export default tools;
@@ -1,2 +0,0 @@
1
- export { default as ASTHandlebars } from './abstract-syntax-tree/handlebars.js';
2
- export { default as ASTJavaScript } from './abstract-syntax-tree/javascript.js';