ember-codemod-remove-ember-css-modules 1.1.3 → 2.0.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 (35) hide show
  1. package/README.md +34 -176
  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 -10
  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 -4
  11. package/dist/src/migration/ember-app/steps/move-stylesheets.js +10 -0
  12. package/dist/src/migration/ember-app/steps/update-component-templates.js +1 -1
  13. package/dist/src/migration/ember-app/steps/update-route-templates.js +1 -1
  14. package/dist/src/migration/ember-v2-addon/index.js +8 -0
  15. package/dist/src/migration/ember-v2-addon/steps/analyze-project/analyze-components.js +43 -0
  16. package/dist/src/migration/ember-v2-addon/steps/analyze-project/index.js +1 -0
  17. package/dist/src/migration/ember-v2-addon/steps/analyze-project.js +7 -0
  18. package/dist/src/migration/ember-v2-addon/steps/import-styles-in-components.js +35 -0
  19. package/dist/src/migration/ember-v2-addon/steps/index.js +3 -0
  20. package/dist/src/migration/ember-v2-addon/steps/update-component-templates.js +22 -0
  21. package/dist/src/migration/index.js +1 -0
  22. package/dist/src/utils/blueprints.js +0 -1
  23. package/dist/src/{migration/ember-app → utils}/steps/create-options.js +5 -4
  24. package/dist/src/{migration/ember-app → utils}/steps/import-styles/create-class.js +1 -1
  25. package/dist/src/{migration/ember-app → utils}/steps/import-styles/update-class.js +16 -0
  26. package/package.json +6 -6
  27. package/dist/src/migration/ember-app/steps/analyze-app.js +0 -7
  28. package/dist/src/migration/ember-app/steps/update-app-app-js.js +0 -46
  29. package/dist/src/migration/ember-app/steps/update-package-json.js +0 -47
  30. package/dist/src/utils/blueprints/get-version.js +0 -19
  31. /package/dist/src/migration/ember-app/steps/{analyze-app → analyze-project}/index.js +0 -0
  32. /package/dist/src/{migration/ember-app/steps/analyze-app → utils/steps/analyze-project}/analyze-file-paths.js +0 -0
  33. /package/dist/src/{migration/ember-app → utils}/steps/import-styles/index.js +0 -0
  34. /package/dist/src/{migration/ember-app → utils}/steps/update-templates/index.js +0 -0
  35. /package/dist/src/{migration/ember-app → utils}/steps/update-templates/update-template.js +0 -0
package/README.md CHANGED
@@ -8,9 +8,6 @@ _Codemod to replace `ember-css-modules` with `embroider-css-modules`_
8
8
  1. [Usage](#usage)
9
9
  - [Arguments](#arguments)
10
10
  - [Limitations](#limitations)
11
- 1. [How to refactor code](#how-to-refactor-code)
12
- - [Remove code inheritance](#remove-code-inheritance)
13
- - [Remove complex string concatenations](#remove-complex-string-concatenations)
14
11
  1. [Compatibility](#compatibility)
15
12
  1. [Contributing](#contributing)
16
13
  1. [License](#license)
@@ -18,235 +15,96 @@ _Codemod to replace `ember-css-modules` with `embroider-css-modules`_
18
15
 
19
16
  ## Features
20
17
 
21
- - Preserves your code whenever possible
22
- - Supports [`glint`](https://typed-ember.gitbook.io/glint/)
23
- - Focuses on maintainability and extensibility
18
+ The codemod helps you:
19
+
20
+ - Remove `ember-css-modules` syntax from an Embroider app
21
+ - Remove `ember-css-modules` syntax from a v2 addon
22
+
23
+ It preserves your code whenever possible.
24
24
 
25
25
 
26
26
  ## Usage
27
27
 
28
- You can check [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/167) as a reference.
28
+ You can find a migration example in [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/167).
29
29
 
30
- Step 1. Quickly migrate to [`embroider-css-modules`](https://github.com/ijlee2/embroider-css-modules).<sup>1</sup>
30
+ Step 1. Quickly remove `ember-css-modules` syntax.<sup>1</sup>
31
31
 
32
32
  ```sh
33
33
  cd <path/to/your/project>
34
34
  npx ember-codemod-remove-ember-css-modules <arguments>
35
35
  ```
36
36
 
37
- Step 2. Review the project.
37
+ Manually remove the remaining instances of `local-class` attributes and `{{local-class}}` helpers.
38
+
39
+ Step 2. Update project configurations.
38
40
 
39
- - [x] Update the configuration files.<sup>2</sup>
40
- - [x] Remove the remaining instances of `local-class` attributes and `{{local-class}}` helpers from `ember-css-modules`.
41
+ - [x] Set up CSS modules (see the guides for [apps](../../docs/written-guides/set-up-css-modules-apps.md) and [v2 addons](../../docs/written-guides/set-up-css-modules-v2-addons.md)).
41
42
  - [x] Confirm that you can run all scripts in `package.json`.
42
43
 
43
- <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>
44
+ <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](../../docs/refactor-code.md) to help the codemod update templates correctly.</sup>
44
45
 
45
46
  <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>
46
47
 
47
48
 
48
49
  ### Arguments
49
50
 
50
- <details>
51
- <summary>Optional: Specify the component structure</summary>
52
-
53
- By default, an Octane project has the flat component structure. Pass `--component-structure` to indicate otherwise.
51
+ You must pass `--type` to indicate what type of project you have.
54
52
 
55
53
  ```sh
56
- npx ember-codemod-remove-ember-css-modules --component-structure="nested"
54
+ npx ember-codemod-remove-ember-css-modules --type app
55
+ npx ember-codemod-remove-ember-css-modules --type v2-addon
57
56
  ```
58
57
 
59
- </details>
60
58
 
61
59
  <details>
62
- <summary>Optional: Specify the project root</summary>
63
60
 
64
- Pass `--root` to run the codemod on a project somewhere else (i.e. not in the current directory).
65
-
66
- ```sh
67
- npx ember-codemod-remove-ember-css-modules --root=<path/to/your/project>
68
- ```
69
-
70
- </details>
71
-
72
-
73
- ### Limitations
74
-
75
- The codemod is designed to cover typical uses of `ember-css-modules`. It is not designed to cover one-off cases.
61
+ <summary>Optional: Specify the component structure</summary>
76
62
 
77
- To better meet your needs, consider cloning the repo and running the codemod locally.
63
+ By default, an Embroider project has the flat component structure. Pass `--component-structure` to indicate otherwise.
78
64
 
79
65
  ```sh
80
- cd <path/to/cloned/repo>
81
-
82
- # Compile TypeScript
83
- pnpm build
84
-
85
- # Run codemod
86
- ./dist/bin/ember-codemod-remove-ember-css-modules.js --root=<path/to/your/project>
87
- ```
88
-
89
-
90
- ## How to refactor code
91
-
92
- ### Remove code inheritance
93
-
94
- `ember-css-modules` allows composing (really, inheriting) CSS code in two ways:
95
-
96
- - `composes: ... from '...';` in `*.css`
97
- - `{{local-class ... from="..."}}` in `*.hbs`
98
-
99
- The first syntax will continue to work in an Embroider app, provided that the import path is either `global` or a relative path.
100
-
101
- ```css
102
- /* app/components/ui/form/textarea.css */
103
- .textarea {
104
- composes: input from "./input.css";
105
- }
106
-
107
- .is-disabled {
108
- composes: input-disabled from global;
109
- }
110
-
111
- /* These do not work */
112
- .textarea {
113
- composes: input from "my-app/components/ui/form/input.css";
114
- }
115
-
116
- .textarea {
117
- composes: input from "my-v2-addon/components/ui/form/input.css";
118
- }
119
- ```
120
-
121
- The second syntax isn't supported by the `{{local}}` helper from `embroider-css-modules`, so you will need to update the template and stylesheet accordingly.
122
-
123
- However, note that the presence of `composes` (in a set of related components) may indicate a premature abstraction and an incorrect component design. Ideally, you might duplicate the CSS, then refactor the components. If short on time, you can import the relevant `styles` object in the backing class.
124
-
125
- <details>
126
-
127
- <summary>Before, with <code>ember-css-modules</code></summary>
128
-
129
- Case 1:
130
-
131
- ```hbs
132
- {{! app/components/ui/form/textarea.hbs }}
133
- <textarea
134
- class={{local-class "input" from="my-app/components/ui/form/input.css"}}
135
- />
136
- ```
137
-
138
- Case 2:
139
-
140
- ```css
141
- /* app/components/ui/form/textarea.css */
142
- .textarea {
143
- composes: input from "my-app/components/ui/form/input.css";
144
- }
145
- ```
146
-
147
- ```hbs
148
- {{! app/components/ui/form/textarea.hbs }}
149
- <textarea
150
- local-class="textarea"
151
- />
66
+ npx ember-codemod-remove-ember-css-modules --component-structure nested
152
67
  ```
153
68
 
154
69
  </details>
155
70
 
156
71
  <details>
157
72
 
158
- <summary>After, with <code>embroider-css-modules</code></summary>
159
-
160
- ```ts
161
- /* app/components/ui/form/textarea.ts */
162
- import Component from '@glimmer/component';
163
-
164
- import inputStyles from './input.css';
165
- import styles from './textarea.css';
73
+ <summary>Optional: Specify the project root</summary>
166
74
 
167
- export default class UiFormTextareaComponent extends Component {
168
- inputStyles = inputStyles;
169
- styles = styles;
170
- }
171
- ```
75
+ Pass `--root` to run the codemod on a project somewhere else (i.e. not in the current directory).
172
76
 
173
- ```hbs
174
- {{! app/components/ui/form/textarea.hbs }}
175
- <textarea
176
- class={{this.inputStyles.input}}
177
- />
77
+ ```sh
78
+ npx ember-codemod-remove-ember-css-modules --root <path/to/your/project>
178
79
  ```
179
80
 
180
81
  </details>
181
82
 
182
83
 
183
- ### Remove complex string concatenations
84
+ ### Limitations
184
85
 
185
- In `ember-css-modules`, a string can represent multiple local class names via concatenation. In `embroider-css-modules`, each string represents exactly one.
86
+ The codemod is designed to cover typical uses of `ember-css-modules`. It is not designed to cover one-off cases.
186
87
 
187
88
  <details>
188
89
 
189
- <summary>Before, with <code>ember-css-modules</code></summary>
190
-
191
- ```hbs
192
- {{! app/components/ui/form/textarea.hbs }}
193
- <textarea
194
- local-class="
195
- textarea
196
- {{if (or @isDisabled @isReadOnly) 'is-disabled'}}
197
- "
198
- />
199
- ```
200
-
201
- </details>
202
-
203
- <details>
90
+ <summary>V2 Addons</summary>
204
91
 
205
- <summary>After, with <code>embroider-css-modules</code></summary>
206
-
207
- ```hbs
208
- {{! app/components/ui/form/textarea.hbs }}
209
- <textarea
210
- class={{local-class
211
- this.styles
212
- "textarea"
213
- (if (or @isDisabled @isReadOnly) "is-disabled")
214
- }}
215
- />
216
- ```
92
+ 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`.
217
93
 
218
94
  </details>
219
95
 
220
- 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.
221
-
222
- <details>
223
-
224
- <summary>Before refactor, with <code>ember-css-modules</code></summary>
225
-
226
- ```hbs
227
- {{! app/components/ui/form/phone.hbs }}
228
- <input
229
- local-class="input flag-{{@country}}"
230
- type="tel"
231
- />
232
- ```
233
-
234
- </details>
96
+ To better meet your needs, consider cloning the repo and running the codemod locally.
235
97
 
236
- <details>
98
+ ```sh
99
+ cd <path/to/cloned/repo>
237
100
 
238
- <summary>After refactor, with <code>ember-css-modules</code></summary>
101
+ # Compile TypeScript
102
+ pnpm build
239
103
 
240
- ```hbs
241
- {{! app/components/ui/form/phone.hbs }}
242
- <input
243
- local-class="input {{concat 'flag-' @country}}"
244
- type="tel"
245
- />
104
+ # Run codemod
105
+ ./dist/bin/ember-codemod-remove-ember-css-modules.js --root=<path/to/your/project>
246
106
  ```
247
107
 
248
- </details>
249
-
250
108
 
251
109
  ## Compatibility
252
110
 
@@ -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,13 +1,9 @@
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, updateComponentTemplates, updateRouteTemplates, } from './steps/index.js';
2
3
  export function migrateEmberApp(codemodOptions) {
3
4
  const options = createOptions(codemodOptions);
4
- const { hasEmberCssModules } = options.project;
5
- // Guarantee idempotency
6
- if (!hasEmberCssModules) {
7
- return;
8
- }
9
5
  // Prepare for migration
10
- const context = analyzeApp(options);
6
+ const context = analyzeProject(options);
11
7
  // Import styles in classes
12
8
  moveStylesheets(options);
13
9
  importStylesInComponents(context, options);
@@ -15,7 +11,4 @@ export function migrateEmberApp(codemodOptions) {
15
11
  // Update templates
16
12
  updateComponentTemplates(context, options);
17
13
  updateRouteTemplates(context, options);
18
- // Fine-tune individual files
19
- updateAppAppJs(options);
20
- updatePackageJson(options);
21
14
  }
@@ -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,9 +1,6 @@
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';
6
- export * from './update-app-app-js.js';
7
5
  export * from './update-component-templates.js';
8
- export * from './update-package-json.js';
9
6
  export * from './update-route-templates.js';
@@ -1,4 +1,11 @@
1
1
  import { createFiles, findFiles, mapFilePaths, moveFiles, } from '@codemod-utils/files';
2
+ function canSkip(options) {
3
+ const { projectRoot } = options;
4
+ const filePaths = findFiles('app/assets/app.css', {
5
+ projectRoot,
6
+ });
7
+ return filePaths.length === 1;
8
+ }
2
9
  function moveRouteStylesheets(options) {
3
10
  const { projectRoot } = options;
4
11
  const filePaths = findFiles('app/styles/**/*.css', {
@@ -12,6 +19,9 @@ function moveRouteStylesheets(options) {
12
19
  moveFiles(pathMapping, options);
13
20
  }
14
21
  function moveAppCssToAssets(options) {
22
+ if (canSkip(options)) {
23
+ return;
24
+ }
15
25
  const { projectRoot } = options;
16
26
  const filePaths = findFiles('app/styles/app.css', {
17
27
  projectRoot,
@@ -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';
@@ -1,2 +1 @@
1
1
  export * from './blueprints/blueprints-root.js';
2
- export * from './blueprints/get-version.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": "2.0.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",
46
- "@shared-configs/typescript": "0.0.0",
45
+ "typescript": "^5.4.2",
46
+ "@shared-configs/eslint-config-node": "0.0.0",
47
47
  "@shared-configs/prettier": "0.0.0",
48
- "@shared-configs/eslint-config-node": "0.0.0"
48
+ "@shared-configs/typescript": "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
- }
@@ -1,46 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { extname, join } from 'node:path';
3
- import { AST } from '@codemod-utils/ast-javascript';
4
- import { createFiles, findFiles } from '@codemod-utils/files';
5
- function addCssEntryPoint(file, data) {
6
- const traverse = AST.traverse(data.isTypeScript);
7
- const ast = traverse(file, {
8
- visitProgram(path) {
9
- const nodesToAdd = [
10
- AST.builders.importDeclaration([], AST.builders.literal('./assets/app.css')),
11
- AST.builders.noop(),
12
- ];
13
- path.value.body.unshift(...nodesToAdd);
14
- return false;
15
- },
16
- });
17
- return AST.print(ast);
18
- }
19
- export function updateAppAppJs(options) {
20
- const { projectRoot } = options;
21
- const filePaths = findFiles('app/app.{js,ts}', {
22
- projectRoot,
23
- });
24
- if (filePaths.length !== 1) {
25
- console.warn('WARNING: updateAppAppJs could not find app.{js,ts} in the app folder. Will skip this step.\n');
26
- return;
27
- }
28
- const filePath = filePaths[0];
29
- const fileExtension = extname(filePath);
30
- const data = {
31
- isTypeScript: fileExtension === '.ts',
32
- };
33
- try {
34
- let file = readFileSync(join(projectRoot, filePath), 'utf8');
35
- file = addCssEntryPoint(file, data);
36
- const fileMap = new Map([[filePath, file]]);
37
- createFiles(fileMap, options);
38
- }
39
- catch (error) {
40
- let message = `WARNING: updateAppAppJs could not update \`${filePath}\`. Please update the file manually.`;
41
- if (error instanceof Error) {
42
- message += ` (${error.message})`;
43
- }
44
- console.warn(`${message}\n`);
45
- }
46
- }
@@ -1,47 +0,0 @@
1
- import { writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { convertToMap, convertToObject, readPackageJson, } from '@codemod-utils/json';
4
- import { getVersion } from '../../../utils/blueprints.js';
5
- function updateDevDependencies(packageJson, options) {
6
- const { project } = options;
7
- const devDependencies = convertToMap(packageJson['devDependencies']);
8
- const packagesToDelete = ['ember-css-modules'];
9
- packagesToDelete.forEach((packageName) => {
10
- devDependencies.delete(packageName);
11
- });
12
- const packagesToInstall = new Set([
13
- '@embroider/compat',
14
- '@embroider/core',
15
- '@embroider/webpack',
16
- 'autoprefixer',
17
- 'embroider-css-modules',
18
- 'postcss',
19
- 'postcss-loader',
20
- 'webpack',
21
- ]);
22
- if (project.hasTypeScript) {
23
- packagesToInstall.add('type-css-modules');
24
- }
25
- [...packagesToInstall].sort().forEach((packageName) => {
26
- const version = getVersion(packageName, options);
27
- devDependencies.set(packageName, version);
28
- });
29
- packageJson['devDependencies'] = convertToObject(devDependencies);
30
- }
31
- function updateScripts(packageJson, options) {
32
- const { project } = options;
33
- const scripts = convertToMap(packageJson.scripts);
34
- if (project.hasTypeScript) {
35
- scripts.set('prelint:types', 'type-css-modules --src app');
36
- }
37
- packageJson['scripts'] = convertToObject(scripts);
38
- }
39
- export function updatePackageJson(options) {
40
- const { projectRoot } = options;
41
- const packageJson = readPackageJson(options);
42
- updateDevDependencies(packageJson, options);
43
- updateScripts(packageJson, options);
44
- const destination = join(projectRoot, 'package.json');
45
- const file = JSON.stringify(packageJson, null, 2) + '\n';
46
- writeFileSync(destination, file, 'utf8');
47
- }
@@ -1,19 +0,0 @@
1
- import { decideVersion } from '@codemod-utils/blueprints';
2
- const latestVersions = new Map([
3
- ['@embroider/compat', '3.2.1'],
4
- ['@embroider/core', '3.2.1'],
5
- ['@embroider/webpack', '3.1.5'],
6
- ['autoprefixer', '10.4.15'],
7
- ['embroider-css-modules', '1.0.0'],
8
- ['postcss', '8.4.29'],
9
- ['postcss-loader', '7.3.3'],
10
- ['type-css-modules', '1.0.0'],
11
- ['webpack', '5.88.2'],
12
- ]);
13
- export function getVersion(packageName, options) {
14
- const { project } = options;
15
- return decideVersion(packageName, {
16
- dependencies: project.dependencies,
17
- latestVersions,
18
- });
19
- }