ember-codemod-remove-ember-css-modules 1.1.3 → 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.
Files changed (30) hide show
  1. package/README.md +28 -6
  2. package/dist/bin/ember-codemod-remove-ember-css-modules.js +7 -0
  3. package/dist/src/index.js +11 -2
  4. package/dist/src/migration/ember-app/index.js +3 -2
  5. package/dist/src/migration/ember-app/steps/{analyze-app → analyze-project}/analyze-components.js +1 -1
  6. package/dist/src/migration/ember-app/steps/{analyze-app → analyze-project}/analyze-routes.js +1 -1
  7. package/dist/src/migration/ember-app/steps/analyze-project.js +7 -0
  8. package/dist/src/migration/ember-app/steps/import-styles-in-components.js +1 -1
  9. package/dist/src/migration/ember-app/steps/import-styles-in-routes.js +1 -1
  10. package/dist/src/migration/ember-app/steps/index.js +1 -2
  11. package/dist/src/migration/ember-app/steps/update-component-templates.js +1 -1
  12. package/dist/src/migration/ember-app/steps/update-route-templates.js +1 -1
  13. package/dist/src/migration/ember-v2-addon/index.js +8 -0
  14. package/dist/src/migration/ember-v2-addon/steps/analyze-project/analyze-components.js +43 -0
  15. package/dist/src/migration/ember-v2-addon/steps/analyze-project/index.js +1 -0
  16. package/dist/src/migration/ember-v2-addon/steps/analyze-project.js +7 -0
  17. package/dist/src/migration/ember-v2-addon/steps/import-styles-in-components.js +35 -0
  18. package/dist/src/migration/ember-v2-addon/steps/index.js +3 -0
  19. package/dist/src/migration/ember-v2-addon/steps/update-component-templates.js +22 -0
  20. package/dist/src/migration/index.js +1 -0
  21. package/dist/src/{migration/ember-app → utils}/steps/create-options.js +5 -4
  22. package/dist/src/{migration/ember-app → utils}/steps/import-styles/create-class.js +1 -1
  23. package/dist/src/{migration/ember-app → utils}/steps/import-styles/update-class.js +16 -0
  24. package/package.json +6 -6
  25. package/dist/src/migration/ember-app/steps/analyze-app.js +0 -7
  26. /package/dist/src/migration/ember-app/steps/{analyze-app → analyze-project}/index.js +0 -0
  27. /package/dist/src/{migration/ember-app/steps/analyze-app → utils/steps/analyze-project}/analyze-file-paths.js +0 -0
  28. /package/dist/src/{migration/ember-app → utils}/steps/import-styles/index.js +0 -0
  29. /package/dist/src/{migration/ember-app → utils}/steps/update-templates/index.js +0 -0
  30. /package/dist/src/{migration/ember-app → utils}/steps/update-templates/update-template.js +0 -0
package/README.md CHANGED
@@ -18,14 +18,18 @@ _Codemod to replace `ember-css-modules` with `embroider-css-modules`_
18
18
 
19
19
  ## Features
20
20
 
21
- - Preserves your code whenever possible
22
- - Supports [`glint`](https://typed-ember.gitbook.io/glint/)
23
- - Focuses on maintainability and extensibility
21
+ The codemod helps you:
22
+
23
+ - Remove `ember-css-modules` syntax from an Embroider app
24
+ - Set up `embroider-css-modules` on an Embroider app
25
+ - Remove `ember-css-modules` syntax from a v2 addon
26
+
27
+ It takes [`glint`](https://typed-ember.gitbook.io/glint/) into account, and preserves your code whenever possible.
24
28
 
25
29
 
26
30
  ## Usage
27
31
 
28
- You can check [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/167) as a reference.
32
+ You can find a migration example in [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/167).
29
33
 
30
34
  Step 1. Quickly migrate to [`embroider-css-modules`](https://github.com/ijlee2/embroider-css-modules).<sup>1</sup>
31
35
 
@@ -47,24 +51,34 @@ Step 2. Review the project.
47
51
 
48
52
  ### Arguments
49
53
 
54
+ You must pass `--type` to indicate what type of project you have.
55
+
56
+ ```sh
57
+ npx ember-codemod-remove-ember-css-modules --type app
58
+ npx ember-codemod-remove-ember-css-modules --type v2-addon
59
+ ```
60
+
61
+
50
62
  <details>
63
+
51
64
  <summary>Optional: Specify the component structure</summary>
52
65
 
53
66
  By default, an Octane project has the flat component structure. Pass `--component-structure` to indicate otherwise.
54
67
 
55
68
  ```sh
56
- npx ember-codemod-remove-ember-css-modules --component-structure="nested"
69
+ npx ember-codemod-remove-ember-css-modules --component-structure nested
57
70
  ```
58
71
 
59
72
  </details>
60
73
 
61
74
  <details>
75
+
62
76
  <summary>Optional: Specify the project root</summary>
63
77
 
64
78
  Pass `--root` to run the codemod on a project somewhere else (i.e. not in the current directory).
65
79
 
66
80
  ```sh
67
- npx ember-codemod-remove-ember-css-modules --root=<path/to/your/project>
81
+ npx ember-codemod-remove-ember-css-modules --root <path/to/your/project>
68
82
  ```
69
83
 
70
84
  </details>
@@ -74,6 +88,14 @@ npx ember-codemod-remove-ember-css-modules --root=<path/to/your/project>
74
88
 
75
89
  The codemod is designed to cover typical uses of `ember-css-modules`. It is not designed to cover one-off cases.
76
90
 
91
+ <details>
92
+
93
+ <summary>V2 Addons</summary>
94
+
95
+ The codemod updates components only. Please see [Set up CSS modules (v2 addons)](../../docs/written-guides/set-up-css-modules-v2-addons.md) to set up `embroider-css-modules`.
96
+
97
+ </details>
98
+
77
99
  To better meet your needs, consider cloning the repo and running the codemod locally.
78
100
 
79
101
  ```sh
@@ -17,10 +17,17 @@ const argv = yargs(hideBin(process.argv))
17
17
  .option('root', {
18
18
  describe: 'Location of your Ember project',
19
19
  type: 'string',
20
+ })
21
+ .option('type', {
22
+ choices: ['app', 'v2-addon'],
23
+ demandOption: true,
24
+ describe: 'Type of your Ember project',
25
+ type: 'string',
20
26
  })
21
27
  .parseSync();
22
28
  const codemodOptions = {
23
29
  componentStructure: argv['component-structure'],
24
30
  projectRoot: argv['root'] ?? process.cwd(),
31
+ projectType: argv['type'],
25
32
  };
26
33
  removeEmberCssModules(codemodOptions);
package/dist/src/index.js CHANGED
@@ -1,4 +1,13 @@
1
- import { migrateEmberApp } from './migration/index.js';
1
+ import { migrateEmberApp, migrateEmberV2Addon } from './migration/index.js';
2
2
  export function removeEmberCssModules(codemodOptions) {
3
- migrateEmberApp(codemodOptions);
3
+ switch (codemodOptions.projectType) {
4
+ case 'app': {
5
+ migrateEmberApp(codemodOptions);
6
+ break;
7
+ }
8
+ case 'v2-addon': {
9
+ migrateEmberV2Addon(codemodOptions);
10
+ break;
11
+ }
12
+ }
4
13
  }
@@ -1,4 +1,5 @@
1
- import { analyzeApp, createOptions, importStylesInComponents, importStylesInRoutes, moveStylesheets, updateAppAppJs, updateComponentTemplates, updatePackageJson, updateRouteTemplates, } from './steps/index.js';
1
+ import { createOptions } from '../../utils/steps/create-options.js';
2
+ import { analyzeProject, importStylesInComponents, importStylesInRoutes, moveStylesheets, updateAppAppJs, updateComponentTemplates, updatePackageJson, updateRouteTemplates, } from './steps/index.js';
2
3
  export function migrateEmberApp(codemodOptions) {
3
4
  const options = createOptions(codemodOptions);
4
5
  const { hasEmberCssModules } = options.project;
@@ -7,7 +8,7 @@ export function migrateEmberApp(codemodOptions) {
7
8
  return;
8
9
  }
9
10
  // Prepare for migration
10
- const context = analyzeApp(options);
11
+ const context = analyzeProject(options);
11
12
  // Import styles in classes
12
13
  moveStylesheets(options);
13
14
  importStylesInComponents(context, options);
@@ -1,5 +1,5 @@
1
1
  import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
2
- import { analyzeFilePaths } from './analyze-file-paths.js';
2
+ import { analyzeFilePaths } from '../../../../utils/steps/analyze-project/analyze-file-paths.js';
3
3
  export function analyzeComponents(options) {
4
4
  const { componentStructure, projectRoot } = options;
5
5
  const classFilePaths = findFiles('app/components/**/*.{js,ts}', {
@@ -1,5 +1,5 @@
1
1
  import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
2
- import { analyzeFilePaths } from './analyze-file-paths.js';
2
+ import { analyzeFilePaths } from '../../../../utils/steps/analyze-project/analyze-file-paths.js';
3
3
  export function analyzeRoutes(options) {
4
4
  const { projectRoot } = options;
5
5
  const classFilePaths = findFiles('app/controllers/**/*.{js,ts}', {
@@ -0,0 +1,7 @@
1
+ import { analyzeComponents, analyzeRoutes } from './analyze-project/index.js';
2
+ export function analyzeProject(options) {
3
+ return {
4
+ components: analyzeComponents(options),
5
+ routes: analyzeRoutes(options),
6
+ };
7
+ }
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { importStyles } from './import-styles/index.js';
2
+ import { importStyles } from '../../../utils/steps/import-styles/index.js';
3
3
  function getBlueprintFilePaths(options) {
4
4
  const { project } = options;
5
5
  if (project.hasTypeScript) {
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { importStyles } from './import-styles/index.js';
2
+ import { importStyles } from '../../../utils/steps/import-styles/index.js';
3
3
  function getBlueprintFilePaths(options) {
4
4
  const { project } = options;
5
5
  if (project.hasTypeScript) {
@@ -1,5 +1,4 @@
1
- export * from './analyze-app.js';
2
- export * from './create-options.js';
1
+ export * from './analyze-project.js';
3
2
  export * from './import-styles-in-components.js';
4
3
  export * from './import-styles-in-routes.js';
5
4
  export * from './move-stylesheets.js';
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { updateTemplates } from './update-templates/index.js';
2
+ import { updateTemplates } from '../../../utils/steps/update-templates/index.js';
3
3
  function getFilePath(options) {
4
4
  const { componentStructure } = options;
5
5
  return function (entityName) {
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { updateTemplates } from './update-templates/index.js';
2
+ import { updateTemplates } from '../../../utils/steps/update-templates/index.js';
3
3
  function getFilePath() {
4
4
  return function (entityName) {
5
5
  let filePath = join('app/templates', entityName);
@@ -0,0 +1,8 @@
1
+ import { createOptions } from '../../utils/steps/create-options.js';
2
+ import { analyzeProject, importStylesInComponents, updateComponentTemplates, } from './steps/index.js';
3
+ export function migrateEmberV2Addon(codemodOptions) {
4
+ const options = createOptions(codemodOptions);
5
+ const context = analyzeProject(options);
6
+ importStylesInComponents(context, options);
7
+ updateComponentTemplates(context, options);
8
+ }
@@ -0,0 +1,43 @@
1
+ import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
2
+ import { analyzeFilePaths } from '../../../../utils/steps/analyze-project/analyze-file-paths.js';
3
+ export function analyzeComponents(options) {
4
+ const { componentStructure, projectRoot } = options;
5
+ const classFilePaths = findFiles('src/components/**/*.{js,ts}', {
6
+ ignoreList: ['src/components/**/*.d.ts'],
7
+ projectRoot,
8
+ }).map((filePath) => {
9
+ return renamePathByDirectory(filePath, {
10
+ from: 'src/components',
11
+ to: '',
12
+ });
13
+ });
14
+ const stylesheetFilePaths = findFiles('src/components/**/*.css', {
15
+ projectRoot,
16
+ }).map((filePath) => {
17
+ return renamePathByDirectory(filePath, {
18
+ from: 'src/components',
19
+ to: '',
20
+ });
21
+ });
22
+ const templateFilePaths = findFiles('src/components/**/*.hbs', {
23
+ projectRoot,
24
+ }).map((filePath) => {
25
+ return renamePathByDirectory(filePath, {
26
+ from: 'src/components',
27
+ to: '',
28
+ });
29
+ });
30
+ const filePaths = [
31
+ ...classFilePaths,
32
+ ...stylesheetFilePaths,
33
+ ...templateFilePaths,
34
+ ].sort();
35
+ const entities = analyzeFilePaths(filePaths);
36
+ if (componentStructure === 'nested') {
37
+ return new Map(Array.from(entities.entries()).map(([entityName, extensions]) => {
38
+ const newEntityName = entityName.replace(/\/index$/, '');
39
+ return [newEntityName, extensions];
40
+ }));
41
+ }
42
+ return entities;
43
+ }
@@ -0,0 +1 @@
1
+ export * from './analyze-components.js';
@@ -0,0 +1,7 @@
1
+ import { analyzeComponents } from './analyze-project/index.js';
2
+ export function analyzeProject(options) {
3
+ return {
4
+ components: analyzeComponents(options),
5
+ routes: new Map(),
6
+ };
7
+ }
@@ -0,0 +1,35 @@
1
+ import { join } from 'node:path';
2
+ import { importStyles } from '../../../utils/steps/import-styles/index.js';
3
+ function getBlueprintFilePaths(options) {
4
+ const { project } = options;
5
+ if (project.hasTypeScript) {
6
+ return ['ember-cli/component/typescript.ts'];
7
+ }
8
+ return ['ember-cli/component/javascript.js'];
9
+ }
10
+ function getFilePath(options) {
11
+ const { componentStructure, project } = options;
12
+ return function (entityName) {
13
+ let filePath = join('src/components', entityName);
14
+ if (componentStructure === 'nested') {
15
+ filePath += '/index';
16
+ }
17
+ if (project.hasTypeScript) {
18
+ filePath += '.ts';
19
+ }
20
+ else {
21
+ filePath += '.js';
22
+ }
23
+ return filePath;
24
+ };
25
+ }
26
+ export function importStylesInComponents(context, options) {
27
+ const customizations = {
28
+ blueprintFilePaths: getBlueprintFilePaths(options),
29
+ getFilePath: getFilePath(options),
30
+ };
31
+ importStyles(context.components, {
32
+ customizations,
33
+ options,
34
+ });
35
+ }
@@ -0,0 +1,3 @@
1
+ export * from './analyze-project.js';
2
+ export * from './import-styles-in-components.js';
3
+ export * from './update-component-templates.js';
@@ -0,0 +1,22 @@
1
+ import { join } from 'node:path';
2
+ import { updateTemplates } from '../../../utils/steps/update-templates/index.js';
3
+ function getFilePath(options) {
4
+ const { componentStructure } = options;
5
+ return function (entityName) {
6
+ let filePath = join('src/components', entityName);
7
+ if (componentStructure === 'nested') {
8
+ filePath += '/index';
9
+ }
10
+ filePath += '.hbs';
11
+ return filePath;
12
+ };
13
+ }
14
+ export function updateComponentTemplates(context, options) {
15
+ const customizations = {
16
+ getFilePath: getFilePath(options),
17
+ };
18
+ updateTemplates(context.components, {
19
+ customizations,
20
+ options,
21
+ });
22
+ }
@@ -1 +1,2 @@
1
1
  export * from './ember-app/index.js';
2
+ export * from './ember-v2-addon/index.js';
@@ -13,11 +13,12 @@ function analyzePackageJson(codemodOptions) {
13
13
  };
14
14
  }
15
15
  export function createOptions(codemodOptions) {
16
+ const { componentStructure, projectRoot, projectType } = codemodOptions;
16
17
  const project = analyzePackageJson(codemodOptions);
17
- const options = {
18
- componentStructure: codemodOptions.componentStructure,
18
+ return {
19
+ componentStructure,
19
20
  project,
20
- projectRoot: codemodOptions.projectRoot,
21
+ projectRoot,
22
+ projectType,
21
23
  };
22
- return options;
23
24
  }
@@ -3,7 +3,7 @@ import { join } from 'node:path';
3
3
  import { processTemplate } from '@codemod-utils/blueprints';
4
4
  import { classify, doubleColonize } from '@codemod-utils/ember-cli-string';
5
5
  import { createFiles, parseFilePath } from '@codemod-utils/files';
6
- import { blueprintsRoot } from '../../../../utils/blueprints.js';
6
+ import { blueprintsRoot } from '../../blueprints.js';
7
7
  export function createClass(entityName, { customizations, options }) {
8
8
  const { blueprintFilePaths, getFilePath } = customizations;
9
9
  const entity = {
@@ -3,6 +3,19 @@ import { readFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
4
  import { AST } from '@codemod-utils/ast-javascript';
5
5
  import { createFiles, parseFilePath } from '@codemod-utils/files';
6
+ function canSkip(file, data) {
7
+ const traverse = AST.traverse(data.isTypeScript);
8
+ let canSkip = false;
9
+ traverse(file, {
10
+ visitImportDeclaration(path) {
11
+ if (path.node.source.value === `./${data.fileName}.css`) {
12
+ canSkip = true;
13
+ }
14
+ return false;
15
+ },
16
+ });
17
+ return canSkip;
18
+ }
6
19
  function removeTemplateOnlyComponentMethod(file, data) {
7
20
  const traverse = AST.traverse(data.isTypeScript);
8
21
  const ast = traverse(file, {
@@ -86,6 +99,9 @@ export function updateClass(entityName, { customizations, options }) {
86
99
  };
87
100
  try {
88
101
  let file = readFileSync(join(projectRoot, filePath), 'utf8');
102
+ if (canSkip(file, data)) {
103
+ return;
104
+ }
89
105
  file = removeTemplateOnlyComponentMethod(file, data);
90
106
  file = importStylesInClass(file, data);
91
107
  file = addStylesAsClassProperty(file, data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-codemod-remove-ember-css-modules",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "Codemod to replace ember-css-modules with embroider-css-modules",
5
5
  "keywords": [
6
6
  "codemod",
@@ -37,15 +37,15 @@
37
37
  "devDependencies": {
38
38
  "@codemod-utils/tests": "^1.1.2",
39
39
  "@sondr3/minitest": "^0.1.2",
40
- "@types/node": "^18.19.17",
40
+ "@types/node": "^18.19.23",
41
41
  "@types/yargs": "^17.0.32",
42
42
  "concurrently": "^8.2.2",
43
- "eslint": "^8.56.0",
43
+ "eslint": "^8.57.0",
44
44
  "prettier": "^3.2.5",
45
- "typescript": "^5.3.3",
45
+ "typescript": "^5.4.2",
46
+ "@shared-configs/eslint-config-node": "0.0.0",
46
47
  "@shared-configs/typescript": "0.0.0",
47
- "@shared-configs/prettier": "0.0.0",
48
- "@shared-configs/eslint-config-node": "0.0.0"
48
+ "@shared-configs/prettier": "0.0.0"
49
49
  },
50
50
  "engines": {
51
51
  "node": "18.* || >= 20"
@@ -1,7 +0,0 @@
1
- import { analyzeComponents, analyzeRoutes } from './analyze-app/index.js';
2
- export function analyzeApp(options) {
3
- return {
4
- components: analyzeComponents(options),
5
- routes: analyzeRoutes(options),
6
- };
7
- }