@atlaskit/codemod-cli 0.27.3 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/main.js +18 -13
  3. package/dist/cjs/presets/remove-token-fallbacks/remove-token-fallbacks.js +294 -43
  4. package/dist/cjs/presets/remove-token-fallbacks/utils/chunk.js +14 -0
  5. package/dist/cjs/presets/remove-token-fallbacks/utils/normalize-values.js +4 -3
  6. package/dist/cjs/presets/remove-token-fallbacks/utils/remove-unused-imports.js +2 -2
  7. package/dist/cjs/presets/remove-token-fallbacks/utils/reporter.js +28 -21
  8. package/dist/cjs/presets/remove-token-fallbacks/utils/token-processor.js +154 -46
  9. package/dist/es2019/main.js +7 -1
  10. package/dist/es2019/presets/remove-token-fallbacks/remove-token-fallbacks.js +122 -17
  11. package/dist/es2019/presets/remove-token-fallbacks/utils/chunk.js +8 -0
  12. package/dist/es2019/presets/remove-token-fallbacks/utils/normalize-values.js +4 -3
  13. package/dist/es2019/presets/remove-token-fallbacks/utils/remove-unused-imports.js +3 -3
  14. package/dist/es2019/presets/remove-token-fallbacks/utils/reporter.js +6 -1
  15. package/dist/es2019/presets/remove-token-fallbacks/utils/token-processor.js +85 -9
  16. package/dist/esm/main.js +18 -13
  17. package/dist/esm/presets/remove-token-fallbacks/remove-token-fallbacks.js +294 -41
  18. package/dist/esm/presets/remove-token-fallbacks/utils/chunk.js +8 -0
  19. package/dist/esm/presets/remove-token-fallbacks/utils/normalize-values.js +4 -3
  20. package/dist/esm/presets/remove-token-fallbacks/utils/remove-unused-imports.js +2 -2
  21. package/dist/esm/presets/remove-token-fallbacks/utils/reporter.js +28 -21
  22. package/dist/esm/presets/remove-token-fallbacks/utils/token-processor.js +154 -46
  23. package/dist/types/presets/remove-token-fallbacks/remove-token-fallbacks.d.ts +1 -1
  24. package/dist/types/presets/remove-token-fallbacks/utils/chunk.d.ts +1 -0
  25. package/dist/types-ts4.5/presets/remove-token-fallbacks/remove-token-fallbacks.d.ts +1 -1
  26. package/dist/types-ts4.5/presets/remove-token-fallbacks/utils/chunk.d.ts +1 -0
  27. package/package.json +4 -4
@@ -94,7 +94,7 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
94
94
  value: function () {
95
95
  var _processSingleToken = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(callPath) {
96
96
  var _callPath$node$loc2;
97
- var args, line, tokenKey, isSkipped, tokenValue, _ref, rawFallbackValue, fallbackValue, resolvedImportDeclaration, resolvedLocalVarDeclaration, _normalizeValues, difference, isAcceptableDifference, tokenLogValue, fallbackLogValue, normalizedTokenValue, normalizedFallbackValue, areEqual, logData, fallbackRemoved, importDeclaration, localVarDeclaration, message;
97
+ var args, line, tokenKey, isSkipped, tokenValue, _ref, rawFallbackValue, fallbackValue, resolvedImportDeclaration, resolvedLocalVarDeclaration, _normalizeValues, difference, isAcceptableDifference, tokenLogValue, fallbackLogValue, normalizedTokenValue, normalizedFallbackValue, areEqual, logData, fallbackRemoved, importDeclaration, localVarDeclaration, isBorderToken, message;
98
98
  return _regenerator.default.wrap(function _callee2$(_context2) {
99
99
  while (1) switch (_context2.prev = _context2.next) {
100
100
  case 0:
@@ -124,7 +124,9 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
124
124
  resolvedLocalVarDeclaration: undefined
125
125
  });
126
126
  case 8:
127
- isSkipped = tokenKey.startsWith('elevation.shadow') || tokenKey.startsWith('font.body') || tokenKey.startsWith('font.heading');
127
+ isSkipped = false; // tokenKey.startsWith('elevation.shadow') ||
128
+ // tokenKey.startsWith('font.body') ||
129
+ // tokenKey.startsWith('font.heading');
128
130
  tokenValue = isSkipped ? '' : this.tokenMap[tokenKey];
129
131
  this.logVerbose("Token value from tokenMap: ".concat(_chalk.default.magenta(tokenValue), " for key: ").concat(_chalk.default.yellow(tokenKey)));
130
132
  if (!isSkipped) {
@@ -163,7 +165,8 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
163
165
  difference: difference
164
166
  };
165
167
  fallbackRemoved = false;
166
- if (areEqual || isAcceptableDifference || this.options.forceUpdate) {
168
+ isBorderToken = tokenKey.startsWith('border');
169
+ if (areEqual || (isAcceptableDifference || this.options.forceUpdate) && !isBorderToken) {
167
170
  this.log(_chalk.default.green(areEqual ? 'Token value and fallback value are equal, removing fallback' : 'Token value and fallback value are within acceptable difference threshold, removing fallback'));
168
171
  args.pop();
169
172
  this.details.replaced.push(logData);
@@ -171,7 +174,7 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
171
174
  importDeclaration = resolvedImportDeclaration;
172
175
  localVarDeclaration = resolvedLocalVarDeclaration;
173
176
  } else {
174
- message = normalizedFallbackValue === undefined ? "Fallback value could not be resolved" : "Values mismatched significantly";
177
+ message = isBorderToken ? 'Skip modifying border token' : normalizedFallbackValue === undefined ? "Fallback value could not be resolved" : "Values mismatched significantly";
175
178
  this.logError(message);
176
179
  if (this.options.addEslintComments) {
177
180
  (0, _updateComments.addOrUpdateEslintIgnoreComment)(this.j, tokenValue, fallbackValue, callPath);
@@ -185,7 +188,7 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
185
188
  resolvedImportDeclaration: importDeclaration,
186
189
  resolvedLocalVarDeclaration: localVarDeclaration
187
190
  });
188
- case 30:
191
+ case 31:
189
192
  case "end":
190
193
  return _context2.stop();
191
194
  }
@@ -328,10 +331,57 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
328
331
  key: "processFallbackAsMemberExpression",
329
332
  value: function () {
330
333
  var _processFallbackAsMemberExpression = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(fallbackValueNode) {
331
- var objectName, propertyName, fallbackValue, rawFallbackValue, resolvedImportDeclaration, importDeclaration, importSource;
334
+ var objectName, propertyName, fallbackValue, resolvedImportDeclaration, resolvedLocalVarDeclaration, _getFullMemberPath, fullMemberPath, pathSegments, localVarDeclaration, _importDeclaration, rawFallbackValue, importDeclaration, importSource;
332
335
  return _regenerator.default.wrap(function _callee5$(_context5) {
333
336
  while (1) switch (_context5.prev = _context5.next) {
334
337
  case 0:
338
+ // Function to get full member expression path as string
339
+ _getFullMemberPath = function getFullMemberPath(node) {
340
+ if (node.type === 'Identifier') {
341
+ return node.name;
342
+ } else if (node.type === 'MemberExpression') {
343
+ return "".concat(_getFullMemberPath(node.object), ".").concat(node.property.type === 'Identifier' ? node.property.name : '');
344
+ }
345
+ return '';
346
+ };
347
+ fullMemberPath = _getFullMemberPath(fallbackValueNode); // Detect long member expression paths
348
+ pathSegments = fullMemberPath.split('.');
349
+ if (!(pathSegments.length > 2)) {
350
+ _context5.next = 9;
351
+ break;
352
+ }
353
+ this.logVerbose("Detected long member expression: ".concat(_chalk.default.yellow(fullMemberPath), ". Just resolving import or local variable declaration."));
354
+
355
+ // Find the import statement or local variable for the top-level object
356
+ objectName = pathSegments[0];
357
+
358
+ // Check if it's a local variable
359
+ localVarDeclaration = this.source.find(this.j.VariableDeclarator, {
360
+ id: {
361
+ name: objectName
362
+ }
363
+ }).at(0);
364
+ if (localVarDeclaration.size()) {
365
+ resolvedLocalVarDeclaration = localVarDeclaration.paths()[0];
366
+ this.logVerbose("Resolved local variable declaration for: ".concat(_chalk.default.yellow(objectName)));
367
+ } else {
368
+ // Search for import declaration
369
+ _importDeclaration = this.source.find(this.j.ImportDeclaration).filter(this.createImportFilter(objectName)).at(0);
370
+ if (_importDeclaration.size()) {
371
+ resolvedImportDeclaration = _importDeclaration.paths()[0];
372
+ this.logVerbose("Resolved import declaration for: ".concat(_chalk.default.yellow(objectName)));
373
+ } else {
374
+ this.logError("Could not resolve import or local variable for: ".concat(_chalk.default.yellow(objectName)));
375
+ }
376
+ }
377
+ return _context5.abrupt("return", {
378
+ rawFallbackValue: fullMemberPath,
379
+ fallbackValue: undefined,
380
+ resolvedImportDeclaration: resolvedImportDeclaration,
381
+ resolvedLocalVarDeclaration: resolvedLocalVarDeclaration
382
+ });
383
+ case 9:
384
+ // Existing logic for member expressions with shorter paths
335
385
  if (fallbackValueNode.object.type === 'Identifier') {
336
386
  objectName = fallbackValueNode.object.name;
337
387
  }
@@ -341,7 +391,7 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
341
391
  propertyName = fallbackValueNode.property.value;
342
392
  }
343
393
  if (!(!objectName || !propertyName)) {
344
- _context5.next = 5;
394
+ _context5.next = 14;
345
395
  break;
346
396
  }
347
397
  this.logError("Could not determine object and property names from member expression: ".concat(_chalk.default.yellow(fallbackValueNode)));
@@ -351,36 +401,37 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
351
401
  resolvedImportDeclaration: undefined,
352
402
  resolvedLocalVarDeclaration: undefined
353
403
  });
354
- case 5:
404
+ case 14:
355
405
  rawFallbackValue = "".concat(objectName, ".").concat(propertyName);
356
406
  this.logVerbose("Fallback is a member expression: ".concat(_chalk.default.yellow(rawFallbackValue), ", attempting to resolve..."));
407
+
357
408
  // Find the import statement for the object
358
409
  importDeclaration = this.source.find(this.j.ImportDeclaration).filter(this.createImportFilter(objectName)).at(0);
359
410
  if (!importDeclaration.size()) {
360
- _context5.next = 16;
411
+ _context5.next = 25;
361
412
  break;
362
413
  }
363
414
  importSource = importDeclaration.get().value.source.value;
364
- _context5.next = 12;
415
+ _context5.next = 21;
365
416
  return this.resolveValueFromImport(this.rootDir, importSource, objectName, propertyName);
366
- case 12:
417
+ case 21:
367
418
  fallbackValue = _context5.sent;
368
419
  if (fallbackValue !== undefined) {
369
420
  resolvedImportDeclaration = importDeclaration.paths()[0];
370
421
  this.logVerbose("Resolved fallback value from member expression: ".concat(_chalk.default.yellow(fallbackValue)));
371
422
  }
372
- _context5.next = 17;
423
+ _context5.next = 26;
373
424
  break;
374
- case 16:
425
+ case 25:
375
426
  this.logError("Could not find import for member expression: ".concat(_chalk.default.yellow(rawFallbackValue)));
376
- case 17:
427
+ case 26:
377
428
  return _context5.abrupt("return", {
378
429
  rawFallbackValue: rawFallbackValue,
379
430
  fallbackValue: fallbackValue,
380
431
  resolvedImportDeclaration: resolvedImportDeclaration,
381
432
  resolvedLocalVarDeclaration: undefined
382
433
  });
383
- case 18:
434
+ case 27:
384
435
  case "end":
385
436
  return _context5.stop();
386
437
  }
@@ -395,51 +446,108 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
395
446
  key: "processFallbackAsTemplateLiteral",
396
447
  value: function () {
397
448
  var _processFallbackAsTemplateLiteral = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(fallbackValueNode) {
398
- var expressions, rawFallbackValue, fallbackValue, quasis, exprValue, expression, resolvedImportDeclaration, resolvedLocalVarDeclaration, result, _result;
449
+ var expressions, quasis, resolvedImportDeclaration, resolvedLocalVarDeclaration, rawFallbackValue, fallbackValue, _iterator, _step, _expression, result, _result, exprValue, expression, _result2, _result3;
399
450
  return _regenerator.default.wrap(function _callee6$(_context6) {
400
451
  while (1) switch (_context6.prev = _context6.next) {
401
452
  case 0:
402
453
  expressions = fallbackValueNode.expressions;
403
- rawFallbackValue = '';
404
454
  quasis = fallbackValueNode.quasis;
455
+ rawFallbackValue = '';
405
456
  if (!(expressions.length !== 1 || quasis.length !== 2)) {
406
- _context6.next = 6;
457
+ _context6.next = 35;
407
458
  break;
408
459
  }
409
460
  this.logError("Unsupported template literal structure");
461
+
462
+ // Attempt to resolve any imports or local variables used in expressions
463
+ _iterator = _createForOfIteratorHelper(expressions);
464
+ _context6.prev = 6;
465
+ _iterator.s();
466
+ case 8:
467
+ if ((_step = _iterator.n()).done) {
468
+ _context6.next = 26;
469
+ break;
470
+ }
471
+ _expression = _step.value;
472
+ if (!(_expression.type === 'Identifier')) {
473
+ _context6.next = 18;
474
+ break;
475
+ }
476
+ _context6.next = 13;
477
+ return this.processFallbackAsIdentifier(_expression);
478
+ case 13:
479
+ result = _context6.sent;
480
+ if (result.resolvedImportDeclaration) {
481
+ resolvedImportDeclaration = result.resolvedImportDeclaration;
482
+ }
483
+ if (result.resolvedLocalVarDeclaration) {
484
+ resolvedLocalVarDeclaration = result.resolvedLocalVarDeclaration;
485
+ }
486
+ _context6.next = 24;
487
+ break;
488
+ case 18:
489
+ if (!(_expression.type === 'MemberExpression')) {
490
+ _context6.next = 24;
491
+ break;
492
+ }
493
+ _context6.next = 21;
494
+ return this.processFallbackAsMemberExpression(_expression);
495
+ case 21:
496
+ _result = _context6.sent;
497
+ if (_result.resolvedImportDeclaration) {
498
+ resolvedImportDeclaration = _result.resolvedImportDeclaration;
499
+ }
500
+ if (_result.resolvedLocalVarDeclaration) {
501
+ resolvedLocalVarDeclaration = _result.resolvedLocalVarDeclaration;
502
+ }
503
+ case 24:
504
+ _context6.next = 8;
505
+ break;
506
+ case 26:
507
+ _context6.next = 31;
508
+ break;
509
+ case 28:
510
+ _context6.prev = 28;
511
+ _context6.t0 = _context6["catch"](6);
512
+ _iterator.e(_context6.t0);
513
+ case 31:
514
+ _context6.prev = 31;
515
+ _iterator.f();
516
+ return _context6.finish(31);
517
+ case 34:
410
518
  return _context6.abrupt("return", {
411
519
  rawFallbackValue: rawFallbackValue,
412
520
  fallbackValue: fallbackValue,
413
- resolvedImportDeclaration: undefined,
414
- resolvedLocalVarDeclaration: undefined
521
+ resolvedImportDeclaration: resolvedImportDeclaration,
522
+ resolvedLocalVarDeclaration: resolvedLocalVarDeclaration
415
523
  });
416
- case 6:
524
+ case 35:
417
525
  expression = expressions[0];
418
526
  if (!(expression.type === 'Identifier')) {
419
- _context6.next = 16;
527
+ _context6.next = 45;
420
528
  break;
421
529
  }
422
- _context6.next = 10;
530
+ _context6.next = 39;
423
531
  return this.processFallbackAsIdentifier(expression);
424
- case 10:
425
- result = _context6.sent;
426
- exprValue = result.fallbackValue;
427
- resolvedImportDeclaration = result.resolvedImportDeclaration;
428
- resolvedLocalVarDeclaration = result.resolvedLocalVarDeclaration;
429
- _context6.next = 22;
532
+ case 39:
533
+ _result2 = _context6.sent;
534
+ exprValue = _result2.fallbackValue;
535
+ resolvedImportDeclaration = _result2.resolvedImportDeclaration;
536
+ resolvedLocalVarDeclaration = _result2.resolvedLocalVarDeclaration;
537
+ _context6.next = 51;
430
538
  break;
431
- case 16:
539
+ case 45:
432
540
  if (!(expression.type === 'MemberExpression')) {
433
- _context6.next = 22;
541
+ _context6.next = 51;
434
542
  break;
435
543
  }
436
- _context6.next = 19;
544
+ _context6.next = 48;
437
545
  return this.processFallbackAsMemberExpression(expression);
438
- case 19:
439
- _result = _context6.sent;
440
- exprValue = _result.fallbackValue;
441
- resolvedImportDeclaration = _result.resolvedImportDeclaration;
442
- case 22:
546
+ case 48:
547
+ _result3 = _context6.sent;
548
+ exprValue = _result3.fallbackValue;
549
+ resolvedImportDeclaration = _result3.resolvedImportDeclaration;
550
+ case 51:
443
551
  if (exprValue !== undefined) {
444
552
  rawFallbackValue = "".concat(quasis[0].value.raw, "${").concat(exprValue, "}").concat(quasis[1].value.raw);
445
553
  fallbackValue = "".concat(quasis[0].value.cooked).concat(exprValue).concat(quasis[1].value.cooked);
@@ -451,11 +559,11 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
451
559
  resolvedImportDeclaration: resolvedImportDeclaration,
452
560
  resolvedLocalVarDeclaration: resolvedLocalVarDeclaration
453
561
  });
454
- case 24:
562
+ case 53:
455
563
  case "end":
456
564
  return _context6.stop();
457
565
  }
458
- }, _callee6, this);
566
+ }, _callee6, this, [[6, 28, 31, 34]]);
459
567
  }));
460
568
  function processFallbackAsTemplateLiteral(_x6) {
461
569
  return _processFallbackAsTemplateLiteral.apply(this, arguments);
@@ -479,19 +587,19 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
479
587
  key: "tryResolveLocalPath",
480
588
  value: function () {
481
589
  var _tryResolveLocalPath = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7(currentDir, importPath) {
482
- var _iterator, _step, ext, potentialPath;
590
+ var _iterator2, _step2, ext, potentialPath;
483
591
  return _regenerator.default.wrap(function _callee7$(_context7) {
484
592
  while (1) switch (_context7.prev = _context7.next) {
485
593
  case 0:
486
- _iterator = _createForOfIteratorHelper(this.possibleExtensions);
594
+ _iterator2 = _createForOfIteratorHelper(this.possibleExtensions);
487
595
  _context7.prev = 1;
488
- _iterator.s();
596
+ _iterator2.s();
489
597
  case 3:
490
- if ((_step = _iterator.n()).done) {
598
+ if ((_step2 = _iterator2.n()).done) {
491
599
  _context7.next = 17;
492
600
  break;
493
601
  }
494
- ext = _step.value;
602
+ ext = _step2.value;
495
603
  potentialPath = _path.default.resolve(currentDir, "".concat(importPath).concat(ext));
496
604
  _context7.prev = 6;
497
605
  _context7.next = 9;
@@ -511,10 +619,10 @@ var TokenProcessor = exports.TokenProcessor = /*#__PURE__*/function () {
511
619
  case 19:
512
620
  _context7.prev = 19;
513
621
  _context7.t1 = _context7["catch"](1);
514
- _iterator.e(_context7.t1);
622
+ _iterator2.e(_context7.t1);
515
623
  case 22:
516
624
  _context7.prev = 22;
517
- _iterator.f();
625
+ _iterator2.f();
518
626
  return _context7.finish(22);
519
627
  case 25:
520
628
  return _context7.abrupt("return", null);
@@ -88,12 +88,18 @@ const runTransform = async (filePaths, transform, flags) => {
88
88
  }
89
89
  logger.log(chalk.green(`Transforming files matching these extensions '${chalk.bold(flags.extensions)}'...`));
90
90
  const transformPath = getTransformPath(transform);
91
+
92
+ // Split the ignorePattern by '|' and add each as a separate --ignore-pattern
93
+ const ignorePatterns = flags.ignorePattern.split('|').filter(Boolean);
94
+ const ignoreArgs = ignorePatterns.map(pattern => `--ignore-pattern=${pattern}`);
91
95
  const args = Object.keys(flags).reduce((acc, key) => {
92
96
  if (!['transform', 'parser', 'extensions', 'ignorePattern', 'logger', 'packages', 'sinceRef', 'preset', 'failOnError'].includes(key)) {
93
97
  acc.unshift(`--${key}=${flags[key]}`);
94
98
  }
95
99
  return acc;
96
- }, [`--transform=${transformPath}`, `--ignore-pattern=${flags.ignorePattern}`, `--parser=${flags.parser}`, `--extensions=${flags.extensions}`,
100
+ }, [`--transform=${transformPath}`, ...ignoreArgs,
101
+ // Spread the ignoreArgs array here
102
+ `--parser=${flags.parser}`, `--extensions=${flags.extensions}`,
97
103
  // Limit CPUs to 8 to prevent issues when running on CI with a large amount of cpus
98
104
  '--cpus=8', ...codemodDirs]);
99
105
  if (flags.failOnError) {
@@ -7,6 +7,7 @@ import { hasImportDeclaration } from '@hypermod/utils';
7
7
  import { findRoot } from '@manypkg/find-root';
8
8
  import chalk from 'chalk';
9
9
  import { getTokenMap } from './utils/all-tokens';
10
+ import { chunkArray } from './utils/chunk';
10
11
  import { getTeamInfo } from './utils/get-team-info';
11
12
  import { removeUnusedImports } from './utils/remove-unused-imports';
12
13
  import { removeUnusedVariables } from './utils/remove-unused-variables';
@@ -59,6 +60,9 @@ export default async function transformer(fileInfo, {
59
60
  });
60
61
  const results = await Promise.all(transformPromises);
61
62
  const unusedVars = [];
63
+ if (options.reportFolder) {
64
+ await writeReports(details, options.reportFolder);
65
+ }
62
66
  if (results.some(result => result.fallbackRemoved)) {
63
67
  const allImports = results.flatMap(result => {
64
68
  var _result$resolvedImpor;
@@ -75,20 +79,22 @@ export default async function transformer(fileInfo, {
75
79
  }
76
80
  removeUnusedImports(allImports, j);
77
81
  }
78
- }
79
- removeUnusedVariables(unusedVars, j);
80
- if (options.reportFolder) {
81
- await writeReports(details, options.reportFolder);
82
- }
83
- if (options.dry) {
84
- if (options.verbose) {
85
- console.log(chalk.cyan(`${fileInfo.path}: dry run mode active. Source was not modified.`));
82
+ if (unusedVars.length) {
83
+ removeUnusedVariables(unusedVars, j);
84
+ }
85
+ if (options.dry) {
86
+ if (options.verbose) {
87
+ console.log(chalk.cyan(`${fileInfo.path}: dry run mode active. Source was not modified.`));
88
+ }
89
+ // Return the unmodified source if dryRun is true
90
+ return fileInfo.source;
91
+ } else {
92
+ // Return the transformed source
93
+ return source.toSource();
86
94
  }
95
+ } else {
87
96
  // Return the unmodified source if dryRun is true
88
97
  return fileInfo.source;
89
- } else {
90
- // Return the transformed source
91
- return source.toSource();
92
98
  }
93
99
  }
94
100
  export const parser = 'tsx';
@@ -104,7 +110,7 @@ export async function beforeAll(options) {
104
110
 
105
111
  /**
106
112
  * Function executed after all transformations to combine individual file reports into a comprehensive transformation report.
107
- * It also applies prettier to the affected files.
113
+ * It also applies prettier and eslint (to remove dangling suppressions) to the affected files.
108
114
  */
109
115
  export async function afterAll(options) {
110
116
  if (options.reportFolder) {
@@ -115,16 +121,115 @@ export async function afterAll(options) {
115
121
  const filesTxtPath = path.join(options.reportFolder, 'files.txt');
116
122
  const fileContent = await fs.readFile(filesTxtPath, 'utf-8');
117
123
  if (fileContent.length > 0) {
118
- console.log(`Running prettier on files: ${chalk.magenta(fileContent)}`);
119
- await execAsync(`yarn prettier --write ${fileContent}`);
120
- console.log(chalk.green(`Prettier was run successfully`));
124
+ const filePaths = fileContent.split(/\r?\n/).filter(Boolean);
125
+
126
+ // Get the first file path and strip any quotes
127
+ const firstFilePath = filePaths[0].replace(/^['"]|['"]$/g, '');
128
+
129
+ // Determine the root directory using findRoot
130
+ const rootDir = await findRoot(path.dirname(firstFilePath));
131
+ console.log('Root directory:', rootDir);
132
+ await gitStage(filePaths, rootDir);
133
+ await runEslint(filePaths, rootDir);
134
+ await runPrettier(filePaths, rootDir);
121
135
  }
122
136
  } catch (error) {
123
137
  if (error instanceof Error) {
124
- console.error(chalk.red(`Unexpected error running Prettier: ${error.message}`));
138
+ console.error(chalk.red(`Unexpected error: ${error.message}`));
125
139
  } else {
126
- console.error(chalk.red('An unknown error occurred while running Prettier.'));
140
+ console.error(chalk.red('An unknown error occurred.'));
141
+ }
142
+ }
143
+ }
144
+ }
145
+ async function gitStage(filePaths, cwd) {
146
+ const gitAddCommand = `git add ${filePaths.join(' ')}`;
147
+ console.log(`Executing command: ${gitAddCommand}`);
148
+ const {
149
+ stdout: gitAddStdout,
150
+ stderr: gitAddStderr
151
+ } = await execAsync(gitAddCommand, {
152
+ cwd
153
+ });
154
+ if (gitAddStdout) {
155
+ console.log(chalk.blue(`Git add output:\n${gitAddStdout}`));
156
+ }
157
+ if (gitAddStderr) {
158
+ console.error(chalk.yellow(`Git add errors:\n${gitAddStderr}`));
159
+ }
160
+ console.log(chalk.green(`All changes have been staged.`));
161
+ }
162
+ async function runPrettier(filePaths, cwd) {
163
+ const prettierCommand = `yarn prettier --write ${filePaths.join(' ')}`;
164
+ console.log(`Executing command: ${prettierCommand}`);
165
+ const {
166
+ stdout: prettierStdout,
167
+ stderr: prettierStderr
168
+ } = await execAsync(prettierCommand, {
169
+ cwd
170
+ });
171
+ if (prettierStdout) {
172
+ console.log(chalk.blue(`Prettier output:\n${prettierStdout}`));
173
+ }
174
+ if (prettierStderr) {
175
+ console.error(chalk.yellow(`Prettier errors:\n${prettierStderr}`));
176
+ }
177
+ console.log(chalk.green(`Prettier was run successfully`));
178
+ }
179
+ async function runEslint(filePaths, cwd) {
180
+ const fileChunks = chunkArray(filePaths, 20);
181
+ const totalChunks = fileChunks.length;
182
+ for (const [chunkIndex, fileChunk] of fileChunks.entries()) {
183
+ const eslintCommand = `yarn eslint ${fileChunk.join(' ')} --report-unused-disable-directives --fix`;
184
+ console.log(`Executing command for chunk ${chunkIndex + 1} of ${totalChunks}: ${eslintCommand}`);
185
+ try {
186
+ const result = await execAsync(eslintCommand, {
187
+ cwd
188
+ });
189
+ const {
190
+ stdout,
191
+ stderr
192
+ } = result;
193
+ if (stdout) {
194
+ console.log(chalk.blue(`ESLint output for chunk ${chunkIndex + 1} of ${totalChunks}:\n${stdout}`));
195
+ }
196
+ if (stderr) {
197
+ console.error(chalk.yellow(`ESLint errors for chunk ${chunkIndex + 1} of ${totalChunks}:\n${stderr}`));
198
+ }
199
+ } catch (error) {
200
+ console.error(chalk.red(`Error running ESLint on chunk ${chunkIndex + 1} of ${totalChunks}: ${error}`));
201
+
202
+ // Retry each file individually
203
+ console.log(chalk.yellow(`Retrying each file in chunk ${chunkIndex + 1} of ${totalChunks} individually...`));
204
+
205
+ // Chunk the files into smaller groups of 5 for parallel retry
206
+ const smallerChunks = chunkArray(fileChunk, 5);
207
+ const totalSmallerChunks = smallerChunks.length;
208
+ for (const [smallChunkIndex, smallerChunk] of smallerChunks.entries()) {
209
+ await Promise.all(smallerChunk.map(async file => {
210
+ try {
211
+ const individualEslintCommand = `yarn eslint ${file} --report-unused-disable-directives --fix`;
212
+ console.log(`Executing command for file in small chunk ${smallChunkIndex + 1} of ${totalSmallerChunks}: ${individualEslintCommand}`);
213
+ const result = await execAsync(individualEslintCommand, {
214
+ cwd
215
+ });
216
+ const {
217
+ stdout,
218
+ stderr
219
+ } = result;
220
+ if (stdout) {
221
+ console.log(chalk.blue(`ESLint output for file ${file} in small chunk ${smallChunkIndex + 1} of ${totalSmallerChunks}:\n${stdout}`));
222
+ }
223
+ if (stderr) {
224
+ console.error(chalk.yellow(`ESLint errors for file ${file} in small chunk ${smallChunkIndex + 1} of ${totalSmallerChunks}:\n${stderr}`));
225
+ }
226
+ } catch (fileError) {
227
+ console.error(chalk.red(`Error running ESLint on file ${file} in small chunk ${smallChunkIndex + 1} of ${totalSmallerChunks}: ${fileError}`));
228
+ }
229
+ }));
127
230
  }
128
231
  }
232
+ console.log(chalk.green(`Finished running ESLint for chunk ${chunkIndex + 1} of ${totalChunks}.`));
129
233
  }
234
+ console.log(chalk.green(`ESLint was run on all files successfully`));
130
235
  }
@@ -0,0 +1,8 @@
1
+ // Utility function to split an array into chunks
2
+ export const chunkArray = (array, chunkSize) => {
3
+ const result = [];
4
+ for (let i = 0; i < array.length; i += chunkSize) {
5
+ result.push(array.slice(i, i + chunkSize));
6
+ }
7
+ return result;
8
+ };
@@ -2,9 +2,10 @@ import chalk from 'chalk';
2
2
  import { colorToHex, compareHex, isValidColor } from './color-utils';
3
3
 
4
4
  // so far allowing to remove only exact matches in values. Can be increased to auto-remove fallbacks with similar values
5
- const ACCEPTABLE_COLOR_DIFFERENCE = 0;
5
+ const ACCEPTABLE_COLOR_DIFFERENCE = 15;
6
6
  const ACCEPTABLE_SPACE_DIFFERENCE = 0;
7
7
  const ACCEPTABLE_NUMERIC_DIFFERENCE = 0;
8
+ const ACCEPTABLE_BORDER_DIFFERENCE = 0;
8
9
  export function normalizeValues(tokenKey, tokenValue, fallbackValue) {
9
10
  let tokenLogValue;
10
11
  let fallbackLogValue;
@@ -28,13 +29,13 @@ export function normalizeValues(tokenKey, tokenValue, fallbackValue) {
28
29
  difference = compareHex(normalizedTokenValue, normalizedFallbackValue);
29
30
  isAcceptableDifference = difference <= ACCEPTABLE_COLOR_DIFFERENCE;
30
31
  }
31
- } else if (lowerCaseTokenKey.startsWith('space')) {
32
+ } else if (lowerCaseTokenKey.startsWith('space') || lowerCaseTokenKey.startsWith('border')) {
32
33
  const tokenValueInPx = tokenValue ? convertToPx(tokenValue) : undefined;
33
34
  const fallbackValueInPx = fallbackValue ? convertToPx(fallbackValue) : undefined;
34
35
  if (tokenValueInPx !== undefined && fallbackValueInPx !== undefined) {
35
36
  const maxVal = Math.max(tokenValueInPx, fallbackValueInPx);
36
37
  difference = Math.abs(tokenValueInPx - fallbackValueInPx) / maxVal * 100;
37
- isAcceptableDifference = difference <= ACCEPTABLE_SPACE_DIFFERENCE;
38
+ isAcceptableDifference = difference <= (lowerCaseTokenKey.startsWith('space') ? ACCEPTABLE_SPACE_DIFFERENCE : ACCEPTABLE_BORDER_DIFFERENCE);
38
39
  }
39
40
  // Log the normalized values
40
41
  normalizedTokenValue = tokenValue;
@@ -35,13 +35,13 @@ export function removeUnusedImports(importDeclarations, j) {
35
35
  return j(importDeclaration).find(j.ImportSpecifier).filter(s => removeIfUnused(s, importDeclaration)).size() > 0;
36
36
  };
37
37
  const processImportDeclaration = importDeclaration => {
38
- var _importDeclaration$va, _importDeclaration$va2;
39
- if (((_importDeclaration$va = importDeclaration.value.specifiers) === null || _importDeclaration$va === void 0 ? void 0 : _importDeclaration$va.length) === 0) {
38
+ var _importDeclaration$va, _importDeclaration$va2, _importDeclaration$va3, _importDeclaration$va4;
39
+ if (((_importDeclaration$va = importDeclaration.value) === null || _importDeclaration$va === void 0 ? void 0 : (_importDeclaration$va2 = _importDeclaration$va.specifiers) === null || _importDeclaration$va2 === void 0 ? void 0 : _importDeclaration$va2.length) === 0) {
40
40
  return false;
41
41
  }
42
42
  const hadUnusedDefaultImport = removeUnusedDefaultImport(importDeclaration);
43
43
  const hadUnusedNonDefaultImports = removeUnusedNonDefaultImports(importDeclaration);
44
- if (((_importDeclaration$va2 = importDeclaration.value.specifiers) === null || _importDeclaration$va2 === void 0 ? void 0 : _importDeclaration$va2.length) === 0) {
44
+ if (((_importDeclaration$va3 = importDeclaration.value) === null || _importDeclaration$va3 === void 0 ? void 0 : (_importDeclaration$va4 = _importDeclaration$va3.specifiers) === null || _importDeclaration$va4 === void 0 ? void 0 : _importDeclaration$va4.length) === 0) {
45
45
  j(importDeclaration).remove();
46
46
  return true;
47
47
  }
@@ -25,6 +25,10 @@ function escapeCsvValue(value) {
25
25
  }
26
26
  export async function clearFolder(reportFolder) {
27
27
  console.log('Clearing report folder:', reportFolder);
28
+ // Create the folder if it doesn't exist
29
+ await fs.mkdir(reportFolder, {
30
+ recursive: true
31
+ });
28
32
  const filesToDelete = await fs.readdir(reportFolder);
29
33
  for (const file of filesToDelete) {
30
34
  const filePath = path.join(reportFolder, file);
@@ -33,7 +37,8 @@ export async function clearFolder(reportFolder) {
33
37
  }
34
38
  async function saveFilePaths(reportFolder, files) {
35
39
  const filesTxtPath = path.join(reportFolder, 'files.txt');
36
- await fs.writeFile(filesTxtPath, Array.from(files).map(filePath => `"${filePath}"`).join(' '), 'utf-8');
40
+ const sortedFiles = Array.from(files).sort(); // Sort the file paths alphabetically
41
+ await fs.writeFile(filesTxtPath, sortedFiles.map(filePath => `"${filePath}"`).join('\n'), 'utf-8');
37
42
  }
38
43
  export async function combineReports(reportFolder) {
39
44
  console.log('Combining reports in folder:', reportFolder);