@workday/canvas-kit-codemod 16.0.0-alpha.0494-next.0 → 16.0.0-alpha.0499-next.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.
@@ -0,0 +1,4 @@
1
+ import { Transform } from 'jscodeshift';
2
+ declare const transform: Transform;
3
+ export default transform;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/icon-migration/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAItC,QAAA,MAAM,SAAS,EAAE,SAIhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ import migrateIcons from './migrateIcons';
2
+ const transform = (file, api, options) => {
3
+ // These will run in order. If your transform depends on others, place yours after dependent transforms
4
+ const fixes = [migrateIcons];
5
+ return fixes.reduce((source, fix) => fix({ ...file, source }, api, options), file.source);
6
+ };
7
+ export default transform;
@@ -0,0 +1,3 @@
1
+ import { API, FileInfo, Options } from 'jscodeshift';
2
+ export default function transformer(file: FileInfo, api: API, _options: Options): string;
3
+ //# sourceMappingURL=migrateIcons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateIcons.d.ts","sourceRoot":"","sources":["../../../lib/icon-migration/migrateIcons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,aAAa,CAAC;AA2CnD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,UA0I9E"}
@@ -0,0 +1,135 @@
1
+ import deprecatedIcons from '@workday/canvas-system-icons-web/dist/metadata/system.deprecated.metadata.json';
2
+ import { getImportRenameMap } from './utils/getImportRenameMap';
3
+ const iconPackage = '@workday/canvas-system-icons-web';
4
+ const toCamelCase = (str) => str
5
+ .split('-')
6
+ .map((word, index) => (index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)))
7
+ .join('');
8
+ // `wd-icon-clipboard-user.svg` -> `clipboard-user`
9
+ // `academicAppointmentTitleIcon` -> `clipboardUserIcon`
10
+ const migrations = deprecatedIcons.reduce((acc, icon) => {
11
+ const oldIcon = toCamelCase(icon.name) + 'Icon';
12
+ // `wd-icon-clipboard-user.svg` -> `clipboardUserIcon`
13
+ const newIcon = icon.fallback
14
+ ? toCamelCase(icon.fallback.replace(/^wd-icon-|\.svg$/g, '')) + 'Icon'
15
+ : oldIcon;
16
+ if (oldIcon !== newIcon) {
17
+ acc[oldIcon] = newIcon;
18
+ }
19
+ return acc;
20
+ }, {});
21
+ // a fallback can itself be deprecated, so follow the chain until we land on a supported icon
22
+ Object.keys(migrations).forEach(oldIcon => {
23
+ const seen = new Set([oldIcon]);
24
+ while (migrations[migrations[oldIcon]] && !seen.has(migrations[oldIcon])) {
25
+ seen.add(migrations[oldIcon]);
26
+ migrations[oldIcon] = migrations[migrations[oldIcon]];
27
+ }
28
+ });
29
+ export default function transformer(file, api, _options) {
30
+ const j = api.jscodeshift;
31
+ const root = j(file.source);
32
+ const { containsCanvasImports } = getImportRenameMap(j, root, iconPackage);
33
+ // exit if the icon package isn't imported
34
+ if (!containsCanvasImports) {
35
+ return file.source;
36
+ }
37
+ const namespaceImportNames = new Set();
38
+ // usages reference the local name, so renames are keyed off of it, i.e. `academicIcon` ->
39
+ // `clipboardIcon` when the deprecated icon's fallback is already imported as `clipboardIcon`
40
+ const usageRenameMap = {};
41
+ root
42
+ .find(j.ImportDeclaration, {
43
+ source: {
44
+ value: (value) => value === iconPackage,
45
+ },
46
+ })
47
+ .forEach(nodePath => {
48
+ if (nodePath.value.specifiers && nodePath.value.specifiers.length) {
49
+ // collect namespace imports, i.e. `import * as systemIcons from ...`, so we can rename the
50
+ // icons accessed off of them later
51
+ nodePath.value.specifiers.forEach(currentSpecifier => {
52
+ if (currentSpecifier.type === 'ImportNamespaceSpecifier' && currentSpecifier.local) {
53
+ namespaceImportNames.add(currentSpecifier.local.name);
54
+ }
55
+ });
56
+ // the local name each imported icon is available under, so we can point usages of a
57
+ // deprecated icon at an existing import of its fallback instead of importing it twice
58
+ const localNamesByImport = {};
59
+ nodePath.value.specifiers.forEach(currentSpecifier => {
60
+ var _a;
61
+ if (currentSpecifier.type === 'ImportSpecifier' &&
62
+ !migrations[currentSpecifier.imported.name]) {
63
+ localNamesByImport[currentSpecifier.imported.name] =
64
+ ((_a = currentSpecifier.local) === null || _a === void 0 ? void 0 : _a.name) || currentSpecifier.imported.name;
65
+ }
66
+ });
67
+ nodePath.value.specifiers = nodePath.value.specifiers.filter(currentSpecifier => {
68
+ var _a;
69
+ if (currentSpecifier.type !== 'ImportSpecifier') {
70
+ return true;
71
+ }
72
+ const renamed = migrations[currentSpecifier.imported.name];
73
+ if (!renamed) {
74
+ return true;
75
+ }
76
+ const localName = ((_a = currentSpecifier.local) === null || _a === void 0 ? void 0 : _a.name) || currentSpecifier.imported.name;
77
+ const existingLocalName = localNamesByImport[renamed];
78
+ // the fallback is already imported, so drop this specifier and send its usages to the
79
+ // existing local name
80
+ if (existingLocalName) {
81
+ if (existingLocalName !== localName) {
82
+ usageRenameMap[localName] = existingLocalName;
83
+ }
84
+ return false;
85
+ }
86
+ // if imported with an alias, retain the alias as the local so usages don't have to change
87
+ const alias = localName !== currentSpecifier.imported.name ? currentSpecifier.local : null;
88
+ if (!alias) {
89
+ usageRenameMap[localName] = renamed;
90
+ }
91
+ localNamesByImport[renamed] = alias ? localName : renamed;
92
+ currentSpecifier.imported = j.identifier(renamed);
93
+ currentSpecifier.local = alias || j.identifier(renamed);
94
+ return true;
95
+ });
96
+ }
97
+ });
98
+ // rename usages of icons imported by name
99
+ root
100
+ .find(j.Identifier, { name: (name) => name in usageRenameMap })
101
+ .filter(nodePath => {
102
+ const parent = nodePath.parent.value;
103
+ // an identifier in a name position, i.e. `config.undoIcon` or `{undoIcon: true}`, only
104
+ // happens to match the icon's name and isn't a reference to the import
105
+ if ((parent.type === 'MemberExpression' || parent.type === 'OptionalMemberExpression') &&
106
+ !parent.computed) {
107
+ return parent.property !== nodePath.value;
108
+ }
109
+ if ((parent.type === 'Property' || parent.type === 'ObjectProperty') &&
110
+ !parent.computed &&
111
+ !parent.shorthand) {
112
+ return parent.key !== nodePath.value;
113
+ }
114
+ return true;
115
+ })
116
+ .replaceWith(nodePath => j.identifier(usageRenameMap[nodePath.value.name]));
117
+ // rename usages of icons accessed off a namespace import, i.e. `systemIcons.academicAppointmentTitleIcon`
118
+ root
119
+ .find(j.MemberExpression, {
120
+ computed: false,
121
+ object: { type: 'Identifier' },
122
+ property: { type: 'Identifier' },
123
+ })
124
+ .replaceWith(nodePath => {
125
+ const { object, property } = nodePath.value;
126
+ if (object.type === 'Identifier' &&
127
+ property.type === 'Identifier' &&
128
+ namespaceImportNames.has(object.name) &&
129
+ migrations[property.name]) {
130
+ return j.memberExpression(object, j.identifier(migrations[property.name]), false);
131
+ }
132
+ return nodePath.value;
133
+ });
134
+ return root.toSource({ objectCurlySpacing: false });
135
+ }
@@ -0,0 +1,7 @@
1
+ import { Collection, JSCodeshift } from 'jscodeshift';
2
+ export declare function getImportRenameMap(j: JSCodeshift, root: Collection<any>, mainPackage?: string, packageName?: string): {
3
+ containsCanvasImports: boolean;
4
+ importMap: Record<string, string>;
5
+ styledMap: Record<string, string>;
6
+ };
7
+ //# sourceMappingURL=getImportRenameMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getImportRenameMap.d.ts","sourceRoot":"","sources":["../../../../lib/icon-migration/utils/getImportRenameMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,UAAU,EAAE,WAAW,EAAC,MAAM,aAAa,CAAC;AAEpE,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,WAAW,EACd,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EACrB,WAAW,SAAqC,EAChD,WAAW,SAAK;;;;EA2DjB"}
@@ -0,0 +1,46 @@
1
+ export function getImportRenameMap(j, root, mainPackage = '@workday/canvas-system-icons-web', packageName = '') {
2
+ let containsCanvasImports = false;
3
+ // build import name remapping - in case someone renamed imports...
4
+ // i.e. `import { IconButton as StyledIconButton } ...`
5
+ const importMap = {};
6
+ const styledMap = {};
7
+ root.find(j.ImportDeclaration, node => {
8
+ // imports our module
9
+ const value = node.source.value;
10
+ if (typeof value === 'string' &&
11
+ (value === mainPackage || value.startsWith(mainPackage) || value === packageName)) {
12
+ containsCanvasImports = true;
13
+ (node.specifiers || []).forEach(specifier => {
14
+ if (specifier.type === 'ImportSpecifier') {
15
+ if (!specifier.local || specifier.local.name === specifier.imported.name) {
16
+ importMap[specifier.imported.name] = specifier.imported.name;
17
+ }
18
+ else {
19
+ importMap[specifier.imported.name] = specifier.local.name;
20
+ }
21
+ }
22
+ });
23
+ }
24
+ return false;
25
+ });
26
+ root
27
+ .find(j.CallExpression, (node) => node.callee.type === 'Identifier' &&
28
+ node.callee.name === 'styled' &&
29
+ node.arguments[0].type === 'Identifier')
30
+ .forEach(nodePath => {
31
+ // const StyledName = styled(OriginalName)({})
32
+ // const StyledName = styled(OriginalName)`` // Tagged template
33
+ if ((nodePath.parent.value.type === 'CallExpression' ||
34
+ nodePath.parent.value.type === 'TaggedTemplateExpression') &&
35
+ nodePath.parent.parent.value.type === 'VariableDeclarator' &&
36
+ nodePath.parent.parent.value.id.type === 'Identifier') {
37
+ const styledName = nodePath.parent.parent.value.id.name;
38
+ if (nodePath.value.arguments &&
39
+ nodePath.value.arguments.length &&
40
+ nodePath.value.arguments[0].type === 'Identifier') {
41
+ styledMap[nodePath.value.arguments[0].name] = styledName;
42
+ }
43
+ }
44
+ });
45
+ return { containsCanvasImports, importMap, styledMap };
46
+ }
package/index.js CHANGED
@@ -145,6 +145,17 @@ const {
145
145
  describe: chalk.gray('The path to execute the transform in (recursively).'),
146
146
  });
147
147
  })
148
+ .command(
149
+ 'icon-migration [path]',
150
+ chalk.gray('Deprecated system icons migration transform'),
151
+ yargs => {
152
+ yargs.positional('path', {
153
+ type: 'string',
154
+ default: '.',
155
+ describe: chalk.gray('The path to execute the transform in (recursively).'),
156
+ });
157
+ }
158
+ )
148
159
  .demandCommand(1, chalk.red.bold('You must provide a transform to apply.'))
149
160
  .strictCommands()
150
161
  .fail((msg, err, yargs) => {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@workday/canvas-kit-codemod",
3
3
  "author": "Workday, Inc. (https://www.workday.com)",
4
4
  "license": "Apache-2.0",
5
- "version": "16.0.0-alpha.0494-next.0",
5
+ "version": "16.0.0-alpha.0499-next.0",
6
6
  "description": "A collection of codemods for use on Workday Canvas Kit packages.",
7
7
  "main": "dist/es6/index.js",
8
8
  "sideEffects": false,
@@ -29,13 +29,17 @@
29
29
  "url": "https://github.com/Workday/canvas-kit/issues"
30
30
  },
31
31
  "homepage": "https://github.com/Workday/canvas-kit#readme",
32
+ "peerDependencies": {
33
+ "@workday/canvas-system-icons-web": "^5.0.3"
34
+ },
32
35
  "dependencies": {
33
36
  "chalk": "4.1.2",
34
37
  "jscodeshift": "^17.1.0",
35
38
  "yargs": "^16.2.0"
36
39
  },
37
40
  "devDependencies": {
38
- "@types/jscodeshift": "^0.11.3"
41
+ "@types/jscodeshift": "^0.11.3",
42
+ "@workday/canvas-system-icons-web": "^5.0.3"
39
43
  },
40
44
  "scripts": {
41
45
  "clean": "rimraf dist && rimraf .build-info && mkdirp dist",
@@ -46,5 +50,5 @@
46
50
  "resolutions": {
47
51
  "recast": "0.20.4"
48
52
  },
49
- "gitHead": "7bde57a5a6d4e41fd4a2e08f9f035c609ff4a8f0"
53
+ "gitHead": "cd5cbb846495120a4bffea4ee17b3b0a482e68c0"
50
54
  }