@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.
- package/README.md +96 -2
- package/dist/codemod/codeshift.utils.js +9 -1
- package/dist/codemod/migrations.js +75 -22
- package/dist/codemod/run-codeshift.js +14 -3
- package/dist/codemod/transforms/v8.0.0/accordion-variant/accordion-variant.js +16 -0
- package/dist/codemod/transforms/{darkside/box-to-boxnew/box-to-boxnew.js → v8.0.0/box/box.js} +80 -100
- package/dist/codemod/transforms/v8.0.0/box-new/box-new.js +91 -0
- package/dist/codemod/transforms/v8.0.0/chips-variant/chips-variant.js +31 -0
- package/dist/codemod/transforms/v8.0.0/list/list.js +218 -0
- package/dist/codemod/transforms/{darkside → v8.0.0}/prop-deprecate/prop-deprecate.js +1 -1
- package/dist/codemod/transforms/v8.0.0/tag-variant/tag-variant.js +38 -0
- package/dist/codemod/transforms/v8.0.0/toggle-group-variant/toggle-group-variant.js +16 -0
- package/dist/codemod/utils/ast.js +1 -1
- package/dist/codemod/utils/check.js +35 -0
- package/dist/codemod/utils/move-variant-to-data-color.js +120 -0
- package/dist/darkside/index.js +3 -9
- package/dist/darkside/run-tooling.js +138 -42
- package/dist/darkside/tasks/print-remaining.js +143 -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/help.js +0 -10
- package/dist/index.js +14 -17
- package/package.json +7 -7
- package/dist/css-imports/config.js +0 -5
- package/dist/css-imports/generate-output.js +0 -147
- package/dist/css-imports/get-directories.js +0 -34
- package/dist/css-imports/get-version.js +0 -28
- package/dist/css-imports/index.js +0 -187
- package/dist/css-imports/inquiry.js +0 -35
- package/dist/css-imports/scan-code.js +0 -45
- /package/dist/codemod/transforms/{spacing → v8.0.0}/primitives-spacing/spacing.js +0 -0
- /package/dist/codemod/transforms/{spacing → v8.0.0}/spacing.utils.js +0 -0
- /package/dist/codemod/transforms/{spacing → v8.0.0}/token-spacing/spacing.js +0 -0
- /package/dist/codemod/transforms/{spacing → v8.0.0}/token-spacing-js/spacing.js +0 -0
|
@@ -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,156 @@
|
|
|
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 clipboardy_1 = __importDefault(require("clipboardy"));
|
|
17
|
+
const enquirer_1 = __importDefault(require("enquirer"));
|
|
7
18
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
19
|
const status_1 = require("./status");
|
|
9
|
-
function printRemaining(files) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
console.info("
|
|
20
|
-
|
|
20
|
+
function printRemaining(files, status) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
process.stdout.write("\nAnalyzing...");
|
|
23
|
+
/**
|
|
24
|
+
* Skip re-calculating status if already provided
|
|
25
|
+
*/
|
|
26
|
+
const statusObj = status !== null && status !== void 0 ? status : (0, status_1.getStatus)(files, "no-print").status;
|
|
27
|
+
/* Flatten all legacy tokens */
|
|
28
|
+
const allTokens = Object.values(statusObj).flatMap((data) => data.legacy);
|
|
29
|
+
if (allTokens.length === 0) {
|
|
30
|
+
console.info("\nNo legacy tokens found!");
|
|
31
|
+
return;
|
|
21
32
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
const response = yield enquirer_1.default.prompt([
|
|
34
|
+
{
|
|
35
|
+
type: "select",
|
|
36
|
+
name: "groupBy",
|
|
37
|
+
message: "How would you like to group the remaining tokens?",
|
|
38
|
+
choices: [
|
|
39
|
+
{ message: "By File", name: "file" },
|
|
40
|
+
{ message: "By Token", name: "token" },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: "confirm",
|
|
45
|
+
name: "copy",
|
|
46
|
+
message: "Copy report to clipboard?",
|
|
47
|
+
initial: true,
|
|
48
|
+
},
|
|
49
|
+
]);
|
|
50
|
+
const { groupBy, copy } = response;
|
|
51
|
+
console.info("\n");
|
|
52
|
+
const log = (str, indent = 0) => {
|
|
53
|
+
const prefix = " ".repeat(indent);
|
|
54
|
+
console.info(prefix + str);
|
|
55
|
+
};
|
|
56
|
+
let jsonOutput;
|
|
57
|
+
/**
|
|
58
|
+
* Group by filename
|
|
59
|
+
*/
|
|
60
|
+
if (groupBy === "file") {
|
|
61
|
+
const byFile = new Map();
|
|
62
|
+
allTokens.forEach((token) => {
|
|
63
|
+
if (!byFile.has(token.fileName)) {
|
|
64
|
+
byFile.set(token.fileName, []);
|
|
65
|
+
}
|
|
66
|
+
byFile.get(token.fileName).push(token);
|
|
67
|
+
});
|
|
68
|
+
/* Sort files by number of tokens (descending) */
|
|
69
|
+
const sortedFiles = Array.from(byFile.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
70
|
+
const fileOutput = [];
|
|
71
|
+
sortedFiles.forEach(([fileName, tokens]) => {
|
|
72
|
+
const fullPath = node_path_1.default.resolve(process.cwd(), fileName);
|
|
73
|
+
log(`${fileName} (${tokens.length} tokens)`);
|
|
74
|
+
/* Sort tokens in file by line number */
|
|
75
|
+
tokens.sort((a, b) => a.lineNumber - b.lineNumber);
|
|
76
|
+
const fileEntry = {
|
|
77
|
+
file: fileName,
|
|
78
|
+
fullPath,
|
|
79
|
+
count: tokens.length,
|
|
80
|
+
tokens: [],
|
|
81
|
+
};
|
|
82
|
+
tokens.forEach((token) => {
|
|
83
|
+
if (token.comment) {
|
|
84
|
+
log(`/* ${token.comment} */`, 1);
|
|
85
|
+
}
|
|
86
|
+
log(`${token.name}: ${fullPath}:${token.lineNumber}:${token.columnNumber}`, 1);
|
|
87
|
+
fileEntry.tokens.push({
|
|
88
|
+
name: token.name,
|
|
89
|
+
line: token.lineNumber,
|
|
90
|
+
column: token.columnNumber,
|
|
91
|
+
comment: token.comment,
|
|
92
|
+
link: `file://${fullPath}`,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
/* Empty line */
|
|
96
|
+
log("");
|
|
97
|
+
fileOutput.push(fileEntry);
|
|
42
98
|
});
|
|
43
|
-
|
|
44
|
-
|
|
99
|
+
jsonOutput = fileOutput;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
/* Group by token name */
|
|
103
|
+
const byToken = new Map();
|
|
104
|
+
allTokens.forEach((token) => {
|
|
105
|
+
if (!byToken.has(token.name)) {
|
|
106
|
+
byToken.set(token.name, []);
|
|
107
|
+
}
|
|
108
|
+
byToken.get(token.name).push(token);
|
|
109
|
+
});
|
|
110
|
+
/* Sort tokens by frequency (descending) */
|
|
111
|
+
const sortedTokens = Array.from(byToken.entries()).sort((a, b) => b[1].length - a[1].length);
|
|
112
|
+
const tokenOutput = [];
|
|
113
|
+
sortedTokens.forEach(([tokenName, tokens]) => {
|
|
114
|
+
var _a;
|
|
115
|
+
log(`${tokenName} (${tokens.length} occurrences)`);
|
|
116
|
+
/**
|
|
117
|
+
* We can assume all comments are the same for a "tokenName"
|
|
118
|
+
*/
|
|
119
|
+
const foundComment = (_a = tokens.find((t) => t.comment)) === null || _a === void 0 ? void 0 : _a.comment;
|
|
120
|
+
if (foundComment) {
|
|
121
|
+
log(`/* ${foundComment} */`, 1);
|
|
122
|
+
}
|
|
123
|
+
const tokenEntry = {
|
|
124
|
+
token: tokenName,
|
|
125
|
+
count: tokens.length,
|
|
126
|
+
occurrences: [],
|
|
127
|
+
};
|
|
128
|
+
tokens.forEach((token) => {
|
|
129
|
+
const fullPath = node_path_1.default.resolve(process.cwd(), token.fileName);
|
|
130
|
+
log(`${fullPath}:${token.lineNumber}:${token.columnNumber}`, 1);
|
|
131
|
+
tokenEntry.occurrences.push({
|
|
132
|
+
file: token.fileName,
|
|
133
|
+
fullPath,
|
|
134
|
+
line: token.lineNumber,
|
|
135
|
+
column: token.columnNumber,
|
|
136
|
+
comment: token.comment,
|
|
137
|
+
link: `file://${fullPath}`,
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
/* Empty line */
|
|
141
|
+
log("");
|
|
142
|
+
tokenOutput.push(tokenEntry);
|
|
143
|
+
});
|
|
144
|
+
jsonOutput = tokenOutput;
|
|
145
|
+
}
|
|
146
|
+
if (copy) {
|
|
147
|
+
try {
|
|
148
|
+
clipboardy_1.default.writeSync(JSON.stringify(jsonOutput, null, 2));
|
|
149
|
+
console.info("✅ Report (JSON) copied to clipboard!");
|
|
45
150
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.error("❌ Failed to copy to clipboard:", error.message);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
49
155
|
});
|
|
50
|
-
console.info("\n");
|
|
51
156
|
}
|