@atlaskit/eslint-plugin-design-system 13.14.2 → 13.16.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 (66) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +2 -0
  3. package/dist/cjs/presets/all-flat.codegen.js +3 -1
  4. package/dist/cjs/presets/all.codegen.js +3 -1
  5. package/dist/cjs/presets/recommended-flat.codegen.js +2 -1
  6. package/dist/cjs/presets/recommended.codegen.js +2 -1
  7. package/dist/cjs/rules/ensure-proper-xcss-usage/index.js +157 -0
  8. package/dist/cjs/rules/index.codegen.js +5 -1
  9. package/dist/cjs/rules/no-legacy-icons/checks.js +22 -5
  10. package/dist/cjs/rules/no-legacy-icons/helpers.js +122 -46
  11. package/dist/cjs/rules/no-utility-icons/checks.js +233 -0
  12. package/dist/cjs/rules/no-utility-icons/index.js +40 -0
  13. package/dist/cjs/rules/utils/get-deprecated-config.js +1 -1
  14. package/dist/es2019/presets/all-flat.codegen.js +3 -1
  15. package/dist/es2019/presets/all.codegen.js +3 -1
  16. package/dist/es2019/presets/recommended-flat.codegen.js +2 -1
  17. package/dist/es2019/presets/recommended.codegen.js +2 -1
  18. package/dist/es2019/rules/ensure-proper-xcss-usage/index.js +149 -0
  19. package/dist/es2019/rules/index.codegen.js +5 -1
  20. package/dist/es2019/rules/no-legacy-icons/checks.js +22 -6
  21. package/dist/es2019/rules/no-legacy-icons/helpers.js +125 -44
  22. package/dist/es2019/rules/no-utility-icons/checks.js +164 -0
  23. package/dist/es2019/rules/no-utility-icons/index.js +35 -0
  24. package/dist/es2019/rules/utils/get-deprecated-config.js +3 -2
  25. package/dist/esm/presets/all-flat.codegen.js +3 -1
  26. package/dist/esm/presets/all.codegen.js +3 -1
  27. package/dist/esm/presets/recommended-flat.codegen.js +2 -1
  28. package/dist/esm/presets/recommended.codegen.js +2 -1
  29. package/dist/esm/rules/ensure-proper-xcss-usage/index.js +151 -0
  30. package/dist/esm/rules/index.codegen.js +5 -1
  31. package/dist/esm/rules/no-legacy-icons/checks.js +22 -5
  32. package/dist/esm/rules/no-legacy-icons/helpers.js +121 -45
  33. package/dist/esm/rules/no-utility-icons/checks.js +226 -0
  34. package/dist/esm/rules/no-utility-icons/index.js +34 -0
  35. package/dist/esm/rules/utils/get-deprecated-config.js +2 -2
  36. package/dist/types/index.codegen.d.ts +14 -0
  37. package/dist/types/presets/all-flat.codegen.d.ts +2 -0
  38. package/dist/types/presets/all.codegen.d.ts +2 -0
  39. package/dist/types/presets/recommended-flat.codegen.d.ts +1 -0
  40. package/dist/types/presets/recommended.codegen.d.ts +1 -0
  41. package/dist/types/rules/ensure-proper-xcss-usage/index.d.ts +3 -0
  42. package/dist/types/rules/index.codegen.d.ts +2 -0
  43. package/dist/types/rules/no-legacy-icons/helpers.d.ts +12 -4
  44. package/dist/types/rules/no-utility-icons/checks.d.ts +10 -0
  45. package/dist/types/rules/no-utility-icons/index.d.ts +3 -0
  46. package/dist/types/rules/use-tokens-typography/transformers/banned-properties.d.ts +1 -1
  47. package/dist/types/rules/use-tokens-typography/transformers/font-family.d.ts +1 -1
  48. package/dist/types/rules/use-tokens-typography/transformers/font-weight.d.ts +1 -1
  49. package/dist/types/rules/use-tokens-typography/transformers/restricted-capitalisation.d.ts +1 -1
  50. package/dist/types/rules/use-tokens-typography/transformers/untokenized-properties.d.ts +1 -1
  51. package/dist/types-ts4.5/index.codegen.d.ts +14 -0
  52. package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +2 -0
  53. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -0
  54. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -0
  55. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -0
  56. package/dist/types-ts4.5/rules/ensure-proper-xcss-usage/index.d.ts +3 -0
  57. package/dist/types-ts4.5/rules/index.codegen.d.ts +2 -0
  58. package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +12 -4
  59. package/dist/types-ts4.5/rules/no-utility-icons/checks.d.ts +10 -0
  60. package/dist/types-ts4.5/rules/no-utility-icons/index.d.ts +3 -0
  61. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/banned-properties.d.ts +1 -1
  62. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/font-family.d.ts +1 -1
  63. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/font-weight.d.ts +1 -1
  64. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/restricted-capitalisation.d.ts +1 -1
  65. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/untokenized-properties.d.ts +1 -1
  66. package/package.json +4 -4
@@ -5,7 +5,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.throwManualErrors = exports.throwAutoErrors = exports.locToString = exports.isSize = exports.isInsideNewButton = exports.isInsideLegacyButton = exports.isInsideIconOnlyLegacyButton = exports.getUpcomingIcons = exports.getMigrationMapObject = exports.createHelpers = exports.createGuidance = exports.createCantMigrateSpreadPropsError = exports.createCantMigrateSizeUnknown = exports.createCantMigrateReExportError = exports.createCantMigrateIdentifierMapOrArrayError = exports.createCantMigrateIdentifierError = exports.createCantMigrateFunctionUnknownError = exports.createCantMigrateColorError = exports.createCantFindSuitableReplacementError = exports.createAutoMigrationError = exports.canMigrateColor = exports.canAutoMigrateNewIconBasedOnSize = exports.addToListOfRanges = void 0;
8
+ exports.throwManualErrors = exports.throwAutoErrors = exports.locToString = exports.isSize = exports.isInsideNewButton = exports.isInsideLegacyButton = exports.isInsideIconOnlyLegacyButton = exports.getUpcomingIcons = exports.getMigrationMapObject = exports.getComponentName = exports.createHelpers = exports.createGuidance = exports.createCantMigrateSpreadPropsError = exports.createCantMigrateSizeUnknown = exports.createCantMigrateReExportError = exports.createCantMigrateIdentifierMapOrArrayError = exports.createCantMigrateIdentifierError = exports.createCantMigrateFunctionUnknownError = exports.createCantMigrateColorError = exports.createCantFindSuitableReplacementError = exports.createAutoMigrationError = exports.canMigrateColor = exports.canAutoMigrateNewIconBasedOnSize = exports.addToListOfRanges = void 0;
9
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
@@ -66,7 +66,7 @@ var getIconKey = function getIconKey(iconPackage) {
66
66
  * Checks if a new icon can be auto-migrated based on guidance from the migration map
67
67
  */
68
68
  var canAutoMigrateNewIconBasedOnSize = exports.canAutoMigrateNewIconBasedOnSize = function canAutoMigrateNewIconBasedOnSize(guidance) {
69
- return ['swap', 'swap-slight-visual-change', 'swap-visual-change', 'swap-size-shift-utility'].includes(guidance || '');
69
+ return guidance ? ['swap', 'swap-slight-visual-change', 'swap-visual-change'].includes(guidance) : false;
70
70
  };
71
71
 
72
72
  /**
@@ -94,8 +94,10 @@ var getNewIconNameAndImportPath = function getNewIconNameAndImportPath(iconPacka
94
94
  var createGuidance = exports.createGuidance = function createGuidance(_ref) {
95
95
  var iconPackage = _ref.iconPackage,
96
96
  insideNewButton = _ref.insideNewButton,
97
- size = _ref.size,
98
- shouldUseMigrationPath = _ref.shouldUseMigrationPath;
97
+ initialSize = _ref.size,
98
+ shouldUseMigrationPath = _ref.shouldUseMigrationPath,
99
+ shouldForceSmallIcon = _ref.shouldForceSmallIcon;
100
+ var size = shouldForceSmallIcon ? 'small' : initialSize;
99
101
  var migrationMapObject = getMigrationMapObject(iconPackage);
100
102
  var upcomingIcon = getUpcomingIcons(iconPackage);
101
103
  if (upcomingIcon) {
@@ -155,8 +157,18 @@ var createGuidance = exports.createGuidance = function createGuidance(_ref) {
155
157
  }
156
158
  if (insideNewButton) {
157
159
  _guidance += buttonGuidanceStr;
158
- } else if (size && size === 'medium') {
159
- _guidance += "Setting the spacing property to 'spacious' will maintain the icon's box dimensions - but consider setting spacing='none' as it allows for easier control of spacing by parent elements.\n";
160
+ } else if (size === 'medium') {
161
+ _guidance += "Setting the spacing='spacious' will maintain the icon's box dimensions - but consider setting spacing='none' as it allows for easier control of spacing by parent elements.\n";
162
+ } else if (size === 'small') {
163
+ if (initialSize !== 'small' && shouldForceSmallIcon) {
164
+ _guidance += "For this icon, it's recommended to use a smaller size using size='small'. Alternatively, for special cases where a larger version is needed size='medium' can be used, but it is generally discouraged for this icon.\n";
165
+ } else if (initialSize === 'small') {
166
+ if (shouldForceSmallIcon) {
167
+ _guidance += "Setting spacing='compact' will maintain the icon's box dimensions - but consider setting spacing='none' as it allows for easier control of spacing by parent elements.\n";
168
+ } else {
169
+ _guidance += "It's recommended to upscale to a medium icon with no spacing. Alternatively for special cases where smaller icons are required, the original icon size and dimensions can be maintained by using size='small' and spacing='compact'.\n";
170
+ }
171
+ }
160
172
  } else if (size) {
161
173
  _guidance += "In the new icon, please use spacing='none'.\n";
162
174
  }
@@ -280,7 +292,8 @@ var createAutoMigrationError = exports.createAutoMigrationError = function creat
280
292
  iconName = _ref4.iconName,
281
293
  errors = _ref4.errors,
282
294
  spacing = _ref4.spacing,
283
- insideNewButton = _ref4.insideNewButton;
295
+ insideNewButton = _ref4.insideNewButton,
296
+ shouldForceSmallIcon = _ref4.shouldForceSmallIcon;
284
297
  var myError = {
285
298
  node: node,
286
299
  messageId: 'noLegacyIconsAutoMigration',
@@ -289,7 +302,8 @@ var createAutoMigrationError = exports.createAutoMigrationError = function creat
289
302
  iconName: iconName,
290
303
  spacing: spacing !== null && spacing !== void 0 ? spacing : '',
291
304
  // value type need to be a string in Rule.ReportDescriptor
292
- insideNewButton: String(insideNewButton)
305
+ insideNewButton: String(insideNewButton),
306
+ shouldForceSmallIcon: String(shouldForceSmallIcon)
293
307
  }
294
308
  };
295
309
  errors[locToString(node)] = myError;
@@ -444,7 +458,7 @@ var getNewIconNameForRenaming = function getNewIconNameForRenaming(isInManualArr
444
458
  var newIconName;
445
459
  if (isInManualArray) {
446
460
  newIconName = getNewIconNameAndImportPath(importSource).iconName;
447
- var keyToName = newIconName ? newIconName[0].toUpperCase() + newIconName.slice(1) + 'Icon' : undefined;
461
+ var keyToName = newIconName ? getComponentName(newIconName) : undefined;
448
462
  newIconName = keyToName;
449
463
  if (newIconName === undefined || importSpecifier === keyToName) {
450
464
  newIconName = "".concat(keyToName, "New");
@@ -452,6 +466,11 @@ var getNewIconNameForRenaming = function getNewIconNameForRenaming(isInManualArr
452
466
  }
453
467
  return newIconName;
454
468
  };
469
+ var getComponentName = exports.getComponentName = function getComponentName(name) {
470
+ return name.split(/\W/).map(function (part) {
471
+ return "".concat(part[0].toUpperCase()).concat(part.slice(1));
472
+ }).join('').concat('Icon');
473
+ };
455
474
 
456
475
  /**
457
476
  *
@@ -517,7 +536,8 @@ var createPropFixes = function createPropFixes(_ref7) {
517
536
  migrationImportNode = _ref7.migrationImportNode,
518
537
  newIconName = _ref7.newIconName;
519
538
  var fixes = [];
520
- var spacing = metadata.spacing;
539
+ var spacing = metadata.spacing,
540
+ size = metadata.size;
521
541
  if (shouldUseMigrationPath && !legacyImportNode) {
522
542
  return fixes;
523
543
  }
@@ -533,24 +553,31 @@ var createPropFixes = function createPropFixes(_ref7) {
533
553
  if (primaryColor && primaryColor.type === 'JSXAttribute') {
534
554
  fixes.push(fixer.replaceText(primaryColor.name, 'color'));
535
555
  }
536
-
537
- // rename or remove size prop based on shouldUseMigrationPath,
538
- // add spacing="spacious" if
539
- // 1. it's in error metadata, which means size is medium
540
- // 2. no existing spacing prop
541
- // 3. iconType is "core"
542
- // 4. icon is not imported from migration entrypoint
543
556
  var sizeProp = findProp(attributes, 'size');
544
557
  var spacingProp = findProp(attributes, 'spacing');
545
- if (spacing && !spacingProp && !migrationImportNode) {
546
- fixes.push(fixer.insertTextAfter(sizeProp || openingElement.name, " spacing=\"".concat(spacing, "\"")));
547
- }
548
558
  if (sizeProp && sizeProp.type === 'JSXAttribute') {
549
- fixes.push(shouldUseMigrationPath ?
550
- // replace size prop with LEGACY_size,
551
- fixer.replaceText(sizeProp.name, 'LEGACY_size') :
552
- // remove size prop if shouldUseMigrationPath is false
553
- fixer.remove(sizeProp));
559
+ if (shouldUseMigrationPath) {
560
+ // Rename existing size prop to LEGACY_size and add new size prop if applicable
561
+ fixes.push(fixer.replaceText(sizeProp.name, 'LEGACY_size'));
562
+ if (size) {
563
+ fixes.push(fixer.insertTextAfter(sizeProp, " size=\"".concat(size, "\"")));
564
+ }
565
+ } else {
566
+ if (size && sizeProp.value) {
567
+ // update size prop with new replacement size
568
+ fixes.push(fixer.replaceText(sizeProp.value, "\"".concat(size, "\"")));
569
+ } else {
570
+ // remove size prop if no new replacement size is specified
571
+ fixes.push(fixer.remove(sizeProp));
572
+ }
573
+ }
574
+ } else if (size) {
575
+ fixes.push(fixer.insertTextAfter(openingElement.name, " size=\"".concat(size, "\"")));
576
+ }
577
+
578
+ // Add spacing prop if no existing spacing prop and icon is not imported from migration entrypoint
579
+ if (spacing && spacing !== 'none' && !spacingProp && !migrationImportNode) {
580
+ fixes.push(fixer.insertTextAfter(sizeProp || openingElement.name, " spacing=\"".concat(spacing, "\"")));
554
581
  }
555
582
 
556
583
  // rename or remove secondaryColor prop based on shouldUseMigrationPath
@@ -647,6 +674,7 @@ var throwManualErrors = exports.throwManualErrors = function throwManualErrors(_
647
674
  var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10) {
648
675
  var errorsManual = _ref10.errorsManual,
649
676
  errorsAuto = _ref10.errorsAuto,
677
+ iconSizesInfo = _ref10.iconSizesInfo,
650
678
  legacyIconImports = _ref10.legacyIconImports,
651
679
  guidance = _ref10.guidance,
652
680
  migrationIconImports = _ref10.migrationIconImports,
@@ -702,7 +730,7 @@ var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10)
702
730
  _step2;
703
731
  try {
704
732
  var _loop2 = function _loop2() {
705
- var _legacyIconImports$er, _legacyIconImports$er2, _migrationIconImports;
733
+ var _iconSizesInfo$import, _iconSizesInfo$import2, _iconSizesInfo$import3, _legacyIconImports$er, _error$data2, _legacyIconImports$er2, _migrationIconImports;
706
734
  var _step2$value = (0, _slicedToArray2.default)(_step2.value, 2),
707
735
  _ = _step2$value[0],
708
736
  error = _step2$value[1];
@@ -712,8 +740,20 @@ var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10)
712
740
  // If that is the case we'll need to provide a suggestion instead of auto-fixing as the suggestion will
713
741
  // add another import without removing the old import and this needs to be validated
714
742
  var isInManualArray = allManualErrorSources.has(importSource);
743
+
744
+ // Check if the icon has size of small, if so it cannot be automatically migrated. Two suggestions will be provided
745
+ // 1. Use core icon with no spacing
746
+ // 2. Use utility icon with compact spacing
747
+ var isSizeSmall = (_iconSizesInfo$import = iconSizesInfo[importSource]) === null || _iconSizesInfo$import === void 0 ? void 0 : _iconSizesInfo$import.small.includes(key);
748
+ var isMixedSizeUsage = ((_iconSizesInfo$import2 = iconSizesInfo[importSource]) === null || _iconSizesInfo$import2 === void 0 ? void 0 : _iconSizesInfo$import2.small.length) > 0 && ((_iconSizesInfo$import3 = iconSizesInfo[importSource]) === null || _iconSizesInfo$import3 === void 0 ? void 0 : _iconSizesInfo$import3.small.length) < iconSizesInfo[importSource].usageCount;
749
+
750
+ // Icon should be renamed
751
+ // 1. If the icon is in the manual array OR
752
+ // 2. If there is mixed size usages of this icon with size small
753
+ var shouldRenameIcon = isInManualArray || isMixedSizeUsage;
754
+
715
755
  // New icon name for renaming if the icon is in the manual array
716
- var newIconName = getNewIconNameForRenaming(isInManualArray, importSource, errorList[0].data ? (_legacyIconImports$er = legacyIconImports[errorList[0].data.iconName]) === null || _legacyIconImports$er === void 0 ? void 0 : _legacyIconImports$er.importSpecifier : undefined);
756
+ var newIconName = getNewIconNameForRenaming(shouldRenameIcon, importSource, errorList[0].data ? (_legacyIconImports$er = legacyIconImports[errorList[0].data.iconName]) === null || _legacyIconImports$er === void 0 ? void 0 : _legacyIconImports$er.importSpecifier : undefined);
717
757
  if (!node) {
718
758
  return 0; // continue
719
759
  }
@@ -721,22 +761,43 @@ var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10)
721
761
  if (Object.keys(error).includes('data') && error.data) {
722
762
  error.data.guidance = guidanceMessage;
723
763
  }
764
+ var shouldForceSmallIcon = ((_error$data2 = error.data) === null || _error$data2 === void 0 ? void 0 : _error$data2.shouldForceSmallIcon) === 'true';
724
765
  var fixArguments = error.data ? {
725
- metadata: error.data,
766
+ metadata: _objectSpread(_objectSpread({}, error.data), {}, {
767
+ spacing: error.data.isInNewButton ? 'none' : error.data.spacing,
768
+ size: shouldForceSmallIcon ? 'small' : error.data.size
769
+ }),
726
770
  legacyImportNode: (_legacyIconImports$er2 = legacyIconImports[error.data.iconName]) === null || _legacyIconImports$er2 === void 0 ? void 0 : _legacyIconImports$er2.importNode,
727
771
  migrationImportNode: (_migrationIconImports = migrationIconImports[error.data.iconName]) === null || _migrationIconImports === void 0 ? void 0 : _migrationIconImports.importNode,
728
772
  shouldUseMigrationPath: shouldUseMigrationPath,
729
- newIconName: isInManualArray ? newIconName : undefined
773
+ newIconName: shouldRenameIcon ? newIconName : undefined
730
774
  } : null;
731
775
  if (!error.data || shouldUseMigrationPath && !checkIfNewIconExist(error) || !fixArguments) {
732
776
  return 0; // continue
733
777
  }
734
- if (isInManualArray) {
735
- // provide suggestion if there is a manual error for the same import source and thus the legacy import can't be removed
778
+ var isInNewButton = fixArguments.metadata.insideNewButton === 'true';
779
+ if (isSizeSmall && !shouldForceSmallIcon) {
736
780
  error.suggest = [{
737
- desc: 'Rename icon import, import from the new package, and update props.',
781
+ desc: isInNewButton ? 'Replace with medium core icon (Recommended)' : 'Replace with medium core icon and no spacing (Recommended)',
782
+ fix: function fix(fixer) {
783
+ return [].concat((0, _toConsumableArray2.default)(createPropFixes(_objectSpread(_objectSpread({}, fixArguments), {}, {
784
+ metadata: _objectSpread(_objectSpread({}, fixArguments.metadata), {}, {
785
+ spacing: 'none'
786
+ }),
787
+ node: node,
788
+ fixer: fixer
789
+ }))), (0, _toConsumableArray2.default)(createImportFix(_objectSpread(_objectSpread({}, fixArguments), {}, {
790
+ fixer: fixer
791
+ }))));
792
+ }
793
+ }, {
794
+ desc: isInNewButton ? 'Replace with small core icon' : 'Replace with small core icon and compact spacing',
738
795
  fix: function fix(fixer) {
739
796
  return [].concat((0, _toConsumableArray2.default)(createPropFixes(_objectSpread(_objectSpread({}, fixArguments), {}, {
797
+ metadata: _objectSpread(_objectSpread({}, fixArguments.metadata), {}, {
798
+ spacing: 'compact',
799
+ size: 'small'
800
+ }),
740
801
  node: node,
741
802
  fixer: fixer
742
803
  }))), (0, _toConsumableArray2.default)(createImportFix(_objectSpread(_objectSpread({}, fixArguments), {}, {
@@ -745,25 +806,40 @@ var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10)
745
806
  }
746
807
  }];
747
808
  } else {
748
- // Update Guidance message for auto-fixing
749
- if (error.data) {
750
- error.data.guidance = error.data.guidance + "\nTo automatically fix this icon, run the auto-fixer attached to the first use of ".concat(importSource, " in this file - either manually, or by saving this file.");
751
- }
752
- // There should only be 1 import fix for each import source and thus only add this at the start of the list
753
- if (autoFixers.length === 0) {
809
+ if (isInManualArray) {
810
+ // provide suggestion if there is a manual error for the same import source and thus the legacy import can't be removed
811
+ error.suggest = [{
812
+ desc: 'Rename icon import, import from the new package, and update props.',
813
+ fix: function fix(fixer) {
814
+ return [].concat((0, _toConsumableArray2.default)(createPropFixes(_objectSpread(_objectSpread({}, fixArguments), {}, {
815
+ node: node,
816
+ fixer: fixer
817
+ }))), (0, _toConsumableArray2.default)(createImportFix(_objectSpread(_objectSpread({}, fixArguments), {}, {
818
+ fixer: fixer
819
+ }))));
820
+ }
821
+ }];
822
+ } else {
823
+ // Update Guidance message for auto-fixing
824
+ if (error.data) {
825
+ error.data.guidance = error.data.guidance + "\nTo automatically fix this icon, run the auto-fixer attached to the first use of ".concat(importSource, " in this file - either manually, or by saving this file.");
826
+ }
827
+ // There should only be 1 import fix for each import source and thus only add this at the start of the list
828
+ if (autoFixers.length === 0) {
829
+ autoFixers.push(function (fixer) {
830
+ return createImportFix(_objectSpread(_objectSpread({}, fixArguments), {}, {
831
+ fixer: fixer
832
+ }));
833
+ });
834
+ }
835
+ // Push the prop fix regardless
754
836
  autoFixers.push(function (fixer) {
755
- return createImportFix(_objectSpread(_objectSpread({}, fixArguments), {}, {
837
+ return createPropFixes(_objectSpread(_objectSpread({}, fixArguments), {}, {
838
+ node: node,
756
839
  fixer: fixer
757
840
  }));
758
841
  });
759
842
  }
760
- // Push the prop fix regardless
761
- autoFixers.push(function (fixer) {
762
- return createPropFixes(_objectSpread(_objectSpread({}, fixArguments), {}, {
763
- node: node,
764
- fixer: fixer
765
- }));
766
- });
767
843
  }
768
844
  // Add the error to the appliedErrorsForImport, ready to be thrown later
769
845
  appliedErrorsForImport.push(error);
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createChecks = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
10
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
11
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
+ var specialCases = {
14
+ '@atlaskit/icon/utility/cross': '@atlaskit/icon/core/close',
15
+ '@atlaskit/icon/utility/migration/cross--editor-close': '@atlaskit/icon/core/migration/close--editor-close'
16
+ };
17
+ var iconPropsinNewButton = ['icon', 'iconBefore', 'iconAfter'];
18
+ var createChecks = exports.createChecks = function createChecks(context) {
19
+ var importStatementsUtility = {};
20
+ var importStatementsCore = {};
21
+ var newButtonImports = new Set();
22
+ var errors = {};
23
+ var checkImportDeclarations = function checkImportDeclarations(node) {
24
+ var moduleSource = node.source.value;
25
+ if (typeof moduleSource !== 'string') {
26
+ return;
27
+ }
28
+ if (moduleSource.startsWith('@atlaskit/icon/utility/')) {
29
+ var _iterator = _createForOfIteratorHelper(node.specifiers),
30
+ _step;
31
+ try {
32
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
33
+ var specifier = _step.value;
34
+ if (specifier.type === 'ImportDefaultSpecifier') {
35
+ importStatementsUtility[specifier.local.name] = node;
36
+ }
37
+ }
38
+ } catch (err) {
39
+ _iterator.e(err);
40
+ } finally {
41
+ _iterator.f();
42
+ }
43
+ } else if (moduleSource.startsWith('@atlaskit/icon/core/')) {
44
+ var _iterator2 = _createForOfIteratorHelper(node.specifiers),
45
+ _step2;
46
+ try {
47
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
48
+ var _specifier = _step2.value;
49
+ if (_specifier.type === 'ImportDefaultSpecifier') {
50
+ importStatementsCore[moduleSource] = {
51
+ node: node,
52
+ localName: _specifier.local.name
53
+ };
54
+ }
55
+ }
56
+ } catch (err) {
57
+ _iterator2.e(err);
58
+ } finally {
59
+ _iterator2.f();
60
+ }
61
+ } else if (moduleSource.startsWith('@atlaskit/button/')) {
62
+ var _iterator3 = _createForOfIteratorHelper(node.specifiers),
63
+ _step3;
64
+ try {
65
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
66
+ var _specifier2 = _step3.value;
67
+ newButtonImports.add(_specifier2.local.name);
68
+ }
69
+ } catch (err) {
70
+ _iterator3.e(err);
71
+ } finally {
72
+ _iterator3.f();
73
+ }
74
+ }
75
+ };
76
+ var checkJSXElement = function checkJSXElement(node) {
77
+ if (!((0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier') && importStatementsUtility.hasOwnProperty(node.openingElement.name.name) && typeof importStatementsUtility[node.openingElement.name.name].source.value === 'string')) {
78
+ return;
79
+ }
80
+ if (!errors.hasOwnProperty(node.openingElement.name.name)) {
81
+ errors[node.openingElement.name.name] = [];
82
+ }
83
+ errors[node.openingElement.name.name].push({
84
+ node: node,
85
+ messageId: 'noUtilityIconsJSXElement',
86
+ localName: node.openingElement.name.name,
87
+ fixable: true,
88
+ inNewButton: false
89
+ });
90
+ };
91
+
92
+ // Cases: As Props, In Function Calls, In Arrays, In Maps, In Exports
93
+ var checkIconReference = function checkIconReference(node) {
94
+ //if this is an import statement then exit early
95
+ if (node.parent && ((0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportSpecifier') || (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportDefaultSpecifier'))) {
96
+ return;
97
+ }
98
+
99
+ //check the reference to see if it's a utility icon, if not exit early
100
+ if (!importStatementsUtility.hasOwnProperty(node.name)) {
101
+ return;
102
+ }
103
+
104
+ // if it is in new Button then we can fix it
105
+ if (node.parent && node.parent.parent && node.parent.parent.parent && (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'JSXExpressionContainer') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.name, 'JSXIdentifier') && iconPropsinNewButton.includes(node.parent.parent.name.name) && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.parent, 'JSXOpeningElement') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.parent.name, 'JSXIdentifier') && newButtonImports.has(node.parent.parent.parent.name.name)) {
106
+ // if it is in new Button then we can fix it
107
+ if (!errors.hasOwnProperty(node.name)) {
108
+ errors[node.name] = [];
109
+ }
110
+ errors[node.name].push({
111
+ node: node,
112
+ messageId: 'noUtilityIconsReference',
113
+ localName: node.name,
114
+ fixable: true,
115
+ inNewButton: true
116
+ });
117
+ return;
118
+ }
119
+
120
+ // manually error
121
+ if (!errors.hasOwnProperty(node.name)) {
122
+ errors[node.name] = [];
123
+ }
124
+ errors[node.name].push({
125
+ node: node,
126
+ messageId: 'noUtilityIconsReference',
127
+ localName: node.name,
128
+ fixable: false,
129
+ inNewButton: false
130
+ });
131
+ };
132
+
133
+ /**
134
+ * Throws the relevant errors in the correct order.
135
+ */
136
+ var throwErrors = function throwErrors() {
137
+ var _loop = function _loop() {
138
+ var utilityIcon = _Object$keys[_i];
139
+ var allFixable = errors[utilityIcon].every(function (x) {
140
+ return x.fixable;
141
+ }); // Check if ALL errors for a giving import are fixable
142
+ var originalImportNode = importStatementsUtility[utilityIcon];
143
+ var oldImportName = importStatementsUtility[utilityIcon].source.value;
144
+ var newImportName = specialCases.hasOwnProperty(oldImportName) ? specialCases[oldImportName] : oldImportName.replace('@atlaskit/icon/utility/', '@atlaskit/icon/core/');
145
+ var existingImport = importStatementsCore.hasOwnProperty(newImportName) ? importStatementsCore[newImportName].localName : null;
146
+ var replacementImportName = existingImport ? existingImport : allFixable ? utilityIcon : "".concat(utilityIcon, "Core");
147
+ var importFixAdded = false;
148
+ var _iterator4 = _createForOfIteratorHelper(errors[utilityIcon].entries()),
149
+ _step4;
150
+ try {
151
+ var _loop2 = function _loop2() {
152
+ var _step4$value = (0, _slicedToArray2.default)(_step4.value, 2),
153
+ index = _step4$value[0],
154
+ error = _step4$value[1];
155
+ if (error.fixable) {
156
+ context.report({
157
+ node: error.node,
158
+ messageId: error.messageId,
159
+ fix: function fix(fixer) {
160
+ var fixes = [];
161
+
162
+ // Add a new import statement if it doesn't already exist
163
+ if (!existingImport && !importFixAdded) {
164
+ importFixAdded = true;
165
+ fixes.push(fixer.insertTextBeforeRange([0, 0], "import ".concat(replacementImportName, " from '").concat(newImportName, "';\n")));
166
+ }
167
+
168
+ // Handle JSX elements differently if they are in a "new Button"
169
+ if (error.inNewButton) {
170
+ // Replace the icon with a function that wraps it with iconProps and size="small"
171
+ var wrappedIcon = "(iconProps) => <".concat(replacementImportName, " label=\"\" {...iconProps} size=\"small\" />");
172
+ fixes.push(fixer.replaceText(error.node, wrappedIcon));
173
+ } else if ((0, _eslintCodemodUtils.isNodeOfType)(error.node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(error.node.openingElement.name, 'JSXIdentifier')) {
174
+ // Replace the JSX element's closing tag with size="small"
175
+ var newOpeningElementText = context.sourceCode.getText(error.node.openingElement).replace(/\s*\/\s*>$/, " size=\"small\"/>").replace(new RegExp('<\s*' + error.node.openingElement.name.name), "<".concat(replacementImportName));
176
+ fixes.push(fixer.replaceText(error.node.openingElement, newOpeningElementText));
177
+ }
178
+
179
+ // Handle the first fixable error for import removal if all fixable for this import
180
+ if (index === 0 && allFixable) {
181
+ fixes.push(fixer.remove(originalImportNode));
182
+ }
183
+ return fixes;
184
+ }
185
+ });
186
+ } else {
187
+ // Report non-fixable errors
188
+ context.report({
189
+ node: error.node,
190
+ messageId: error.messageId
191
+ });
192
+ }
193
+ };
194
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
195
+ _loop2();
196
+ }
197
+ } catch (err) {
198
+ _iterator4.e(err);
199
+ } finally {
200
+ _iterator4.f();
201
+ }
202
+ };
203
+ for (var _i = 0, _Object$keys = Object.keys(errors); _i < _Object$keys.length; _i++) {
204
+ _loop();
205
+ }
206
+
207
+ // If other utility icons are imported but there were no errors for them - (this should only be unused imports but good to have as a backup), report them
208
+ var otherUtilityImportsWithoutErrors = Object.keys(importStatementsUtility).filter(function (utilityIcon) {
209
+ return !errors.hasOwnProperty(utilityIcon);
210
+ });
211
+ var _iterator5 = _createForOfIteratorHelper(otherUtilityImportsWithoutErrors),
212
+ _step5;
213
+ try {
214
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
215
+ var utilityIcon = _step5.value;
216
+ context.report({
217
+ node: importStatementsUtility[utilityIcon],
218
+ messageId: 'noUtilityIconsImport'
219
+ });
220
+ }
221
+ } catch (err) {
222
+ _iterator5.e(err);
223
+ } finally {
224
+ _iterator5.f();
225
+ }
226
+ };
227
+ return {
228
+ checkImportDeclarations: checkImportDeclarations,
229
+ checkJSXElement: checkJSXElement,
230
+ checkIconReference: checkIconReference,
231
+ throwErrors: throwErrors
232
+ };
233
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _createRule = require("../utils/create-rule");
8
+ var _checks = require("./checks");
9
+ var rule = (0, _createRule.createLintRule)({
10
+ meta: {
11
+ name: 'no-utility-icons',
12
+ fixable: 'code',
13
+ hasSuggestions: true,
14
+ type: 'problem',
15
+ docs: {
16
+ description: 'Disallow use of deprecated utility icons, in favor of core icons with `size="small"`.',
17
+ recommended: true,
18
+ severity: 'warn'
19
+ },
20
+ messages: {
21
+ noUtilityIconsJSXElement: "Utility icons are deprecated. Please use core icons instead with the size prop set to small.",
22
+ noUtilityIconsImport: "Utility icons are deprecated. Please do not import them, use core icons instead.",
23
+ noUtilityIconsReference: "Utility icons are deprecated. To replace them, please use core icons with the size prop set to small instead."
24
+ }
25
+ },
26
+ create: function create(context) {
27
+ var _createChecks = (0, _checks.createChecks)(context),
28
+ checkImportDeclarations = _createChecks.checkImportDeclarations,
29
+ checkJSXElement = _createChecks.checkJSXElement,
30
+ checkIconReference = _createChecks.checkIconReference,
31
+ throwErrors = _createChecks.throwErrors;
32
+ return {
33
+ ImportDeclaration: checkImportDeclarations,
34
+ JSXElement: checkJSXElement,
35
+ Identifier: checkIconReference,
36
+ 'Program:exit': throwErrors
37
+ };
38
+ }
39
+ });
40
+ var _default = exports.default = rule;
@@ -17,7 +17,7 @@ var getConfig = exports.getConfig = function getConfig(specifier) {
17
17
  var source = _fs.default.readFileSync(configPath, 'utf8');
18
18
  var parsedConfig = JSON.parse(source);
19
19
  var combinedConfig = _objectSpread(_objectSpread({}, parsedConfig), {}, {
20
- imports: _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, parsedConfig.imports), _deprecatedMap2.deprecatedCore), _deprecatedMap2.deprecatedUtility), _deprecatedMap.deprecatedCore)
20
+ imports: _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, parsedConfig.imports), _deprecatedMap2.deprecatedCore), _deprecatedMap2.deprecatedUtility), _deprecatedMap.deprecatedCore), _deprecatedMap.deprecatedUtility)
21
21
  });
22
22
  return combinedConfig[specifier];
23
23
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::c6c896451f2be4d48f04068f5bbb85f1>>
3
+ * @codegen <<SignedSource::5ceb45b21744434ca96a850461a3c574>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -12,6 +12,7 @@ export default {
12
12
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
13
13
  '@atlaskit/design-system/ensure-design-token-usage/preview': 'warn',
14
14
  '@atlaskit/design-system/ensure-icon-color': 'error',
15
+ '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
15
16
  '@atlaskit/design-system/icon-label': 'warn',
16
17
  '@atlaskit/design-system/no-banned-imports': 'error',
17
18
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
@@ -47,6 +48,7 @@ export default {
47
48
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
48
49
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
49
50
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
51
+ '@atlaskit/design-system/no-utility-icons': 'warn',
50
52
  '@atlaskit/design-system/prefer-primitives': 'warn',
51
53
  '@atlaskit/design-system/use-button-group-label': 'warn',
52
54
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::d4de619ac262298b2af11f905a02b0dd>>
3
+ * @codegen <<SignedSource::b96d8bb5115de6e0a230feef152a1365>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ export default {
11
11
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
12
12
  '@atlaskit/design-system/ensure-design-token-usage/preview': 'warn',
13
13
  '@atlaskit/design-system/ensure-icon-color': 'error',
14
+ '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
14
15
  '@atlaskit/design-system/icon-label': 'warn',
15
16
  '@atlaskit/design-system/no-banned-imports': 'error',
16
17
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
@@ -46,6 +47,7 @@ export default {
46
47
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
47
48
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
48
49
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
50
+ '@atlaskit/design-system/no-utility-icons': 'warn',
49
51
  '@atlaskit/design-system/prefer-primitives': 'warn',
50
52
  '@atlaskit/design-system/use-button-group-label': 'warn',
51
53
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::af96131434aa77c7882ceb200e4e2cf1>>
3
+ * @codegen <<SignedSource::10f372e16c048db9bfb1bc36cf48421c>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -36,6 +36,7 @@ export default {
36
36
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
37
37
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
38
38
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
39
+ '@atlaskit/design-system/no-utility-icons': 'warn',
39
40
  '@atlaskit/design-system/use-button-group-label': 'warn',
40
41
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
41
42
  '@atlaskit/design-system/use-datetime-picker-calendar-button': 'warn',