@navikt/aksel 7.35.0 → 7.35.2
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/dist/codemod/codeshift.utils.js +9 -1
- package/dist/codemod/migrations.js +27 -27
- package/dist/codemod/run-codeshift.js +14 -3
- package/dist/codemod/transforms/v8.0.0/box/box.js +50 -2
- package/dist/codemod/utils/ast.js +1 -1
- package/dist/darkside/index.js +3 -9
- package/dist/darkside/run-tooling.js +138 -42
- package/dist/darkside/tasks/print-remaining.js +148 -38
- package/dist/darkside/tasks/status.js +147 -30
- package/dist/darkside/transforms/darkside-tokens-css.js +23 -8
- package/dist/darkside/transforms/darkside-tokens-tailwind.js +9 -10
- package/dist/index.js +14 -15
- package/package.json +10 -10
|
@@ -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
|
-
|
|
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
|
|
@@ -134,30 +134,6 @@ exports.migrations = {
|
|
|
134
134
|
path: "v8.0.0/prop-deprecate/prop-deprecate",
|
|
135
135
|
ignoredExtensions: CSS_EXTENSIONS,
|
|
136
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",
|
|
141
|
-
ignoredExtensions: CSS_EXTENSIONS,
|
|
142
|
-
},
|
|
143
|
-
{
|
|
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",
|
|
147
|
-
ignoredExtensions: CSS_EXTENSIONS,
|
|
148
|
-
},
|
|
149
|
-
{
|
|
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
137
|
{
|
|
162
138
|
description: "Tries to migrate List component moving 'title' and 'description' props to 'Heading' and 'BodyShort'.",
|
|
163
139
|
value: "v8-list",
|
|
@@ -182,6 +158,30 @@ exports.migrations = {
|
|
|
182
158
|
path: "v8.0.0/token-spacing-js/spacing",
|
|
183
159
|
ignoredExtensions: CSS_EXTENSIONS,
|
|
184
160
|
},
|
|
161
|
+
{
|
|
162
|
+
description: "Updates variant + data-color props on Tag based on current variant prop.",
|
|
163
|
+
value: "v8-tag-variant",
|
|
164
|
+
path: "v8.0.0/tag-variant/tag-variant",
|
|
165
|
+
ignoredExtensions: CSS_EXTENSIONS,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
description: "Updates variant + data-color props on ToggleGroup based on current variant prop.",
|
|
169
|
+
value: "v8-toggle-group-variant",
|
|
170
|
+
path: "v8.0.0/toggle-group-variant/toggle-group-variant",
|
|
171
|
+
ignoredExtensions: CSS_EXTENSIONS,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
description: "Updates variant + data-color props on Accordion based on current variant prop.",
|
|
175
|
+
value: "v8-accordion-variant",
|
|
176
|
+
path: "v8.0.0/accordion-variant/accordion-variant",
|
|
177
|
+
ignoredExtensions: CSS_EXTENSIONS,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
description: "Updates variant + data-color props on Chips based on current variant prop.",
|
|
181
|
+
value: "v8-chips-variant",
|
|
182
|
+
path: "v8.0.0/chips-variant/chips-variant",
|
|
183
|
+
ignoredExtensions: CSS_EXTENSIONS,
|
|
184
|
+
},
|
|
185
185
|
],
|
|
186
186
|
};
|
|
187
187
|
/**
|
|
@@ -235,13 +235,13 @@ function getMigrationString() {
|
|
|
235
235
|
let str = "";
|
|
236
236
|
Object.entries(exports.migrations).forEach(([version, vMigrations]) => {
|
|
237
237
|
str += `\n${chalk_1.default.underline(version)}\n`;
|
|
238
|
-
vMigrations.forEach((migration) => {
|
|
239
|
-
str += `${chalk_1.default.blue(migration.value)}: ${migration.description}\n`;
|
|
240
|
-
});
|
|
241
238
|
const overrideMigrations = exports.migrationStringOverride[version] || [];
|
|
242
239
|
overrideMigrations.forEach((migration) => {
|
|
243
240
|
str += `${chalk_1.default.blue(migration.value)}: ${migration.description}\n`;
|
|
244
241
|
});
|
|
242
|
+
vMigrations.forEach((migration) => {
|
|
243
|
+
str += `${chalk_1.default.blue(migration.value)}: ${migration.description}\n`;
|
|
244
|
+
});
|
|
245
245
|
});
|
|
246
246
|
return str;
|
|
247
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
|
-
|
|
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;
|
|
@@ -33,15 +33,22 @@ function transformer(file, api) {
|
|
|
33
33
|
},
|
|
34
34
|
},
|
|
35
35
|
});
|
|
36
|
+
const predefinedReplacents = predefinedReplacentset();
|
|
36
37
|
const tokenComments = [];
|
|
37
38
|
for (const astElement of astElements.paths()) {
|
|
38
39
|
for (const prop of propsAffected) {
|
|
39
40
|
(0, ast_1.findProps)({ j, path: astElement, name: prop }).forEach((attr) => {
|
|
40
41
|
const attrvalue = attr.value.value;
|
|
41
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
|
+
}
|
|
42
49
|
const config = legacy_tokens_1.legacyTokenConfig[attrvalue.value];
|
|
43
50
|
if (config === null || config === void 0 ? void 0 : config.replacement) {
|
|
44
|
-
attrvalue.value = config.replacement;
|
|
51
|
+
attrvalue.value = cleanReplacementToken(config.replacement, prop);
|
|
45
52
|
}
|
|
46
53
|
else {
|
|
47
54
|
const tokenComment = {
|
|
@@ -57,9 +64,15 @@ function transformer(file, api) {
|
|
|
57
64
|
else if (attrvalue.type === "JSXExpressionContainer" &&
|
|
58
65
|
attrvalue.expression.type === "StringLiteral") {
|
|
59
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
|
+
}
|
|
60
73
|
const config = legacy_tokens_1.legacyTokenConfig[literal.value];
|
|
61
74
|
if (config === null || config === void 0 ? void 0 : config.replacement) {
|
|
62
|
-
literal.value = config.replacement;
|
|
75
|
+
literal.value = cleanReplacementToken(config.replacement, prop);
|
|
63
76
|
}
|
|
64
77
|
else {
|
|
65
78
|
const tokenComment = {
|
|
@@ -149,3 +162,38 @@ function convertBorderRadiusToRadius(oldValue) {
|
|
|
149
162
|
}
|
|
150
163
|
return newRadius.join(" ");
|
|
151
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
|
+
}
|
package/dist/darkside/index.js
CHANGED
|
@@ -6,23 +6,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.darksideCommand = darksideCommand;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const commander_1 = require("commander");
|
|
9
|
-
const validation_js_1 = require("../codemod/validation.js");
|
|
10
|
-
// import figlet from "figlet";
|
|
11
|
-
// import { getMigrationString } from "./migrations.js";
|
|
12
9
|
const run_tooling_js_1 = require("./run-tooling.js");
|
|
13
10
|
const program = new commander_1.Command();
|
|
14
11
|
function darksideCommand() {
|
|
15
|
-
program.name(`${chalk_1.default.blueBright(`npx @navikt/aksel`)}`);
|
|
12
|
+
program.name(`${chalk_1.default.blueBright(`npx @navikt/aksel v8-tokens`)}`);
|
|
16
13
|
program
|
|
17
14
|
.option("-g, --glob [glob]", "Globbing pattern, overrides --ext! Run with 'noglob' if using zsh-terminal. ")
|
|
15
|
+
.option("-e, --ext [ext]", "File extensions to include, defaults to 'js,ts,jsx,tsx,css,scss,less'")
|
|
18
16
|
.option("-d, --dry-run", "Dry run, no changes will be made")
|
|
19
17
|
.option("-f, --force", "Forcibly run updates without checking git-changes")
|
|
20
|
-
.description("Update tool for
|
|
18
|
+
.description("Update tool for v8 token updates");
|
|
21
19
|
program.parse();
|
|
22
20
|
const options = program.opts();
|
|
23
|
-
/* Makes sure that you don't migrate lots of files while having other uncommitted changes */
|
|
24
|
-
if (!options.force) {
|
|
25
|
-
(0, validation_js_1.validateGit)(options, program);
|
|
26
|
-
}
|
|
27
21
|
(0, run_tooling_js_1.runTooling)(options, program);
|
|
28
22
|
}
|
|
@@ -63,50 +63,46 @@ const TRANSFORMS = {
|
|
|
63
63
|
"js-tokens": "./transforms/darkside-tokens-js",
|
|
64
64
|
"tailwind-tokens": "./transforms/darkside-tokens-tailwind",
|
|
65
65
|
};
|
|
66
|
-
const TASK_MENU = {
|
|
67
|
-
type: "select",
|
|
68
|
-
name: "task",
|
|
69
|
-
message: "Task",
|
|
70
|
-
initial: "status",
|
|
71
|
-
choices: [
|
|
72
|
-
{ message: "Check status", name: "status" },
|
|
73
|
-
{ message: "Print remaining tokens", name: "print-remaining-tokens" },
|
|
74
|
-
{ message: "Migrate CSS tokens", name: "css-tokens" },
|
|
75
|
-
{ message: "Migrate Scss tokens", name: "scss-tokens" },
|
|
76
|
-
{ message: "Migrate Less tokens", name: "less-tokens" },
|
|
77
|
-
{ message: "Migrate JS tokens", name: "js-tokens" },
|
|
78
|
-
{ message: "Migrate tailwind tokens", name: "tailwind-tokens" },
|
|
79
|
-
{ message: "Run all migrations", name: "run-all-migrations" },
|
|
80
|
-
{ message: "Exit", name: "exit" },
|
|
81
|
-
],
|
|
82
|
-
};
|
|
83
66
|
/**
|
|
84
67
|
* Main entry point for the tooling system
|
|
85
68
|
*/
|
|
86
69
|
function runTooling(options, program) {
|
|
87
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
71
|
var _a;
|
|
72
|
+
console.info(chalk_1.default.greenBright.bold("\nWelcome to the Aksel v8 token migration tool!"));
|
|
73
|
+
const globList = (_a = options.glob) !== null && _a !== void 0 ? _a : (0, codeshift_utils_1.getDefaultGlob)(options === null || options === void 0 ? void 0 : options.ext);
|
|
74
|
+
console.info(chalk_1.default.gray(`Using glob pattern(s): ${globList}\nWorking directory: ${process.cwd()}\n`));
|
|
89
75
|
// Find matching files based on glob pattern
|
|
90
|
-
const filepaths =
|
|
76
|
+
const filepaths = yield (0, fast_glob_1.default)(globList, {
|
|
91
77
|
cwd: process.cwd(),
|
|
92
78
|
ignore: codeshift_utils_1.GLOB_IGNORE_PATTERNS,
|
|
79
|
+
/**
|
|
80
|
+
* When globbing, do not follow symlinks to avoid processing files outside the directory.
|
|
81
|
+
* This is most likely to happen in monorepos where node_modules may contain symlinks to packages
|
|
82
|
+
* in other parts of the repo.
|
|
83
|
+
*
|
|
84
|
+
* While node_modules is already ignored via GLOB_IGNORE_PATTERNS, if user globs upwards (e.g., using '../src/**'),
|
|
85
|
+
* that ignore-pattern may be ignored, leading to unintended file processing.
|
|
86
|
+
*/
|
|
87
|
+
followSymbolicLinks: false,
|
|
93
88
|
});
|
|
94
89
|
if (options.dryRun) {
|
|
95
90
|
console.info(chalk_1.default.yellow("Running in dry-run mode, no changes will be made"));
|
|
96
91
|
}
|
|
97
92
|
// Show initial status
|
|
98
|
-
(0, status_1.getStatus)(filepaths);
|
|
93
|
+
const initialStatus = (0, status_1.getStatus)(filepaths);
|
|
99
94
|
// Task execution loop
|
|
100
|
-
let task = yield getNextTask();
|
|
95
|
+
let task = yield getNextTask(initialStatus.status);
|
|
96
|
+
let currentStatus = initialStatus;
|
|
101
97
|
while (task !== "exit") {
|
|
102
98
|
console.info("\n\n");
|
|
103
99
|
try {
|
|
104
|
-
yield executeTask(task, filepaths, options, program);
|
|
100
|
+
currentStatus = yield executeTask(task, filepaths, options, program, currentStatus, () => (0, status_1.getStatus)(filepaths, "no-print"));
|
|
105
101
|
}
|
|
106
102
|
catch (error) {
|
|
107
103
|
program.error(chalk_1.default.red("Error:", error.message));
|
|
108
104
|
}
|
|
109
|
-
task = yield getNextTask();
|
|
105
|
+
task = yield getNextTask(currentStatus.status);
|
|
110
106
|
}
|
|
111
107
|
process.exit(0);
|
|
112
108
|
});
|
|
@@ -114,27 +110,34 @@ function runTooling(options, program) {
|
|
|
114
110
|
/**
|
|
115
111
|
* Executes the selected task
|
|
116
112
|
*/
|
|
117
|
-
function executeTask(task, filepaths, options, program) {
|
|
113
|
+
function executeTask(task, filepaths, options, program, statusStore, updateStatus) {
|
|
118
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
119
115
|
switch (task) {
|
|
120
116
|
case "status":
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
(0, print_remaining_1.printRemaining)(filepaths);
|
|
125
|
-
|
|
117
|
+
return updateStatus();
|
|
118
|
+
case "print-remaining-tokens": {
|
|
119
|
+
const newStatus = updateStatus();
|
|
120
|
+
yield (0, print_remaining_1.printRemaining)(filepaths, newStatus.status);
|
|
121
|
+
return newStatus;
|
|
122
|
+
}
|
|
126
123
|
case "css-tokens":
|
|
127
124
|
case "scss-tokens":
|
|
128
125
|
case "less-tokens":
|
|
129
126
|
case "js-tokens":
|
|
130
127
|
case "tailwind-tokens": {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
if (!options.force) {
|
|
129
|
+
(0, validation_1.validateGit)(options, program);
|
|
130
|
+
}
|
|
131
|
+
const scopedFiles = getScopedFilesForTask(task, filepaths, statusStore.status);
|
|
132
|
+
const tokensBefore = getTokenCount(statusStore.status, task);
|
|
133
|
+
const stats = yield runCodeshift(task, scopedFiles, {
|
|
134
134
|
dryRun: options.dryRun,
|
|
135
135
|
force: options.force,
|
|
136
136
|
});
|
|
137
|
-
|
|
137
|
+
const newStatus = updateStatus();
|
|
138
|
+
const tokensAfter = getTokenCount(newStatus.status, task);
|
|
139
|
+
printSummary(task, stats, tokensBefore, tokensAfter);
|
|
140
|
+
return newStatus;
|
|
138
141
|
}
|
|
139
142
|
case "run-all-migrations": {
|
|
140
143
|
const tasks = [
|
|
@@ -144,20 +147,45 @@ function executeTask(task, filepaths, options, program) {
|
|
|
144
147
|
"js-tokens",
|
|
145
148
|
"tailwind-tokens",
|
|
146
149
|
];
|
|
150
|
+
if (!options.force) {
|
|
151
|
+
(0, validation_1.validateGit)(options, program);
|
|
152
|
+
}
|
|
153
|
+
let currentStatus = statusStore;
|
|
154
|
+
const summaryData = [];
|
|
147
155
|
for (const migrationTask of tasks) {
|
|
148
|
-
if (!options.force) {
|
|
149
|
-
(0, validation_1.validateGit)(options, program);
|
|
150
|
-
}
|
|
151
156
|
console.info(`\nRunning ${migrationTask}...`);
|
|
152
|
-
|
|
157
|
+
const scopedFiles = getScopedFilesForTask(migrationTask, filepaths, currentStatus.status);
|
|
158
|
+
const tokensBefore = getTokenCount(currentStatus.status, migrationTask);
|
|
159
|
+
const stats = yield runCodeshift(migrationTask, scopedFiles, {
|
|
153
160
|
dryRun: options.dryRun,
|
|
154
161
|
force: true,
|
|
155
162
|
});
|
|
163
|
+
currentStatus = updateStatus();
|
|
164
|
+
const tokensAfter = getTokenCount(currentStatus.status, migrationTask);
|
|
165
|
+
summaryData.push({
|
|
166
|
+
task: migrationTask,
|
|
167
|
+
stats,
|
|
168
|
+
tokensBefore,
|
|
169
|
+
tokensAfter,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
console.info(chalk_1.default.bold(`\nMigration Summary:`));
|
|
173
|
+
console.info("-".repeat(60));
|
|
174
|
+
for (const data of summaryData) {
|
|
175
|
+
const replaced = data.tokensBefore - data.tokensAfter;
|
|
176
|
+
const remaining = data.tokensAfter;
|
|
177
|
+
const icon = remaining === 0 ? "✨" : "⚠️";
|
|
178
|
+
console.info(`${chalk_1.default.bold(data.task)}:`);
|
|
179
|
+
console.info(` Files changed: ${data.stats.ok}`);
|
|
180
|
+
console.info(` Tokens replaced: ${replaced}`);
|
|
181
|
+
console.info(` ${icon} Remaining: ${remaining}`);
|
|
182
|
+
console.info("");
|
|
156
183
|
}
|
|
157
|
-
|
|
184
|
+
return currentStatus;
|
|
158
185
|
}
|
|
159
186
|
default:
|
|
160
187
|
program.error(chalk_1.default.red(`Unknown task: ${task}`));
|
|
188
|
+
return statusStore;
|
|
161
189
|
}
|
|
162
190
|
});
|
|
163
191
|
}
|
|
@@ -201,7 +229,7 @@ function runCodeshift(task, filepaths, options) {
|
|
|
201
229
|
throw new Error(`No transform found for task: ${task}`);
|
|
202
230
|
}
|
|
203
231
|
const codemodPath = node_path_1.default.join(__dirname, `${TRANSFORMS[task]}.js`);
|
|
204
|
-
yield jscodeshift.run(codemodPath, filepaths, {
|
|
232
|
+
return yield jscodeshift.run(codemodPath, filepaths, {
|
|
205
233
|
babel: true,
|
|
206
234
|
ignorePattern: codeshift_utils_1.GLOB_IGNORE_PATTERNS,
|
|
207
235
|
parser: "tsx",
|
|
@@ -218,12 +246,52 @@ function runCodeshift(task, filepaths, options) {
|
|
|
218
246
|
/**
|
|
219
247
|
* Prompts the user for the next task to run
|
|
220
248
|
*/
|
|
221
|
-
function getNextTask() {
|
|
249
|
+
function getNextTask(status) {
|
|
222
250
|
return __awaiter(this, void 0, void 0, function* () {
|
|
251
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
252
|
+
const getMessage = (base, tokens) => {
|
|
253
|
+
if (!status)
|
|
254
|
+
return base;
|
|
255
|
+
const fileCount = new Set(tokens.map((t) => t.fileName)).size;
|
|
256
|
+
if (fileCount === 0)
|
|
257
|
+
return `${base} (Done)`;
|
|
258
|
+
return `${base} (${fileCount} files)`;
|
|
259
|
+
};
|
|
260
|
+
const choices = [
|
|
261
|
+
{ message: "Check status", name: "status" },
|
|
262
|
+
{ message: "Print status", name: "print-remaining-tokens" },
|
|
263
|
+
{
|
|
264
|
+
message: getMessage("Migrate CSS tokens", (_b = (_a = status === null || status === void 0 ? void 0 : status.css) === null || _a === void 0 ? void 0 : _a.legacy) !== null && _b !== void 0 ? _b : []),
|
|
265
|
+
name: "css-tokens",
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
message: getMessage("Migrate Scss tokens", (_d = (_c = status === null || status === void 0 ? void 0 : status.scss) === null || _c === void 0 ? void 0 : _c.legacy) !== null && _d !== void 0 ? _d : []),
|
|
269
|
+
name: "scss-tokens",
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
message: getMessage("Migrate Less tokens", (_f = (_e = status === null || status === void 0 ? void 0 : status.less) === null || _e === void 0 ? void 0 : _e.legacy) !== null && _f !== void 0 ? _f : []),
|
|
273
|
+
name: "less-tokens",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
message: getMessage("Migrate JS tokens", (_h = (_g = status === null || status === void 0 ? void 0 : status.js) === null || _g === void 0 ? void 0 : _g.legacy) !== null && _h !== void 0 ? _h : []),
|
|
277
|
+
name: "js-tokens",
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
message: getMessage("Migrate tailwind tokens", (_k = (_j = status === null || status === void 0 ? void 0 : status.tailwind) === null || _j === void 0 ? void 0 : _j.legacy) !== null && _k !== void 0 ? _k : []),
|
|
281
|
+
name: "tailwind-tokens",
|
|
282
|
+
},
|
|
283
|
+
{ message: "Run all migrations", name: "run-all-migrations" },
|
|
284
|
+
{ message: "Exit", name: "exit" },
|
|
285
|
+
];
|
|
223
286
|
try {
|
|
224
|
-
const response = yield enquirer_1.default.prompt(
|
|
225
|
-
|
|
226
|
-
|
|
287
|
+
const response = yield enquirer_1.default.prompt({
|
|
288
|
+
type: "select",
|
|
289
|
+
name: "task",
|
|
290
|
+
message: "Task",
|
|
291
|
+
initial: "status",
|
|
292
|
+
choices,
|
|
293
|
+
onCancel: () => process.exit(1),
|
|
294
|
+
});
|
|
227
295
|
return response.task;
|
|
228
296
|
}
|
|
229
297
|
catch (error) {
|
|
@@ -238,3 +306,31 @@ function getNextTask() {
|
|
|
238
306
|
}
|
|
239
307
|
});
|
|
240
308
|
}
|
|
309
|
+
function getTokenCount(status, task) {
|
|
310
|
+
switch (task) {
|
|
311
|
+
case "css-tokens":
|
|
312
|
+
return status.css.legacy.length;
|
|
313
|
+
case "scss-tokens":
|
|
314
|
+
return status.scss.legacy.length;
|
|
315
|
+
case "less-tokens":
|
|
316
|
+
return status.less.legacy.length;
|
|
317
|
+
case "js-tokens":
|
|
318
|
+
return status.js.legacy.length;
|
|
319
|
+
case "tailwind-tokens":
|
|
320
|
+
return status.tailwind.legacy.length;
|
|
321
|
+
default:
|
|
322
|
+
return 0;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function printSummary(task, stats, tokensBefore, tokensAfter) {
|
|
326
|
+
console.info(chalk_1.default.bold(`\nMigration Summary for ${task}:`));
|
|
327
|
+
console.info("-".repeat(40));
|
|
328
|
+
console.info(`✅ Files changed: ${stats.ok}`);
|
|
329
|
+
console.info(`✅ Tokens replaced: ${tokensBefore - tokensAfter}`);
|
|
330
|
+
if (tokensAfter > 0) {
|
|
331
|
+
console.info(chalk_1.default.yellow(`⚠️ Tokens remaining: ${tokensAfter} (manual intervention needed)`));
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
console.info(chalk_1.default.green(`✨ Tokens remaining: ${tokensAfter}`));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
@@ -1,51 +1,161 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
5
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
15
|
exports.printRemaining = printRemaining;
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const clipboardy_1 = __importDefault(require("clipboardy"));
|
|
18
|
+
const enquirer_1 = __importDefault(require("enquirer"));
|
|
7
19
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
20
|
const status_1 = require("./status");
|
|
9
|
-
function printRemaining(files) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
console.info("
|
|
20
|
-
|
|
21
|
+
function printRemaining(files, status) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
process.stdout.write("\nAnalyzing...");
|
|
24
|
+
/**
|
|
25
|
+
* Skip re-calculating status if already provided
|
|
26
|
+
*/
|
|
27
|
+
const statusObj = status !== null && status !== void 0 ? status : (0, status_1.getStatus)(files, "no-print").status;
|
|
28
|
+
/* Flatten all legacy tokens */
|
|
29
|
+
const allTokens = Object.values(statusObj).flatMap((data) => data.legacy);
|
|
30
|
+
if (allTokens.length === 0) {
|
|
31
|
+
console.info("\nNo legacy tokens found!");
|
|
32
|
+
return;
|
|
21
33
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
const response = yield enquirer_1.default.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: "select",
|
|
37
|
+
name: "groupBy",
|
|
38
|
+
message: "How would you like to group the remaining tokens?",
|
|
39
|
+
choices: [
|
|
40
|
+
{ message: "By File", name: "file" },
|
|
41
|
+
{ message: "By Token", name: "token" },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "confirm",
|
|
46
|
+
name: "copy",
|
|
47
|
+
message: "Copy report to clipboard?",
|
|
48
|
+
initial: true,
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
const { groupBy, copy } = response;
|
|
52
|
+
console.info("\n");
|
|
53
|
+
let jsonOutput;
|
|
54
|
+
/**
|
|
55
|
+
* Group by filename
|
|
56
|
+
*/
|
|
57
|
+
if (groupBy === "file") {
|
|
58
|
+
const byFile = new Map();
|
|
59
|
+
allTokens.forEach((token) => {
|
|
60
|
+
if (!byFile.has(token.fileName)) {
|
|
61
|
+
byFile.set(token.fileName, []);
|
|
62
|
+
}
|
|
63
|
+
byFile.get(token.fileName).push(token);
|
|
64
|
+
});
|
|
65
|
+
/* Sort files by number of tokens (descending) */
|
|
66
|
+
const sortedFiles = Array.from(byFile.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
67
|
+
const fileOutput = [];
|
|
68
|
+
sortedFiles.forEach(([fileName, tokens]) => {
|
|
69
|
+
const fullPath = node_path_1.default.resolve(process.cwd(), fileName);
|
|
70
|
+
log(`${fileName} (${tokens.length} tokens)`, 0, "blueBright");
|
|
71
|
+
/* Sort tokens in file by line number */
|
|
72
|
+
tokens.sort((a, b) => a.lineNumber - b.lineNumber);
|
|
73
|
+
const fileEntry = {
|
|
74
|
+
file: fileName,
|
|
75
|
+
fullPath,
|
|
76
|
+
count: tokens.length,
|
|
77
|
+
tokens: [],
|
|
78
|
+
};
|
|
79
|
+
tokens.forEach((token) => {
|
|
80
|
+
if (token.comment) {
|
|
81
|
+
log(`/* ${token.comment} */`, 1, "gray");
|
|
82
|
+
}
|
|
83
|
+
log(`${chalk_1.default.blueBright(token.name)}: ${fullPath}:${token.lineNumber}:${token.columnNumber}`, 1);
|
|
84
|
+
fileEntry.tokens.push({
|
|
85
|
+
name: token.name,
|
|
86
|
+
line: token.lineNumber,
|
|
87
|
+
column: token.columnNumber,
|
|
88
|
+
comment: token.comment,
|
|
89
|
+
link: `file://${fullPath}`,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
/* Empty line */
|
|
93
|
+
log("");
|
|
94
|
+
fileOutput.push(fileEntry);
|
|
95
|
+
});
|
|
96
|
+
jsonOutput = fileOutput;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
/* Group by token name */
|
|
100
|
+
const byToken = new Map();
|
|
101
|
+
allTokens.forEach((token) => {
|
|
102
|
+
if (!byToken.has(token.name)) {
|
|
103
|
+
byToken.set(token.name, []);
|
|
104
|
+
}
|
|
105
|
+
byToken.get(token.name).push(token);
|
|
106
|
+
});
|
|
107
|
+
/* Sort tokens by frequency (descending) */
|
|
108
|
+
const sortedTokens = Array.from(byToken.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
109
|
+
const tokenOutput = [];
|
|
110
|
+
sortedTokens.forEach(([tokenName, tokens]) => {
|
|
111
|
+
var _a;
|
|
112
|
+
log(`${chalk_1.default.blueBright(tokenName)} (${tokens.length} occurrences)`, 0, "blueBright");
|
|
113
|
+
/**
|
|
114
|
+
* We can assume all comments are the same for a "tokenName"
|
|
115
|
+
*/
|
|
116
|
+
const foundComment = (_a = tokens.find((t) => t.comment)) === null || _a === void 0 ? void 0 : _a.comment;
|
|
117
|
+
if (foundComment) {
|
|
118
|
+
log(`/* ${foundComment} */`, 1, "gray");
|
|
119
|
+
}
|
|
120
|
+
const tokenEntry = {
|
|
121
|
+
token: tokenName,
|
|
122
|
+
count: tokens.length,
|
|
123
|
+
occurrences: [],
|
|
124
|
+
};
|
|
125
|
+
tokens.forEach((token) => {
|
|
126
|
+
const fullPath = node_path_1.default.resolve(process.cwd(), token.fileName);
|
|
127
|
+
log(`${fullPath}:${token.lineNumber}:${token.columnNumber}`, 1);
|
|
128
|
+
tokenEntry.occurrences.push({
|
|
129
|
+
file: token.fileName,
|
|
130
|
+
fullPath,
|
|
131
|
+
line: token.lineNumber,
|
|
132
|
+
column: token.columnNumber,
|
|
133
|
+
comment: token.comment,
|
|
134
|
+
link: `file://${fullPath}`,
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
/* Empty line */
|
|
138
|
+
log("");
|
|
139
|
+
tokenOutput.push(tokenEntry);
|
|
42
140
|
});
|
|
43
|
-
|
|
44
|
-
|
|
141
|
+
jsonOutput = tokenOutput;
|
|
142
|
+
}
|
|
143
|
+
if (copy) {
|
|
144
|
+
try {
|
|
145
|
+
clipboardy_1.default.writeSync(JSON.stringify(jsonOutput, null, 2));
|
|
146
|
+
console.info("✅ Report (JSON) copied to clipboard!");
|
|
45
147
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error("❌ Failed to copy to clipboard:", error.message);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
49
152
|
});
|
|
50
|
-
|
|
153
|
+
}
|
|
154
|
+
function log(str, indent = 0, chalkColor) {
|
|
155
|
+
const prefix = " ".repeat(indent);
|
|
156
|
+
if (chalkColor) {
|
|
157
|
+
console.info(prefix + chalk_1.default[chalkColor](str));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
console.info(prefix + str);
|
|
51
161
|
}
|
|
@@ -4,13 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getStatus = getStatus;
|
|
7
|
+
exports.getCharacterPositionInFile = getCharacterPositionInFile;
|
|
8
|
+
exports.getLineStarts = getLineStarts;
|
|
7
9
|
const cli_progress_1 = __importDefault(require("cli-progress"));
|
|
8
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
|
+
const translate_token_1 = require("../../codemod/utils/translate-token");
|
|
9
12
|
const TokenStatus_1 = require("../config/TokenStatus");
|
|
10
13
|
const darkside_tokens_1 = require("../config/darkside.tokens");
|
|
11
14
|
const legacy_component_tokens_1 = require("../config/legacy-component.tokens");
|
|
12
15
|
const legacy_tokens_1 = require("../config/legacy.tokens");
|
|
13
|
-
const token_regex_1 = require("../config/token-regex");
|
|
14
16
|
const StatusStore = new TokenStatus_1.TokenStatus();
|
|
15
17
|
/**
|
|
16
18
|
* Get the status of the tokens in the files
|
|
@@ -25,13 +27,57 @@ function getStatus(files, action = "print") {
|
|
|
25
27
|
progressBar.start(files.length, 0);
|
|
26
28
|
}
|
|
27
29
|
StatusStore.initStatus();
|
|
30
|
+
/**
|
|
31
|
+
* Prepare search terms for legacy and darkside tokens.
|
|
32
|
+
* By pre-computing these sets, we save re-calculating them for each file,
|
|
33
|
+
* improving performance when processing large numbers of files.
|
|
34
|
+
*/
|
|
35
|
+
const legacySearchTerms = getLegacySearchTerms();
|
|
36
|
+
const darksideSearchTerms = getDarksideSearchTerms();
|
|
37
|
+
const legacyComponentTokensSet = new Set(legacy_component_tokens_1.legacyComponentTokenList);
|
|
38
|
+
/**
|
|
39
|
+
* Pre-computed regex for legacy component tokens
|
|
40
|
+
*/
|
|
41
|
+
const legacyRegex = new RegExp(`(${legacy_component_tokens_1.legacyComponentTokenList.map((t) => `${t}:`).join("|")})`, "gm");
|
|
42
|
+
/**
|
|
43
|
+
* Process each file to find and record token usages
|
|
44
|
+
*/
|
|
28
45
|
files.forEach((fileName, index) => {
|
|
29
46
|
const fileSrc = node_fs_1.default.readFileSync(fileName, "utf8");
|
|
47
|
+
/**
|
|
48
|
+
* Create a set of all words in the file to quickly check for potential matches
|
|
49
|
+
*/
|
|
50
|
+
const fileWords = new Set(fileSrc.match(/[a-zA-Z0-9_@$-]+/g) || []);
|
|
51
|
+
let lineStarts;
|
|
52
|
+
/**
|
|
53
|
+
* Gets line-start positions for the file, caching the result.
|
|
54
|
+
* We only calculate this if we actually find a token match, saving processing time.
|
|
55
|
+
*/
|
|
56
|
+
const getLineStartsLazy = () => {
|
|
57
|
+
if (!lineStarts) {
|
|
58
|
+
lineStarts = getLineStarts(fileSrc);
|
|
59
|
+
}
|
|
60
|
+
return lineStarts;
|
|
61
|
+
};
|
|
30
62
|
/**
|
|
31
63
|
* We first parse trough all legacy tokens (--a-) prefixed tokens
|
|
32
64
|
*/
|
|
33
65
|
for (const [legacyToken, config] of Object.entries(legacy_tokens_1.legacyTokenConfig)) {
|
|
34
|
-
|
|
66
|
+
const terms = legacySearchTerms.get(legacyToken);
|
|
67
|
+
/**
|
|
68
|
+
* Optimization: Check if any of the search terms exist in the file words set
|
|
69
|
+
* before running expensive regex operations.
|
|
70
|
+
*/
|
|
71
|
+
let found = false;
|
|
72
|
+
if (terms) {
|
|
73
|
+
for (const term of terms) {
|
|
74
|
+
if (fileWords.has(term)) {
|
|
75
|
+
found = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!found) {
|
|
35
81
|
continue;
|
|
36
82
|
}
|
|
37
83
|
for (const [regexKey, regex] of Object.entries(config.regexes)) {
|
|
@@ -40,7 +86,7 @@ function getStatus(files, action = "print") {
|
|
|
40
86
|
}
|
|
41
87
|
let match = regex.exec(fileSrc);
|
|
42
88
|
while (match) {
|
|
43
|
-
const { row, column } =
|
|
89
|
+
const { row, column } = getCharacterPositionInFile(match.index, getLineStartsLazy());
|
|
44
90
|
StatusStore.add({
|
|
45
91
|
isLegacy: true,
|
|
46
92
|
comment: config.comment,
|
|
@@ -57,23 +103,43 @@ function getStatus(files, action = "print") {
|
|
|
57
103
|
}
|
|
58
104
|
}
|
|
59
105
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
106
|
+
let hasLegacyComponentToken = false;
|
|
107
|
+
for (const token of legacyComponentTokensSet) {
|
|
108
|
+
if (fileWords.has(token)) {
|
|
109
|
+
hasLegacyComponentToken = true;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (hasLegacyComponentToken) {
|
|
114
|
+
legacyRegex.lastIndex = 0;
|
|
115
|
+
let legacyMatch = legacyRegex.exec(fileSrc);
|
|
116
|
+
while (legacyMatch !== null) {
|
|
117
|
+
const { row, column } = getCharacterPositionInFile(legacyMatch.index, getLineStartsLazy());
|
|
118
|
+
StatusStore.add({
|
|
119
|
+
isLegacy: true,
|
|
120
|
+
type: "component",
|
|
121
|
+
columnNumber: column,
|
|
122
|
+
lineNumber: row,
|
|
123
|
+
canAutoMigrate: false,
|
|
124
|
+
fileName,
|
|
125
|
+
name: legacyMatch[0],
|
|
126
|
+
});
|
|
127
|
+
legacyMatch = legacyRegex.exec(fileSrc);
|
|
128
|
+
}
|
|
74
129
|
}
|
|
75
130
|
for (const [newTokenName, config] of Object.entries(darkside_tokens_1.darksideTokenConfig)) {
|
|
76
|
-
|
|
131
|
+
const terms = darksideSearchTerms.get(newTokenName);
|
|
132
|
+
/* Optimization: Check if any of the search terms exist in the file words set */
|
|
133
|
+
let found = false;
|
|
134
|
+
if (terms) {
|
|
135
|
+
for (const term of terms) {
|
|
136
|
+
if (fileWords.has(term)) {
|
|
137
|
+
found = true;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (!found) {
|
|
77
143
|
continue;
|
|
78
144
|
}
|
|
79
145
|
for (const [regexKey, regex] of Object.entries(config.regexes)) {
|
|
@@ -82,7 +148,7 @@ function getStatus(files, action = "print") {
|
|
|
82
148
|
}
|
|
83
149
|
let match = regex.exec(fileSrc);
|
|
84
150
|
while (match) {
|
|
85
|
-
const { row, column } =
|
|
151
|
+
const { row, column } = getCharacterPositionInFile(match.index, getLineStartsLazy());
|
|
86
152
|
StatusStore.add({
|
|
87
153
|
isLegacy: false,
|
|
88
154
|
type: regexKey,
|
|
@@ -109,17 +175,68 @@ function getStatus(files, action = "print") {
|
|
|
109
175
|
console.info("\n");
|
|
110
176
|
return StatusStore;
|
|
111
177
|
}
|
|
112
|
-
function
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
178
|
+
function getLegacySearchTerms() {
|
|
179
|
+
const legacySearchTerms = new Map();
|
|
180
|
+
for (const [legacyToken, config] of Object.entries(legacy_tokens_1.legacyTokenConfig)) {
|
|
181
|
+
const terms = new Set();
|
|
182
|
+
const tokenName = `--a-${legacyToken}`;
|
|
183
|
+
terms.add(tokenName);
|
|
184
|
+
terms.add((0, translate_token_1.translateToken)(tokenName, "scss"));
|
|
185
|
+
terms.add((0, translate_token_1.translateToken)(tokenName, "less"));
|
|
186
|
+
terms.add((0, translate_token_1.translateToken)(tokenName, "js"));
|
|
187
|
+
if (config.twOld) {
|
|
188
|
+
config.twOld.split(",").forEach((t) => terms.add(t.trim()));
|
|
189
|
+
}
|
|
190
|
+
legacySearchTerms.set(legacyToken, terms);
|
|
191
|
+
}
|
|
192
|
+
return legacySearchTerms;
|
|
193
|
+
}
|
|
194
|
+
function getDarksideSearchTerms() {
|
|
195
|
+
const darksideSearchTerms = new Map();
|
|
196
|
+
for (const [newTokenName, config] of Object.entries(darkside_tokens_1.darksideTokenConfig)) {
|
|
197
|
+
const terms = new Set();
|
|
198
|
+
const tokenName = `--ax-${newTokenName}`;
|
|
199
|
+
terms.add(tokenName);
|
|
200
|
+
terms.add((0, translate_token_1.translateToken)(tokenName, "scss"));
|
|
201
|
+
terms.add((0, translate_token_1.translateToken)(tokenName, "less"));
|
|
202
|
+
terms.add((0, translate_token_1.translateToken)(newTokenName, "js"));
|
|
203
|
+
terms.add(newTokenName);
|
|
204
|
+
if (config.tw) {
|
|
205
|
+
config.tw.split(",").forEach((t) => terms.add(t.trim()));
|
|
206
|
+
}
|
|
207
|
+
darksideSearchTerms.set(newTokenName, terms);
|
|
208
|
+
}
|
|
209
|
+
return darksideSearchTerms;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Given the content of a file, returns an array of line start positions.
|
|
213
|
+
*/
|
|
214
|
+
function getLineStarts(content) {
|
|
215
|
+
const starts = [0];
|
|
216
|
+
let lineIndex = content.indexOf("\n", 0);
|
|
217
|
+
while (lineIndex !== -1) {
|
|
218
|
+
starts.push(lineIndex + 1);
|
|
219
|
+
lineIndex = content.indexOf("\n", lineIndex + 1);
|
|
220
|
+
}
|
|
221
|
+
return starts;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Given a character index and an array of line start positions,
|
|
225
|
+
* returns the corresponding row and column numbers.
|
|
226
|
+
*/
|
|
227
|
+
function getCharacterPositionInFile(index, lineStarts) {
|
|
228
|
+
let low = 0;
|
|
229
|
+
let high = lineStarts.length - 1;
|
|
230
|
+
let lineIndex = 0;
|
|
231
|
+
while (low <= high) {
|
|
232
|
+
const mid = (low + high) >>> 1;
|
|
233
|
+
if (lineStarts[mid] <= index) {
|
|
234
|
+
lineIndex = mid;
|
|
235
|
+
low = mid + 1;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
high = mid - 1;
|
|
120
239
|
}
|
|
121
|
-
charCount += lineLength;
|
|
122
|
-
lineNumber++;
|
|
123
240
|
}
|
|
124
|
-
return { row:
|
|
241
|
+
return { row: lineIndex + 1, column: index - lineStarts[lineIndex] + 1 };
|
|
125
242
|
}
|
|
@@ -4,14 +4,29 @@ exports.default = transformer;
|
|
|
4
4
|
const legacy_tokens_1 = require("../config/legacy.tokens");
|
|
5
5
|
function transformer(file) {
|
|
6
6
|
let src = file.source;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
/*
|
|
8
|
+
1. Replace definitions: --a-token: -> --aksel-legacy__a-token:
|
|
9
|
+
Matches "--a-token" followed by optional whitespace and a colon.
|
|
10
|
+
Uses negative lookbehind to ensure we don't match "--not-a-token".
|
|
11
|
+
*/
|
|
12
|
+
src = src.replace(/(?<![\w-])(--a-[\w-]+)(\s*:)/g, (match, tokenName, suffix) => {
|
|
13
|
+
const key = tokenName.replace("--a-", "");
|
|
14
|
+
if (legacy_tokens_1.legacyTokenConfig[key]) {
|
|
15
|
+
return `--aksel-legacy${tokenName.replace("--", "__")}${suffix}`;
|
|
14
16
|
}
|
|
15
|
-
|
|
17
|
+
return match;
|
|
18
|
+
});
|
|
19
|
+
/*
|
|
20
|
+
2. Replace usages: --a-token -> --ax-replacement
|
|
21
|
+
Matches "--a-token" with word boundaries.
|
|
22
|
+
*/
|
|
23
|
+
src = src.replace(/(?<![\w-])(--a-[\w-]+)(?![\w-])/g, (match, tokenName) => {
|
|
24
|
+
const key = tokenName.replace("--a-", "");
|
|
25
|
+
const config = legacy_tokens_1.legacyTokenConfig[key];
|
|
26
|
+
if (config === null || config === void 0 ? void 0 : config.replacement) {
|
|
27
|
+
return `--ax-${config.replacement}`;
|
|
28
|
+
}
|
|
29
|
+
return match;
|
|
30
|
+
});
|
|
16
31
|
return src;
|
|
17
32
|
}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = transformer;
|
|
4
4
|
const legacy_tokens_1 = require("../config/legacy.tokens");
|
|
5
|
-
const token_regex_1 = require("../config/token-regex");
|
|
6
5
|
function transformer(file) {
|
|
7
6
|
let src = file.source;
|
|
8
7
|
for (const [name, config] of Object.entries(legacy_tokens_1.legacyTokenConfig)) {
|
|
9
|
-
if (!config.twOld || !config.twNew) {
|
|
8
|
+
if (!config.twOld || !config.twNew || !config.regexes.tailwind) {
|
|
10
9
|
continue;
|
|
11
10
|
}
|
|
12
11
|
const isBreakpoint = name.includes("breakpoint");
|
|
@@ -16,18 +15,18 @@ function transformer(file) {
|
|
|
16
15
|
}
|
|
17
16
|
const beforeSplit = config.twOld.split(",");
|
|
18
17
|
const afterSplit = config.twNew.split(",");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
18
|
+
src = src.replace(config.regexes.tailwind, (match) => {
|
|
19
|
+
const trimmed = match.trim();
|
|
20
|
+
const cleanToken = trimmed.replace(":", "");
|
|
21
|
+
const index = beforeSplit.indexOf(cleanToken);
|
|
22
22
|
if (index >= 0) {
|
|
23
|
-
const withPrefix =
|
|
23
|
+
const withPrefix = trimmed.startsWith(":");
|
|
24
24
|
const addSpace = match.startsWith(" ");
|
|
25
25
|
const replacementToken = afterSplit[index];
|
|
26
|
-
|
|
27
|
-
? `:${replacementToken}`
|
|
28
|
-
: `${addSpace ? " " : ""}${replacementToken}`);
|
|
26
|
+
return `${addSpace ? " " : ""}${withPrefix ? ":" : ""}${replacementToken}`;
|
|
29
27
|
}
|
|
30
|
-
|
|
28
|
+
return match;
|
|
29
|
+
});
|
|
31
30
|
}
|
|
32
31
|
return src;
|
|
33
32
|
}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const commander_1 = require("commander");
|
|
17
18
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
18
19
|
const index_1 = require("./codemod/index");
|
|
19
20
|
const darkside_1 = require("./darkside");
|
|
@@ -21,26 +22,24 @@ const help_1 = require("./help");
|
|
|
21
22
|
run();
|
|
22
23
|
function run() {
|
|
23
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
|
|
25
|
+
const pkg = JSON.parse(node_fs_1.default.readFileSync("./package.json").toString()).version;
|
|
26
|
+
const program = new commander_1.Command();
|
|
27
|
+
program.version(pkg, "-v, --version");
|
|
28
|
+
program.allowUnknownOption().helpOption(false);
|
|
29
|
+
program.parse();
|
|
30
|
+
const args = program.args;
|
|
31
|
+
if (args.length === 0 || args[0] === "help") {
|
|
25
32
|
(0, help_1.helpCommand)();
|
|
26
33
|
return;
|
|
27
34
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
if (process.argv[2] === "codemod") {
|
|
35
|
+
if (args[0] === "codemod") {
|
|
36
|
+
if (args.includes("v8-tokens")) {
|
|
37
|
+
(0, darkside_1.darksideCommand)();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
36
40
|
(0, index_1.codemodCommand)();
|
|
37
41
|
return;
|
|
38
42
|
}
|
|
39
|
-
|
|
40
|
-
const pkg = JSON.parse(node_fs_1.default.readFileSync("./package.json").toString()).version;
|
|
41
|
-
console.info(pkg);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
console.info(chalk_1.default.red(`Unknown command: ${process.argv[2]}.\nRun ${chalk_1.default.cyan("npx @navikt/aksel help")} for all available commands.`));
|
|
43
|
+
console.info(chalk_1.default.red(`Unknown command: ${args[0]}.\nRun ${chalk_1.default.cyan("npx @navikt/aksel help")} for all available commands.`));
|
|
45
44
|
});
|
|
46
45
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navikt/aksel",
|
|
3
|
-
"version": "7.35.
|
|
3
|
+
"version": "7.35.2",
|
|
4
4
|
"description": "Aksel command line interface. Codemods and other utilities for Aksel users.",
|
|
5
5
|
"author": "Aksel | Nav designsystem team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,20 +32,20 @@
|
|
|
32
32
|
"url": "https://github.com/navikt/aksel/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@navikt/ds-css": "^7.35.
|
|
36
|
-
"@navikt/ds-tokens": "^7.35.
|
|
35
|
+
"@navikt/ds-css": "^7.35.2",
|
|
36
|
+
"@navikt/ds-tokens": "^7.35.2",
|
|
37
37
|
"axios": "1.13.2",
|
|
38
|
-
"chalk": "
|
|
39
|
-
"cli-progress": "
|
|
38
|
+
"chalk": "5.6.2",
|
|
39
|
+
"cli-progress": "3.12.0",
|
|
40
|
+
"clipboardy": "5.0.1",
|
|
40
41
|
"commander": "10.0.1",
|
|
41
|
-
"enquirer": "
|
|
42
|
+
"enquirer": "2.4.1",
|
|
42
43
|
"fast-glob": "3.2.11",
|
|
43
44
|
"figlet": "1.8.0",
|
|
44
45
|
"is-git-clean": "1.1.0",
|
|
45
|
-
"jscodeshift": "
|
|
46
|
+
"jscodeshift": "0.15.2",
|
|
46
47
|
"jscodeshift-add-imports": "1.0.11",
|
|
47
|
-
"lodash": "
|
|
48
|
-
"react-scanner": "^1.1.0"
|
|
48
|
+
"lodash": "4.17.21"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/cli-progress": "3.11.6",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"engines": {
|
|
58
|
-
"node": ">=
|
|
58
|
+
"node": ">=20.0.0"
|
|
59
59
|
},
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public",
|