@navikt/aksel 7.34.0 → 7.35.1

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 +96 -2
  2. package/dist/codemod/codeshift.utils.js +9 -1
  3. package/dist/codemod/migrations.js +75 -22
  4. package/dist/codemod/run-codeshift.js +14 -3
  5. package/dist/codemod/transforms/v8.0.0/accordion-variant/accordion-variant.js +16 -0
  6. package/dist/codemod/transforms/{darkside/box-to-boxnew/box-to-boxnew.js → v8.0.0/box/box.js} +80 -100
  7. package/dist/codemod/transforms/v8.0.0/box-new/box-new.js +91 -0
  8. package/dist/codemod/transforms/v8.0.0/chips-variant/chips-variant.js +31 -0
  9. package/dist/codemod/transforms/v8.0.0/list/list.js +218 -0
  10. package/dist/codemod/transforms/{darkside → v8.0.0}/prop-deprecate/prop-deprecate.js +1 -1
  11. package/dist/codemod/transforms/v8.0.0/tag-variant/tag-variant.js +38 -0
  12. package/dist/codemod/transforms/v8.0.0/toggle-group-variant/toggle-group-variant.js +16 -0
  13. package/dist/codemod/utils/ast.js +1 -1
  14. package/dist/codemod/utils/check.js +35 -0
  15. package/dist/codemod/utils/move-variant-to-data-color.js +120 -0
  16. package/dist/darkside/index.js +3 -9
  17. package/dist/darkside/run-tooling.js +138 -42
  18. package/dist/darkside/tasks/print-remaining.js +143 -38
  19. package/dist/darkside/tasks/status.js +147 -30
  20. package/dist/darkside/transforms/darkside-tokens-css.js +23 -8
  21. package/dist/darkside/transforms/darkside-tokens-tailwind.js +9 -10
  22. package/dist/help.js +0 -10
  23. package/dist/index.js +14 -17
  24. package/package.json +7 -7
  25. package/dist/css-imports/config.js +0 -5
  26. package/dist/css-imports/generate-output.js +0 -147
  27. package/dist/css-imports/get-directories.js +0 -34
  28. package/dist/css-imports/get-version.js +0 -28
  29. package/dist/css-imports/index.js +0 -187
  30. package/dist/css-imports/inquiry.js +0 -35
  31. package/dist/css-imports/scan-code.js +0 -45
  32. /package/dist/codemod/transforms/{spacing → v8.0.0}/primitives-spacing/spacing.js +0 -0
  33. /package/dist/codemod/transforms/{spacing → v8.0.0}/spacing.utils.js +0 -0
  34. /package/dist/codemod/transforms/{spacing → v8.0.0}/token-spacing/spacing.js +0 -0
  35. /package/dist/codemod/transforms/{spacing → v8.0.0}/token-spacing-js/spacing.js +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Aksel command line interface
2
2
 
3
- CLI tool for managing CSS-imports and Codemods when consuming Aksel-packages.
3
+ CLI tool for running codemods when consuming Aksel-packages.
4
4
 
5
5
  [Documentation](https://aksel.nav.no/preview/grunnleggende/kode/kommandolinje)
6
6
 
@@ -9,7 +9,6 @@ run:
9
9
  npx @navikt/aksel
10
10
 
11
11
  commands:
12
- css-imports: Generate css-imports for all components from Aksel
13
12
  codemod: Codemods for version-migrations related to Aksel
14
13
  ```
15
14
 
@@ -22,6 +21,101 @@ To get started:
22
21
  npx @navikt/aksel codemod --help
23
22
  ```
24
23
 
24
+ ### v8
25
+
26
+ #### Box
27
+
28
+ `npx @navikt/aksel codemod v8-box ...`
29
+
30
+ Updates Box with legacy-tokens to Box using the new token system.
31
+
32
+ ```diff
33
+ -<Box background="bg-subtle" borderColor="border-alt-1">
34
+ +<Box background="bg-neutral-soft" borderColor="border-meta-purple">
35
+ ```
36
+
37
+ #### BoxNew
38
+
39
+ `npx @navikt/aksel codemod v8-box-new ...`
40
+
41
+ Renames already migrated BoxNew/Box.New instances to Box.
42
+
43
+ ```diff
44
+ -<BoxNew>
45
+ +<Box>
46
+ ```
47
+
48
+ #### Prop deprecate
49
+
50
+ `npx @navikt/aksel codemod v8-prop-deprecate ...`
51
+
52
+ Removes deprecated props from components.
53
+
54
+ ```diff
55
+ -<Accordion headingSize="large">
56
+ +<Accordion>
57
+
58
+ -<Popover arrow>
59
+ +<Popover>
60
+
61
+ -<Page background="bg-subtle">
62
+ +<Page>
63
+ ```
64
+
65
+ #### List
66
+
67
+ `npx @navikt/aksel codemod v8-list ...`
68
+
69
+ Tries to migrate List component moving 'title' and 'description' props to 'Heading' and 'BodyShort'.
70
+
71
+ #### Variants
72
+
73
+ `npx @navikt/aksel codemod v8-tag-variant ...`
74
+ `npx @navikt/aksel codemod v8-toggle-group-variant ...`
75
+ `npx @navikt/aksel codemod v8-accordion-variant ...`
76
+ `npx @navikt/aksel codemod v8-chips-variant ...`
77
+
78
+ Updates variant + data-color props based on current variant prop.
79
+
80
+ ```diff
81
+ -<Tag variant="info">
82
+ +<Tag variant="outline" data-color="info">
83
+ ```
84
+
85
+ #### Spacing
86
+
87
+ `npx @navikt/aksel codemod v8-primitive-spacing ...`
88
+ `npx @navikt/aksel codemod v8-token-spacing ...`
89
+ `npx @navikt/aksel codemod v8-token-spacing-js ...`
90
+
91
+ Updates use of legacy `spacing` token to new `space`-token
92
+
93
+ ```diff
94
+ -<HStack gap="spacing-4" />
95
+ +<HStack gap="space-16" />
96
+ ```
97
+
98
+ ```diff
99
+ -margin: var(--a-spacing-1);
100
+ +margin: var(--ax-space-4);
101
+ ```
102
+
103
+ ### v6
104
+
105
+ #### Chat
106
+
107
+ `npx @navikt/aksel codemod v6-chat ...`
108
+
109
+ Removes `backgroundColor` and `avatarBgColor` properties from `Chat` and `Chat.Bubble`.
110
+
111
+ ```diff
112
+ -<Chat backgroundColor="red" avatarBgColor="blue">
113
+ +<Chat>
114
+ - <Chat.Bubble backgroundColor="red" />
115
+ + <Chat.Bubble />
116
+ </Chat>
117
+ ```
118
+
25
119
  ### v4
26
120
 
27
121
  In v4, we moved all the components from `@navikt/ds-react-internal` to `@navikt/ds-react`. This means that you will need to update all your imports to the new package. As a part of this, Header was renamed to `InternalHeader` and all the CSS-classes was renamed to use `navds` as a prefix instead of `navdsi`.
@@ -17,7 +17,15 @@ exports.GLOB_IGNORE_PATTERNS = GLOB_IGNORE_PATTERNS;
17
17
  */
18
18
  function getDefaultGlob(ext) {
19
19
  const defaultExt = "js,ts,jsx,tsx,css,scss,less";
20
- return `**/*.{${cleanExtensions(ext !== null && ext !== void 0 ? ext : defaultExt).join(",")}}`;
20
+ const extensions = cleanExtensions(ext !== null && ext !== void 0 ? ext : defaultExt);
21
+ /**
22
+ * Single-item braces are treated as a literal string by some globbing libraries,
23
+ * so we only use them when there are multiple extensions
24
+ */
25
+ if (extensions.length > 1) {
26
+ return `**/*.{${extensions.join(",")}}`;
27
+ }
28
+ return `**/*.${extensions[0]}`;
21
29
  }
22
30
  /**
23
31
  * Utility function to clean file extensions
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.migrations = void 0;
6
+ exports.migrationStringOverride = exports.migrations = void 0;
7
7
  exports.getMigrationPath = getMigrationPath;
8
8
  exports.getWarning = getWarning;
9
9
  exports.getIgnoredFileExtensions = getIgnoredFileExtensions;
@@ -79,7 +79,7 @@ exports.migrations = {
79
79
  description: "Replaces deprecated <CopyToClipboard /> with <CopyButton />",
80
80
  value: "v3-copybutton",
81
81
  path: "v3.0.0/copybutton/copybutton",
82
- warning: "Remember to clean css-import from '@navikt/ds-css-internal' if no longer needed\nIf non-text was used as children, or different locales were handled, you need to manually fix this",
82
+ warning: "Remember to remove css-import from '@navikt/ds-css-internal' if no longer needed\nIf non-text was used as children, or different locales were handled, you need to manually fix this",
83
83
  ignoredExtensions: CSS_EXTENSIONS,
84
84
  },
85
85
  ],
@@ -114,38 +114,72 @@ exports.migrations = {
114
114
  ignoredExtensions: CSS_EXTENSIONS,
115
115
  },
116
116
  ],
117
- spacing: [
117
+ "v8.0.0": [
118
118
  {
119
- description: "Updates all Primitives to use new `space`-tokens. (Works with old and new system)",
120
- value: "primitive-spacing",
121
- path: "spacing/primitives-spacing/spacing",
119
+ description: "Updates Box with legacy-tokens to Box using the new token system, and renames already migrated BoxNew/Box.New instances to Box.",
120
+ value: "v8-box",
121
+ path: "v8.0.0/box/box",
122
+ warning: "Remember to check if 'TODO: Aksel Box migration'-comment was added to any files after migration. This comment will help you find and update Box-instances we couldn't update for you.",
122
123
  ignoredExtensions: CSS_EXTENSIONS,
123
124
  },
124
125
  {
125
- description: "Updates css, scss and less-variables to use new `space`-tokens. (Works with old and new system)",
126
- value: "token-spacing",
127
- path: "spacing/token-spacing/spacing",
128
- ignoredExtensions: [],
126
+ description: "Renames already migrated BoxNew/Box.New instances to Box.",
127
+ value: "v8-box-new",
128
+ path: "v8.0.0/box-new/box-new",
129
+ ignoredExtensions: CSS_EXTENSIONS,
129
130
  },
130
131
  {
131
- description: "Updates js-tokens to use new `space`-tokens. (Works with old and new system)",
132
- value: "token-spacing-js",
133
- path: "spacing/token-spacing-js/spacing",
132
+ description: "Removes deprecated props from components.",
133
+ value: "v8-prop-deprecate",
134
+ path: "v8.0.0/prop-deprecate/prop-deprecate",
135
+ ignoredExtensions: CSS_EXTENSIONS,
136
+ },
137
+ {
138
+ description: "Updates variant + data-color props on Tag based on current variant prop.",
139
+ value: "v8-tag-variant",
140
+ path: "v8.0.0/tag-variant/tag-variant",
134
141
  ignoredExtensions: CSS_EXTENSIONS,
135
142
  },
136
- ],
137
- darkside: [
138
143
  {
139
- description: "marks deprecated prop usage with comments.",
140
- value: "prop-deprecate",
141
- path: "darkside/prop-deprecate/prop-deprecate",
144
+ description: "Updates variant + data-color props on ToggleGroup based on current variant prop.",
145
+ value: "v8-toggle-group-variant",
146
+ path: "v8.0.0/toggle-group-variant/toggle-group-variant",
142
147
  ignoredExtensions: CSS_EXTENSIONS,
143
148
  },
144
149
  {
145
- description: "Update Box to to BoxNew (future Box) using the new token system",
146
- value: "box-to-boxnew",
147
- path: "darkside/box-to-boxnew/box-to-boxnew",
148
- warning: "Remember to check if 'aksel box migration'-comment were added to any files after migration. This comment will help you find and update Box-instances where we could not resolve the update for you.",
150
+ description: "Updates variant + data-color props on Accordion based on current variant prop.",
151
+ value: "v8-accordion-variant",
152
+ path: "v8.0.0/accordion-variant/accordion-variant",
153
+ ignoredExtensions: CSS_EXTENSIONS,
154
+ },
155
+ {
156
+ description: "Updates variant + data-color props on Chips based on current variant prop.",
157
+ value: "v8-chips-variant",
158
+ path: "v8.0.0/chips-variant/chips-variant",
159
+ ignoredExtensions: CSS_EXTENSIONS,
160
+ },
161
+ {
162
+ description: "Tries to migrate List component moving 'title' and 'description' props to 'Heading' and 'BodyShort'.",
163
+ value: "v8-list",
164
+ path: "v8.0.0/list/list",
165
+ ignoredExtensions: CSS_EXTENSIONS,
166
+ },
167
+ {
168
+ description: "Updates all Primitives to use new `space`-tokens. (Works with old and new system)",
169
+ value: "v8-primitive-spacing",
170
+ path: "v8.0.0/primitives-spacing/spacing",
171
+ ignoredExtensions: CSS_EXTENSIONS,
172
+ },
173
+ {
174
+ description: "Updates css, scss and less-variables to use new `space`-tokens. (Works with old and new system)",
175
+ value: "v8-token-spacing",
176
+ path: "v8.0.0/token-spacing/spacing",
177
+ ignoredExtensions: [],
178
+ },
179
+ {
180
+ description: "Updates js-tokens to use new `space`-tokens. (Works with old and new system)",
181
+ value: "v8-token-spacing-js",
182
+ path: "v8.0.0/token-spacing-js/spacing",
149
183
  ignoredExtensions: CSS_EXTENSIONS,
150
184
  },
151
185
  ],
@@ -182,6 +216,21 @@ function getMigrationNames() {
182
216
  .flat()
183
217
  .map((x) => x.value);
184
218
  }
219
+ /**
220
+ * Allows injecting additional migration names that are not part of the main migrations-list.
221
+ * This is used for interactive migrations that should not be part of the main list.
222
+ *
223
+ * We need to separate this since main migration list expect all migration names to have a unique path,
224
+ * which is not the case for interactive migrations that are handled differently.
225
+ */
226
+ exports.migrationStringOverride = {
227
+ "v8.0.0": [
228
+ {
229
+ value: "v8-tokens",
230
+ description: "Starts interactive token migration for v8",
231
+ },
232
+ ],
233
+ };
185
234
  function getMigrationString() {
186
235
  let str = "";
187
236
  Object.entries(exports.migrations).forEach(([version, vMigrations]) => {
@@ -189,6 +238,10 @@ function getMigrationString() {
189
238
  vMigrations.forEach((migration) => {
190
239
  str += `${chalk_1.default.blue(migration.value)}: ${migration.description}\n`;
191
240
  });
241
+ const overrideMigrations = exports.migrationStringOverride[version] || [];
242
+ overrideMigrations.forEach((migration) => {
243
+ str += `${chalk_1.default.blue(migration.value)}: ${migration.description}\n`;
244
+ });
192
245
  });
193
246
  return str;
194
247
  }
@@ -63,12 +63,23 @@ function runCodeshift(input, options, program) {
63
63
  return __awaiter(this, void 0, void 0, function* () {
64
64
  var _a;
65
65
  const codemodPath = node_path_1.default.join(__dirname, `./transforms/${(0, migrations_1.getMigrationPath)(input)}.js`);
66
- const filepaths = fast_glob_1.default.sync([(_a = options.glob) !== null && _a !== void 0 ? _a : (0, codeshift_utils_1.getDefaultGlob)(options === null || options === void 0 ? void 0 : options.ext)], {
66
+ console.info(chalk_1.default.greenBright.bold("\nWelcome to Aksel codemods!"));
67
+ console.info("\nRunning migration:", chalk_1.default.green(input));
68
+ const globList = (_a = options.glob) !== null && _a !== void 0 ? _a : (0, codeshift_utils_1.getDefaultGlob)(options === null || options === void 0 ? void 0 : options.ext);
69
+ console.info(chalk_1.default.gray(`Using glob pattern(s): ${globList}\nWorking directory: ${process.cwd()}\n`));
70
+ const filepaths = fast_glob_1.default.sync(globList, {
67
71
  cwd: process.cwd(),
68
72
  ignore: codeshift_utils_1.GLOB_IGNORE_PATTERNS,
73
+ /**
74
+ * When globbing, do not follow symlinks to avoid processing files outside the directory.
75
+ * This is most likely to happen in monorepos where node_modules may contain symlinks to packages
76
+ * in other parts of the repo.
77
+ *
78
+ * While node_modules is already ignored via GLOB_IGNORE_PATTERNS, if user globs upwards (e.g., using '../src/**'),
79
+ * that ignore-pattern may be ignored, leading to unintended file processing.
80
+ */
81
+ followSymbolicLinks: false,
69
82
  });
70
- console.info("\nRunning migration:", chalk_1.default.green("input"));
71
- (options === null || options === void 0 ? void 0 : options.glob) && console.info(`Using glob: ${chalk_1.default.green(options.glob)}\n`);
72
83
  const warning = (0, migrations_1.getWarning)(input);
73
84
  const unsafeExtensions = (0, migrations_1.getIgnoredFileExtensions)(input);
74
85
  let safeFilepaths = filepaths;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrationConfig = void 0;
4
+ exports.default = transformer;
5
+ const move_variant_to_data_color_1 = require("../../../utils/move-variant-to-data-color");
6
+ exports.migrationConfig = {
7
+ component: "Accordion",
8
+ prop: "variant",
9
+ changes: {
10
+ default: { color: "accent" },
11
+ neutral: { color: "neutral" },
12
+ },
13
+ };
14
+ function transformer(file, api) {
15
+ return (0, move_variant_to_data_color_1.moveVariantToDataColor)(file, api, exports.migrationConfig);
16
+ }
@@ -1,49 +1,19 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
35
5
  Object.defineProperty(exports, "__esModule", { value: true });
36
6
  exports.default = transformer;
37
7
  const legacy_tokens_1 = require("../../../../darkside/config/legacy.tokens");
38
8
  const ast_1 = require("../../../utils/ast");
39
9
  const lineterminator_1 = require("../../../utils/lineterminator");
40
- const packageImports_1 = __importStar(require("../../../utils/packageImports"));
10
+ const box_new_1 = __importDefault(require("../box-new/box-new"));
41
11
  const propsAffected = ["background", "borderColor", "shadow"];
42
12
  function transformer(file, api) {
43
13
  const j = api.jscodeshift;
44
14
  const root = j(file.source);
45
15
  const toSourceOptions = (0, lineterminator_1.getLineTerminator)(file.source);
46
- if (file.source.includes("TODO: aksel box migration")) {
16
+ if (file.source.includes("TODO: Aksel Box migration")) {
47
17
  return root.toSource(toSourceOptions);
48
18
  }
49
19
  const localName = (0, ast_1.findComponentImport)({
@@ -63,19 +33,24 @@ function transformer(file, api) {
63
33
  },
64
34
  },
65
35
  });
36
+ const predefinedReplacents = predefinedReplacentset();
66
37
  const tokenComments = [];
67
38
  for (const astElement of astElements.paths()) {
68
- let encounteredUnmigratableProp = false;
69
39
  for (const prop of propsAffected) {
70
40
  (0, ast_1.findProps)({ j, path: astElement, name: prop }).forEach((attr) => {
71
41
  const attrvalue = attr.value.value;
72
42
  if (attrvalue.type === "StringLiteral") {
43
+ /**
44
+ * Skips if the replacement token already set
45
+ */
46
+ if (predefinedReplacents.has(addPrefix(attrvalue.value, prop))) {
47
+ return;
48
+ }
73
49
  const config = legacy_tokens_1.legacyTokenConfig[attrvalue.value];
74
50
  if (config === null || config === void 0 ? void 0 : config.replacement) {
75
- attrvalue.value = config.replacement;
51
+ attrvalue.value = cleanReplacementToken(config.replacement, prop);
76
52
  }
77
53
  else {
78
- encounteredUnmigratableProp = true;
79
54
  const tokenComment = {
80
55
  prop,
81
56
  token: attrvalue.value,
@@ -86,6 +61,30 @@ function transformer(file, api) {
86
61
  tokenComments.push(tokenComment);
87
62
  }
88
63
  }
64
+ else if (attrvalue.type === "JSXExpressionContainer" &&
65
+ attrvalue.expression.type === "StringLiteral") {
66
+ const literal = attrvalue.expression;
67
+ /**
68
+ * Skips if the replacement token already set
69
+ */
70
+ if (predefinedReplacents.has(addPrefix(literal.value, prop))) {
71
+ return;
72
+ }
73
+ const config = legacy_tokens_1.legacyTokenConfig[literal.value];
74
+ if (config === null || config === void 0 ? void 0 : config.replacement) {
75
+ literal.value = cleanReplacementToken(config.replacement, prop);
76
+ }
77
+ else {
78
+ const tokenComment = {
79
+ prop,
80
+ token: literal.value,
81
+ };
82
+ if (config === null || config === void 0 ? void 0 : config.comment) {
83
+ tokenComment.comment = config.comment;
84
+ }
85
+ tokenComments.push(tokenComment);
86
+ }
87
+ }
89
88
  });
90
89
  }
91
90
  (0, ast_1.findProps)({ j, path: astElement, name: "borderRadius" }).forEach((attr) => {
@@ -107,46 +106,24 @@ function transformer(file, api) {
107
106
  }
108
107
  });
109
108
  }
109
+ else if (expression.type === "StringLiteral") {
110
+ expression.value = convertBorderRadiusToRadius(expression.value);
111
+ }
110
112
  }
111
113
  });
112
- if (!encounteredUnmigratableProp) {
113
- // TODO: ?? Box -> BoxNew type fail? (but works)
114
- astElement.node.openingElement.name.name = "BoxNew";
115
- astElement.node.closingElement.name.name = "BoxNew";
116
- }
117
114
  }
118
115
  const blockComment = createFileComments({ tokenComments });
119
- const importAnalysis = analyzePartialMigration(j, root.toSource(toSourceOptions));
120
- if (importAnalysis === "no new") {
121
- // WHY: we do nothing to the import statements if we couldn't migrate any Box
122
- }
123
- if (importAnalysis === "mixed") {
124
- // WHY: mixed Box and BoxNew == we keep old, and add the new import
125
- (0, packageImports_1.addPackageImport)({
126
- j,
127
- root,
128
- packageName: "@navikt/ds-react/Box",
129
- specifiers: ["BoxNew"],
130
- });
116
+ if (blockComment) {
117
+ return `${blockComment ? blockComment + "\n\n" : ""}${root.toSource(toSourceOptions)}`;
131
118
  }
132
- if (importAnalysis === "all new") {
133
- // WHY: when we have only new boxes == we replace the old import with the new one
134
- (0, packageImports_1.default)(j, root, {
135
- fromImport: "@navikt/ds-react",
136
- toImport: "@navikt/ds-react/Box",
137
- fromName: "Box",
138
- toName: "BoxNew",
139
- ignoreAlias: true,
140
- });
141
- }
142
- const output = `${blockComment ? blockComment + "\n\n" : ""}${root.toSource(toSourceOptions)}`;
143
- return output;
119
+ file.source = root.toSource(toSourceOptions);
120
+ return (0, box_new_1.default)(file, api);
144
121
  }
145
122
  const createFileComments = ({ tokenComments, }) => {
146
123
  if (tokenComments.length === 0) {
147
124
  return null;
148
125
  }
149
- let constructedComment = "/*\nTODO: aksel box migration:\nCould not migrate the following:\n";
126
+ let constructedComment = "/*\nTODO: Aksel Box migration:\nCould not migrate the following:\n";
150
127
  for (const { prop, token, comment } of tokenComments.values()) {
151
128
  constructedComment += ` - ${prop}=${token}\n`;
152
129
  if (comment) {
@@ -156,38 +133,6 @@ const createFileComments = ({ tokenComments, }) => {
156
133
  constructedComment += "*/";
157
134
  return constructedComment;
158
135
  };
159
- const analyzePartialMigration = (j, source) => {
160
- const root = j(source);
161
- const astNewElements = (0, ast_1.findJSXElement)({
162
- root,
163
- j,
164
- name: "BoxNew",
165
- originalName: "BoxNew",
166
- });
167
- if (astNewElements.length === 0) {
168
- return "no new";
169
- }
170
- const localName = (0, ast_1.findComponentImport)({
171
- root,
172
- j,
173
- name: "Box",
174
- packageType: "react",
175
- });
176
- if (!localName) {
177
- // this should never happen
178
- throw new Error('package imports have been tampered with before the package import "step" in the migration');
179
- }
180
- const astOldElements = (0, ast_1.findJSXElement)({
181
- root,
182
- j,
183
- name: localName,
184
- originalName: "Box",
185
- });
186
- if (astOldElements.length === 0) {
187
- return "all new";
188
- }
189
- return "mixed";
190
- };
191
136
  const legacyBorderRadiusNameTokenLookup = {
192
137
  full: "full",
193
138
  xlarge: "12",
@@ -217,3 +162,38 @@ function convertBorderRadiusToRadius(oldValue) {
217
162
  }
218
163
  return newRadius.join(" ");
219
164
  }
165
+ /**
166
+ * New props in Box do not have bg- or border- prefixes
167
+ * This function removes those prefixes from the tokens
168
+ */
169
+ function cleanReplacementToken(token, type) {
170
+ if (type === "background") {
171
+ return token.replace("bg-", "");
172
+ }
173
+ if (type === "borderColor") {
174
+ return token.replace("border-", "");
175
+ }
176
+ return token;
177
+ }
178
+ /**
179
+ * Adds bg- or border- prefixes to tokens for comparison with existing replacements
180
+ */
181
+ function addPrefix(token, type) {
182
+ if (type === "background") {
183
+ return `bg-${token}`;
184
+ }
185
+ if (type === "borderColor") {
186
+ return `border-${token}`;
187
+ }
188
+ return token;
189
+ }
190
+ function predefinedReplacentset() {
191
+ const set = new Set();
192
+ for (const key in legacy_tokens_1.legacyTokenConfig) {
193
+ const config = legacy_tokens_1.legacyTokenConfig[key];
194
+ if (config.replacement) {
195
+ set.add(config.replacement);
196
+ }
197
+ }
198
+ return set;
199
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = transformer;
4
+ const ast_1 = require("../../../utils/ast");
5
+ const lineterminator_1 = require("../../../utils/lineterminator");
6
+ function transformer(file, api) {
7
+ const j = api.jscodeshift;
8
+ const root = j(file.source);
9
+ const toSourceOptions = (0, lineterminator_1.getLineTerminator)(file.source);
10
+ const boxLocalName = (0, ast_1.findComponentImport)({
11
+ root,
12
+ j,
13
+ name: "Box",
14
+ packageType: "react",
15
+ }) || "Box";
16
+ // Rename <BoxNew ...> to <Box ...>
17
+ root.find(j.JSXOpeningElement).forEach((path) => {
18
+ if (path.value.name.type === "JSXIdentifier" &&
19
+ path.value.name.name === "BoxNew") {
20
+ path.value.name.name = boxLocalName;
21
+ }
22
+ // Rename <Box.New ...> to <Box ...>
23
+ if (path.value.name.type === "JSXMemberExpression" &&
24
+ path.value.name.object.type === "JSXIdentifier" &&
25
+ path.value.name.object.name === boxLocalName &&
26
+ path.value.name.property.name === "New") {
27
+ path.value.name = j.jsxIdentifier(boxLocalName);
28
+ }
29
+ });
30
+ root.find(j.JSXClosingElement).forEach((path) => {
31
+ if (path.value.name.type === "JSXIdentifier" &&
32
+ path.value.name.name === "BoxNew") {
33
+ path.value.name.name = boxLocalName;
34
+ }
35
+ if (path.value.name.type === "JSXMemberExpression" &&
36
+ path.value.name.object.type === "JSXIdentifier" &&
37
+ path.value.name.object.name === boxLocalName &&
38
+ path.value.name.property.name === "New") {
39
+ path.value.name = j.jsxIdentifier(boxLocalName);
40
+ }
41
+ });
42
+ // Handle imports
43
+ const imports = root.find(j.ImportDeclaration).filter((path) => {
44
+ return (path.value.source.value === "@navikt/ds-react" ||
45
+ path.value.source.value === "@navikt/ds-react/Box");
46
+ });
47
+ imports.forEach((path) => {
48
+ const specifiers = path.value.specifiers;
49
+ if (!specifiers)
50
+ return;
51
+ const boxNewIndex = specifiers.findIndex((s) => s.type === "ImportSpecifier" && s.imported.name === "BoxNew");
52
+ if (boxNewIndex !== -1) {
53
+ const boxIndex = specifiers.findIndex((s) => s.type === "ImportSpecifier" && s.imported.name === "Box");
54
+ if (boxIndex !== -1) {
55
+ // Box already imported, remove BoxNew
56
+ const boxNewSpecifier = specifiers[boxNewIndex];
57
+ if (boxNewSpecifier.type === "ImportSpecifier" &&
58
+ boxNewSpecifier.local &&
59
+ boxNewSpecifier.local.name !== "BoxNew") {
60
+ const localName = boxNewSpecifier.local.name;
61
+ root.find(j.JSXOpeningElement).forEach((jsxPath) => {
62
+ if (jsxPath.value.name.type === "JSXIdentifier" &&
63
+ jsxPath.value.name.name === localName) {
64
+ jsxPath.value.name.name = boxLocalName;
65
+ }
66
+ });
67
+ root.find(j.JSXClosingElement).forEach((jsxPath) => {
68
+ if (jsxPath.value.name.type === "JSXIdentifier" &&
69
+ jsxPath.value.name.name === localName) {
70
+ jsxPath.value.name.name = boxLocalName;
71
+ }
72
+ });
73
+ }
74
+ specifiers.splice(boxNewIndex, 1);
75
+ }
76
+ else {
77
+ // Rename BoxNew to Box
78
+ const boxNewSpecifier = specifiers[boxNewIndex];
79
+ if (boxNewSpecifier.type === "ImportSpecifier") {
80
+ boxNewSpecifier.imported.name = "Box";
81
+ // If local name is BoxNew, rename it to Box
82
+ if (boxNewSpecifier.local &&
83
+ boxNewSpecifier.local.name === "BoxNew") {
84
+ boxNewSpecifier.local.name = "Box";
85
+ }
86
+ }
87
+ }
88
+ }
89
+ });
90
+ return root.toSource(toSourceOptions);
91
+ }