ember-codemod-remove-ember-css-modules 0.3.0 → 0.4.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/README.md CHANGED
@@ -4,6 +4,17 @@
4
4
 
5
5
  _Codemod to replace `ember-css-modules` with `embroider-css-modules`_
6
6
 
7
+ 1. [Features](#features)
8
+ 1. [Usage](#usage)
9
+ - [Arguments](#arguments)
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
+ 1. [Compatibility](#compatibility)
15
+ 1. [Contributing](#contributing)
16
+ 1. [License](#license)
17
+
7
18
 
8
19
  ## Features
9
20
 
@@ -98,7 +109,7 @@ Case 1:
98
109
  ```hbs
99
110
  {{! app/components/ui/form/textarea.hbs }}
100
111
  <textarea
101
- class={{local-class "input" from "app/components/ui/form/input.css"}}
112
+ class={{local-class "input" from="app/components/ui/form/input.css"}}
102
113
  />
103
114
  ```
104
115
 
@@ -217,7 +228,7 @@ The codemod may fail to update complex expressions. Refactor templates to provid
217
228
 
218
229
  ## Compatibility
219
230
 
220
- * Node.js v16 or above
231
+ - Node.js v16 or above
221
232
 
222
233
 
223
234
  ## Contributing
@@ -0,0 +1,43 @@
1
+ import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
2
+ import { analyzeFilePaths } from './analyze-file-paths.js';
3
+ export function analyzeComponents(options) {
4
+ const { componentStructure, projectRoot } = options;
5
+ const classFilePaths = findFiles('app/components/**/*.{js,ts}', {
6
+ ignoreList: ['app/components/**/*.d.ts'],
7
+ projectRoot,
8
+ }).map((filePath) => {
9
+ return renamePathByDirectory(filePath, {
10
+ from: 'app/components',
11
+ to: '',
12
+ });
13
+ });
14
+ const stylesheetFilePaths = findFiles('app/components/**/*.css', {
15
+ projectRoot,
16
+ }).map((filePath) => {
17
+ return renamePathByDirectory(filePath, {
18
+ from: 'app/components',
19
+ to: '',
20
+ });
21
+ });
22
+ const templateFilePaths = findFiles('app/components/**/*.hbs', {
23
+ projectRoot,
24
+ }).map((filePath) => {
25
+ return renamePathByDirectory(filePath, {
26
+ from: 'app/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,15 @@
1
+ import { join, parse } from 'node:path';
2
+ export function analyzeFilePaths(filePaths) {
3
+ const entities = new Map();
4
+ filePaths.forEach((filePath) => {
5
+ const { dir, ext, name } = parse(filePath);
6
+ const entityName = join(dir, name);
7
+ if (entities.has(entityName)) {
8
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
9
+ entities.get(entityName).add(ext);
10
+ return;
11
+ }
12
+ entities.set(entityName, new Set([ext]));
13
+ });
14
+ return entities;
15
+ }
@@ -0,0 +1,38 @@
1
+ import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
2
+ import { analyzeFilePaths } from './analyze-file-paths.js';
3
+ export function analyzeRoutes(options) {
4
+ const { projectRoot } = options;
5
+ const classFilePaths = findFiles('app/controllers/**/*.{js,ts}', {
6
+ ignoreList: ['app/controllers/**/*.d.ts'],
7
+ projectRoot,
8
+ }).map((filePath) => {
9
+ return renamePathByDirectory(filePath, {
10
+ from: 'app/controllers',
11
+ to: '',
12
+ });
13
+ });
14
+ const stylesheetFilePaths = findFiles('app/styles/**/*.css', {
15
+ ignoreList: ['app/styles/app.css'],
16
+ projectRoot,
17
+ }).map((filePath) => {
18
+ return renamePathByDirectory(filePath, {
19
+ from: 'app/styles',
20
+ to: '',
21
+ });
22
+ });
23
+ const templateFilePaths = findFiles('app/templates/**/*.hbs', {
24
+ ignoreList: ['app/templates/components/**/*'],
25
+ projectRoot,
26
+ }).map((filePath) => {
27
+ return renamePathByDirectory(filePath, {
28
+ from: 'app/templates',
29
+ to: '',
30
+ });
31
+ });
32
+ const filePaths = [
33
+ ...classFilePaths,
34
+ ...stylesheetFilePaths,
35
+ ...templateFilePaths,
36
+ ].sort();
37
+ return analyzeFilePaths(filePaths);
38
+ }
@@ -0,0 +1,2 @@
1
+ export * from './analyze-components.js';
2
+ export * from './analyze-routes.js';
@@ -1,96 +1,4 @@
1
- import { join, parse } from 'node:path';
2
- import { findFiles, renamePathByDirectory } from '@codemod-utils/files';
3
- function analyzeFilePaths(filePaths) {
4
- const entities = new Map();
5
- filePaths.forEach((filePath) => {
6
- const { dir, ext, name } = parse(filePath);
7
- const entityName = join(dir, name);
8
- if (entities.has(entityName)) {
9
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
10
- entities.get(entityName).add(ext);
11
- return;
12
- }
13
- entities.set(entityName, new Set([ext]));
14
- });
15
- return entities;
16
- }
17
- function analyzeComponents(options) {
18
- const { componentStructure, projectRoot } = options;
19
- const classFilePaths = findFiles('app/components/**/*.{js,ts}', {
20
- ignoreList: ['app/components/**/*.d.ts'],
21
- projectRoot,
22
- }).map((filePath) => {
23
- return renamePathByDirectory(filePath, {
24
- from: 'app/components',
25
- to: '',
26
- });
27
- });
28
- const stylesheetFilePaths = findFiles('app/components/**/*.css', {
29
- projectRoot,
30
- }).map((filePath) => {
31
- return renamePathByDirectory(filePath, {
32
- from: 'app/components',
33
- to: '',
34
- });
35
- });
36
- const templateFilePaths = findFiles('app/components/**/*.hbs', {
37
- projectRoot,
38
- }).map((filePath) => {
39
- return renamePathByDirectory(filePath, {
40
- from: 'app/components',
41
- to: '',
42
- });
43
- });
44
- const filePaths = [
45
- ...classFilePaths,
46
- ...stylesheetFilePaths,
47
- ...templateFilePaths,
48
- ].sort();
49
- const entities = analyzeFilePaths(filePaths);
50
- if (componentStructure === 'nested') {
51
- return new Map(Array.from(entities.entries()).map(([entityName, extensions]) => {
52
- const newEntityName = entityName.replace(/\/index$/, '');
53
- return [newEntityName, extensions];
54
- }));
55
- }
56
- return entities;
57
- }
58
- function analyzeRoutes(options) {
59
- const { projectRoot } = options;
60
- const classFilePaths = findFiles('app/controllers/**/*.{js,ts}', {
61
- ignoreList: ['app/controllers/**/*.d.ts'],
62
- projectRoot,
63
- }).map((filePath) => {
64
- return renamePathByDirectory(filePath, {
65
- from: 'app/controllers',
66
- to: '',
67
- });
68
- });
69
- const stylesheetFilePaths = findFiles('app/styles/**/*.css', {
70
- ignoreList: ['app/styles/app.css'],
71
- projectRoot,
72
- }).map((filePath) => {
73
- return renamePathByDirectory(filePath, {
74
- from: 'app/styles',
75
- to: '',
76
- });
77
- });
78
- const templateFilePaths = findFiles('app/templates/**/*.hbs', {
79
- ignoreList: ['app/templates/components/**/*'],
80
- projectRoot,
81
- }).map((filePath) => {
82
- return renamePathByDirectory(filePath, {
83
- from: 'app/templates',
84
- to: '',
85
- });
86
- });
87
- const filePaths = [
88
- ...classFilePaths,
89
- ...stylesheetFilePaths,
90
- ...templateFilePaths,
91
- ].sort();
92
- return analyzeFilePaths(filePaths);
93
- }
1
+ import { analyzeComponents, analyzeRoutes } from './analyze-app/index.js';
94
2
  export function analyzeApp(options) {
95
3
  return {
96
4
  components: analyzeComponents(options),
@@ -0,0 +1,20 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { processTemplate } from '@codemod-utils/blueprints';
4
+ import { createFiles } from '@codemod-utils/files';
5
+ import { blueprintsRoot } from '../../../../utils/blueprints.js';
6
+ import { parseEntityName } from '../../../../utils/string.js';
7
+ export function createClass(entityName, { customizations, options }) {
8
+ const { blueprintFilePaths, getFilePath } = customizations;
9
+ const entity = parseEntityName(entityName);
10
+ const filePath = getFilePath(entityName);
11
+ const fileMap = new Map(blueprintFilePaths.map((blueprintFilePath) => {
12
+ const blueprintFile = readFileSync(join(blueprintsRoot, blueprintFilePath), 'utf8');
13
+ const file = processTemplate(blueprintFile, {
14
+ entity,
15
+ options,
16
+ });
17
+ return [filePath, file];
18
+ }));
19
+ createFiles(fileMap, options);
20
+ }
@@ -0,0 +1,16 @@
1
+ import { createClass } from './create-class.js';
2
+ import { updateClass } from './update-class.js';
3
+ export function importStyles(entities, options) {
4
+ for (const [entityName, extensions] of entities) {
5
+ const hasClass = extensions.has('.js') || extensions.has('.ts');
6
+ const hasStylesheet = extensions.has('.css');
7
+ if (!hasStylesheet) {
8
+ continue;
9
+ }
10
+ if (!hasClass) {
11
+ createClass(entityName, options);
12
+ continue;
13
+ }
14
+ updateClass(entityName, options);
15
+ }
16
+ }
@@ -2,10 +2,7 @@
2
2
  import { readFileSync } from 'node:fs';
3
3
  import { join, parse } from 'node:path';
4
4
  import { ASTJavaScript as AST } from '@codemod-utils/ast';
5
- import { processTemplate } from '@codemod-utils/blueprints';
6
5
  import { createFiles } from '@codemod-utils/files';
7
- import { blueprintsRoot } from '../../../../utils/blueprints.js';
8
- import { parseEntityName } from '../../../../utils/string.js';
9
6
  function removeTemplateOnlyComponentMethod(file, data) {
10
7
  const traverse = AST.traverse(data.isTypeScript);
11
8
  const ast = traverse(file, {
@@ -80,21 +77,7 @@ function addStylesAsClassProperty(file, data) {
80
77
  });
81
78
  return AST.print(ast);
82
79
  }
83
- function createClass(entityName, { customizations, options }) {
84
- const { blueprintFilePaths, getFilePath } = customizations;
85
- const entity = parseEntityName(entityName);
86
- const filePath = getFilePath(entityName);
87
- const fileMap = new Map(blueprintFilePaths.map((blueprintFilePath) => {
88
- const blueprintFile = readFileSync(join(blueprintsRoot, blueprintFilePath), 'utf8');
89
- const file = processTemplate(blueprintFile, {
90
- entity,
91
- options,
92
- });
93
- return [filePath, file];
94
- }));
95
- createFiles(fileMap, options);
96
- }
97
- function updateClass(entityName, { customizations, options }) {
80
+ export function updateClass(entityName, { customizations, options }) {
98
81
  const { getFilePath } = customizations;
99
82
  const { __styles__, projectRoot } = options;
100
83
  const filePath = getFilePath(entityName);
@@ -120,17 +103,3 @@ function updateClass(entityName, { customizations, options }) {
120
103
  console.warn(`${message}\n`);
121
104
  }
122
105
  }
123
- export function importStyles(entities, options) {
124
- for (const [entityName, extensions] of entities) {
125
- const hasClass = extensions.has('.js') || extensions.has('.ts');
126
- const hasStylesheet = extensions.has('.css');
127
- if (!hasStylesheet) {
128
- continue;
129
- }
130
- if (!hasClass) {
131
- createClass(entityName, options);
132
- continue;
133
- }
134
- updateClass(entityName, options);
135
- }
136
- }
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { importStyles } from './shared/import-styles.js';
2
+ import { importStyles } from './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 './shared/import-styles.js';
2
+ import { importStyles } from './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 { updateTemplates } from './shared/update-templates.js';
2
+ import { updateTemplates } from './update-templates/index.js';
3
3
  function getFilePath(options) {
4
4
  const { componentStructure } = options;
5
5
  return function (entityName) {
@@ -9,7 +9,16 @@ function updateDevDependencies(packageJson, options) {
9
9
  packagesToDelete.forEach((packageName) => {
10
10
  devDependencies.delete(packageName);
11
11
  });
12
- const packagesToInstall = new Set(['embroider-css-modules']);
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
+ ]);
13
22
  if (project.hasTypeScript) {
14
23
  packagesToInstall.add('type-css-modules');
15
24
  }
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { updateTemplates } from './shared/update-templates.js';
2
+ import { updateTemplates } from './update-templates/index.js';
3
3
  function getFilePath() {
4
4
  return function (entityName) {
5
5
  let filePath = join('app/templates', entityName);
@@ -0,0 +1,10 @@
1
+ import { updateTemplate } from './update-template.js';
2
+ export function updateTemplates(entities, options) {
3
+ for (const [entityName, extensions] of entities) {
4
+ const hasTemplate = extensions.has('.hbs');
5
+ if (!hasTemplate) {
6
+ continue;
7
+ }
8
+ updateTemplate(entityName, options);
9
+ }
10
+ }
@@ -327,7 +327,7 @@ function removeLocalClassAttributes(file, data) {
327
327
  });
328
328
  return AST.print(ast);
329
329
  }
330
- function updateTemplate(entityName, { customizations, options }) {
330
+ export function updateTemplate(entityName, { customizations, options }) {
331
331
  const { getFilePath } = customizations;
332
332
  const { __styles__, projectRoot } = options;
333
333
  const filePath = getFilePath(entityName);
@@ -351,12 +351,3 @@ function updateTemplate(entityName, { customizations, options }) {
351
351
  console.warn(`${message}\n`);
352
352
  }
353
353
  }
354
- export function updateTemplates(entities, options) {
355
- for (const [entityName, extensions] of entities) {
356
- const hasTemplate = extensions.has('.hbs');
357
- if (!hasTemplate) {
358
- continue;
359
- }
360
- updateTemplate(entityName, options);
361
- }
362
- }
@@ -1,8 +1,14 @@
1
1
  import { decideVersion } from '@codemod-utils/blueprints';
2
2
  const latestVersions = new Map([
3
- ['embroider-css-modules', '0.1.7'],
4
- ['type-css-modules', '0.1.5'],
5
- ['webpack', '5.86.0'],
3
+ ['@embroider/compat', '3.0.2'],
4
+ ['@embroider/core', '3.0.2'],
5
+ ['@embroider/webpack', '3.0.0'],
6
+ ['autoprefixer', '10.4.14'],
7
+ ['embroider-css-modules', '0.1.9'],
8
+ ['postcss', '8.4.24'],
9
+ ['postcss-loader', '7.3.3'],
10
+ ['type-css-modules', '0.2.2'],
11
+ ['webpack', '5.87.0'],
6
12
  ]);
7
13
  export function getVersion(packageName, options) {
8
14
  const { project } = options;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-codemod-remove-ember-css-modules",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Codemod to replace ember-css-modules with embroider-css-modules",
5
5
  "keywords": [
6
6
  "codemod",
@@ -38,12 +38,12 @@
38
38
  "@types/node": "^16.11.7",
39
39
  "@types/yargs": "^17.0.24",
40
40
  "concurrently": "^8.2.0",
41
- "eslint": "^8.42.0",
41
+ "eslint": "^8.43.0",
42
42
  "prettier": "^2.8.8",
43
43
  "typescript": "^5.1.3",
44
44
  "@shared-configs/eslint-config-node": "0.0.0",
45
- "@shared-configs/prettier": "0.0.0",
46
- "@shared-configs/typescript": "0.0.0"
45
+ "@shared-configs/typescript": "0.0.0",
46
+ "@shared-configs/prettier": "0.0.0"
47
47
  },
48
48
  "engines": {
49
49
  "node": "16.* || >= 18"