@atlaskit/eslint-plugin-design-system 11.1.0 → 11.3.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 (41) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/cjs/rules/no-deprecated-apis/index.js +13 -26
  3. package/dist/cjs/rules/no-legacy-icons/checks.js +14 -3
  4. package/dist/cjs/rules/no-legacy-icons/helpers.js +3 -14
  5. package/dist/cjs/rules/no-legacy-icons/index.js +3 -0
  6. package/dist/cjs/rules/use-tokens-typography/config/index.js +2 -1
  7. package/dist/cjs/rules/use-tokens-typography/index.js +15 -6
  8. package/dist/cjs/rules/use-tokens-typography/transformers/font-weight.js +96 -0
  9. package/dist/cjs/rules/use-tokens-typography/transformers/style-object.js +5 -0
  10. package/dist/cjs/rules/use-tokens-typography/utils.js +6 -0
  11. package/dist/es2019/rules/no-deprecated-apis/index.js +14 -23
  12. package/dist/es2019/rules/no-legacy-icons/checks.js +14 -3
  13. package/dist/es2019/rules/no-legacy-icons/helpers.js +3 -14
  14. package/dist/es2019/rules/no-legacy-icons/index.js +3 -0
  15. package/dist/es2019/rules/use-tokens-typography/config/index.js +2 -1
  16. package/dist/es2019/rules/use-tokens-typography/index.js +13 -6
  17. package/dist/es2019/rules/use-tokens-typography/transformers/font-weight.js +92 -0
  18. package/dist/es2019/rules/use-tokens-typography/transformers/style-object.js +5 -0
  19. package/dist/es2019/rules/use-tokens-typography/utils.js +6 -0
  20. package/dist/esm/rules/no-deprecated-apis/index.js +14 -26
  21. package/dist/esm/rules/no-legacy-icons/checks.js +14 -3
  22. package/dist/esm/rules/no-legacy-icons/helpers.js +3 -14
  23. package/dist/esm/rules/no-legacy-icons/index.js +3 -0
  24. package/dist/esm/rules/use-tokens-typography/config/index.js +2 -1
  25. package/dist/esm/rules/use-tokens-typography/index.js +15 -6
  26. package/dist/esm/rules/use-tokens-typography/transformers/font-weight.js +90 -0
  27. package/dist/esm/rules/use-tokens-typography/transformers/style-object.js +5 -0
  28. package/dist/esm/rules/use-tokens-typography/utils.js +6 -0
  29. package/dist/types/index.codegen.d.ts +3 -9
  30. package/dist/types/rules/index.codegen.d.ts +1 -3
  31. package/dist/types/rules/no-deprecated-apis/index.d.ts +2 -4
  32. package/dist/types/rules/no-legacy-icons/helpers.d.ts +1 -0
  33. package/dist/types/rules/use-tokens-typography/config/index.d.ts +3 -0
  34. package/dist/types/rules/use-tokens-typography/transformers/font-weight.d.ts +13 -0
  35. package/dist/types-ts4.5/index.codegen.d.ts +3 -15
  36. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -5
  37. package/dist/types-ts4.5/rules/no-deprecated-apis/index.d.ts +2 -6
  38. package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +1 -0
  39. package/dist/types-ts4.5/rules/use-tokens-typography/config/index.d.ts +3 -0
  40. package/dist/types-ts4.5/rules/use-tokens-typography/transformers/font-weight.d.ts +13 -0
  41. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 11.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#175432](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/175432)
8
+ [`0a1070983ac76`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/0a1070983ac76) -
9
+ `use-tokens-typography` rule now reports on `fontWeight` used with raw values (e.g. 600, 'bold').
10
+ If a matching token is found, a fix is suggested. This rule is disabled by default but can be
11
+ enabled under the name `font-weight`.
12
+
13
+ ### Patch Changes
14
+
15
+ - [#173274](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/173274)
16
+ [`fd5bac37c73ba`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/fd5bac37c73ba) -
17
+ Fix eslint type error.
18
+
19
+ ## 11.2.0
20
+
21
+ ### Minor Changes
22
+
23
+ - [#175583](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/175583)
24
+ [`75911cb003bd5`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/75911cb003bd5) - ####
25
+ no-legacy-icons
26
+
27
+ Add new `shouldUseSafeMigrationMode` flag to no-legacy-icons rule. When set to true, the autofixer
28
+ will only attempt to migrate icons that are visually similar and do not include secondary colors
29
+ or sizes other than medium.
30
+
31
+ Additionally, the autofixer will no longer attempt to explicity add `color="currentColor"` for
32
+ every migration as this is now the default.
33
+
34
+ #### no-deprecated-apis
35
+
36
+ Refactored to fix type errors and match code style of other rules.
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies
41
+
3
42
  ## 11.1.0
4
43
 
5
44
  ### Minor Changes
@@ -1,43 +1,36 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.noDeprecatedJSXAttributeMessageId = exports.name = exports.default = void 0;
8
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
- var _utils = require("@typescript-eslint/utils");
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
10
8
  var _createRule = require("../utils/create-rule");
11
9
  var _getDeprecatedConfig = require("../utils/get-deprecated-config");
12
10
  var _types = require("../utils/types");
13
11
  var noDeprecatedJSXAttributeMessageId = exports.noDeprecatedJSXAttributeMessageId = 'noDeprecatedJSXAttributes';
14
- var isNodeOfType = function isNodeOfType(node, nodeType) {
15
- return _utils.ASTUtils.isNodeOfType(nodeType)(node);
16
- };
17
12
  var isImportDeclaration = function isImportDeclaration(programStatement) {
18
13
  return (programStatement === null || programStatement === void 0 ? void 0 : programStatement.type) === 'ImportDeclaration';
19
14
  };
20
15
  var findJSXElementName = function findJSXElementName(jsxAttributeNode) {
21
- if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode.parent, _utils.AST_NODE_TYPES.JSXOpeningElement)) {
16
+ if (!jsxAttributeNode.parent || !(0, _eslintCodemodUtils.isNodeOfType)(jsxAttributeNode === null || jsxAttributeNode === void 0 ? void 0 : jsxAttributeNode.parent, 'JSXOpeningElement')) {
22
17
  return;
23
18
  }
24
19
  var openingElement = jsxAttributeNode.parent;
25
- if (!isNodeOfType(openingElement.name, _utils.AST_NODE_TYPES.JSXIdentifier)) {
20
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(openingElement.name, 'JSXIdentifier')) {
26
21
  return;
27
22
  }
28
23
  return openingElement.name.name;
29
24
  };
30
25
  var name = exports.name = 'no-deprecated-apis';
31
- var rule = (0, _createRule.createRule)({
32
- name: name,
33
- defaultOptions: [{
34
- deprecatedConfig: (0, _getDeprecatedConfig.getConfig)('jsxAttributes')
35
- }],
26
+ var rule = (0, _createRule.createLintRule)({
36
27
  meta: {
28
+ name: name,
37
29
  type: 'suggestion',
38
30
  docs: {
39
31
  description: 'Disallow using deprecated APIs.',
40
- recommended: 'strict'
32
+ recommended: true,
33
+ severity: 'error'
41
34
  },
42
35
  messages: {
43
36
  noDeprecatedJSXAttributes: 'The JSX attribute {{propName}} has been deprecated.'
@@ -75,24 +68,18 @@ var rule = (0, _createRule.createRule)({
75
68
  }
76
69
  }]
77
70
  },
78
- create: function create(context, _ref) {
71
+ create: function create(context) {
79
72
  var _context$options$;
80
- var _ref2 = (0, _slicedToArray2.default)(_ref, 1),
81
- options = _ref2[0];
82
- // Get rule configuration
83
- var defaultDeprecatedConfig = options.deprecatedConfig;
84
-
85
73
  // Get the rule configuration specified otherwise use default config.
86
74
  // A bit confusing as it seems that the default options have precedence over the user specified options.
87
- var deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || defaultDeprecatedConfig;
75
+ var deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || (0, _getDeprecatedConfig.getConfig)('jsxAttributes');
88
76
  return {
89
77
  // find JSX atribute - find name of attribute - get source and find relevant identifiers.
90
78
  JSXAttribute: function JSXAttribute(node) {
91
- var jsxAttributeIdentifier = node.name;
92
- if (!isNodeOfType(jsxAttributeIdentifier, _utils.AST_NODE_TYPES.JSXIdentifier)) {
79
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXAttribute') || !(0, _eslintCodemodUtils.isNodeOfType)(node.name, 'JSXIdentifier')) {
93
80
  return;
94
81
  }
95
- var jsxAttributeName = jsxAttributeIdentifier.name;
82
+ var jsxAttributeName = node.name.name;
96
83
  if (!(0, _types.isDeprecatedJSXAttributeConfig)(deprecatedConfig) || !deprecatedConfig[jsxAttributeName]) {
97
84
  return;
98
85
  }
@@ -100,13 +87,13 @@ var rule = (0, _createRule.createRule)({
100
87
  if (!jsxElementName) {
101
88
  return;
102
89
  }
103
- var source = context.getSourceCode();
90
+ var source = context.sourceCode;
104
91
 
105
92
  // find an import for the path of the banned api
106
93
  deprecatedConfig[jsxAttributeName].forEach(function (importItem) {
107
94
  var _importItem$namedSpec;
108
95
  var importNode = source.ast.body.filter(isImportDeclaration).find(function (node) {
109
- return node.source.value.includes(importItem.moduleSpecifier);
96
+ return node && node.source.value && typeof node.source.value === 'string' && node.source.value.includes(importItem.moduleSpecifier);
110
97
  });
111
98
  if (!importNode) {
112
99
  return;
@@ -10,7 +10,7 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
10
10
  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; } }
11
11
  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; }
12
12
  var createChecks = exports.createChecks = function createChecks(context) {
13
- //create global variables to be shared by the checks
13
+ // Create global variables to be shared by the checks
14
14
  var _createHelpers = (0, _helpers.createHelpers)(context),
15
15
  getPrimaryColor = _createHelpers.getPrimaryColor,
16
16
  getConfigFlag = _createHelpers.getConfigFlag;
@@ -27,6 +27,7 @@ var createChecks = exports.createChecks = function createChecks(context) {
27
27
  var shouldErrorForAutoMigration = getConfigFlag('shouldErrorForAutoMigration', true);
28
28
  var isQuietMode = getConfigFlag('quiet', false);
29
29
  var shouldUseMigrationPath = getConfigFlag('shouldUseMigrationPath', true);
30
+ var shouldUseSafeMigrationMode = getConfigFlag('shouldUseSafeMigrationMode', false);
30
31
 
31
32
  // Sorted list of ranges
32
33
  var errorRanges = [];
@@ -411,10 +412,11 @@ var createChecks = exports.createChecks = function createChecks(context) {
411
412
  // Find size prop on node
412
413
  var size = 'medium';
413
414
  var primaryColor = null;
415
+ var hasPrimaryColorProp = false;
416
+ var hasSecondaryColorProp = false;
414
417
  var afterSpreadSet = new Set();
415
418
  var requiredAttributesAfterSpread = new Set(['size', 'primaryColor', 'secondaryColor']);
416
419
  var hasSpread = false;
417
- var hasPrimaryColorProp = false;
418
420
  var _iterator8 = _createForOfIteratorHelper(node.openingElement.attributes),
419
421
  _step8;
420
422
  try {
@@ -449,6 +451,9 @@ var createChecks = exports.createChecks = function createChecks(context) {
449
451
  primaryColor = getPrimaryColor(attr);
450
452
  hasPrimaryColorProp = true;
451
453
  break;
454
+ case 'secondaryColor':
455
+ hasSecondaryColorProp = true;
456
+ break;
452
457
  }
453
458
  }
454
459
  } catch (err) {
@@ -457,6 +462,8 @@ var createChecks = exports.createChecks = function createChecks(context) {
457
462
  _iterator8.f();
458
463
  }
459
464
  var hasManualMigration = false;
465
+
466
+ // Flag manual migration if primary color cannot be migrated
460
467
  if (primaryColor && !(0, _helpers.canMigrateColor)(primaryColor) || hasPrimaryColorProp && !primaryColor) {
461
468
  (0, _helpers.createCantMigrateColorError)(node, primaryColor ? "the value of '".concat(primaryColor, "'") : 'a statically unknown value', errorsManual, legacyIconImports[name].packageName, name);
462
469
  hasManualMigration = true;
@@ -468,6 +475,7 @@ var createChecks = exports.createChecks = function createChecks(context) {
468
475
  (0, _helpers.createCantMigrateSizeUnknown)(node, errorsManual, legacyIconImports[name].packageName, name);
469
476
  hasManualMigration = true;
470
477
  }
478
+
471
479
  // Do a set comparison - is requiredAttributesAfterSpread a subset of afterSpreadSet?
472
480
  if (hasSpread === true && !Array.from(requiredAttributesAfterSpread).every(function (val) {
473
481
  return afterSpreadSet.has(val);
@@ -478,6 +486,7 @@ var createChecks = exports.createChecks = function createChecks(context) {
478
486
  (0, _helpers.createCantMigrateSpreadPropsError)(node, missingProps, errorsManual, legacyIconImports[name].packageName, name);
479
487
  hasManualMigration = true;
480
488
  }
489
+
481
490
  // Check if it is an exported component?
482
491
  if (legacyIconImports[name].exported) {
483
492
  (0, _helpers.createCantMigrateReExportError)(node, legacyIconImports[name].packageName, name, errorsManual);
@@ -507,7 +516,9 @@ var createChecks = exports.createChecks = function createChecks(context) {
507
516
  spacing = 'spacious';
508
517
  }
509
518
  }
510
- if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
519
+ if (shouldUseSafeMigrationMode && !hasManualMigration && (newIcon !== null && newIcon !== void 0 && newIcon.isMigrationUnsafe || size !== 'medium' || hasSecondaryColorProp)) {
520
+ (0, _helpers.createCantFindSuitableReplacementError)(node, legacyIconImports[name].packageName, name, errorsManual, upcomingIcon ? true : migrationMapObject ? true : false);
521
+ } else if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
511
522
  (0, _helpers.createAutoMigrationError)({
512
523
  node: node,
513
524
  importSource: legacyIconImports[name].packageName,
@@ -480,8 +480,7 @@ var createPropFixes = function createPropFixes(_ref7) {
480
480
  migrationImportNode = _ref7.migrationImportNode,
481
481
  newIconName = _ref7.newIconName;
482
482
  var fixes = [];
483
- var spacing = metadata.spacing,
484
- insideNewButton = metadata.insideNewButton;
483
+ var spacing = metadata.spacing;
485
484
  if (shouldUseMigrationPath && !legacyImportNode) {
486
485
  return fixes;
487
486
  }
@@ -498,16 +497,6 @@ var createPropFixes = function createPropFixes(_ref7) {
498
497
  fixes.push(fixer.replaceText(primaryColor.name, 'color'));
499
498
  }
500
499
 
501
- // add color="currentColor" if
502
- // 1. primaryColor prop is not set
503
- // 2. icon is not imported from migration entrypoint
504
- // 3. icon element is not inside a new button
505
- if (legacyImportNode && !primaryColor && !migrationImportNode &&
506
- // value type need to be a string in Rule.ReportDescriptor
507
- insideNewButton !== 'true') {
508
- fixes.push(fixer.insertTextAfter(openingElement.name, " color=\"currentColor\""));
509
- }
510
-
511
500
  // rename or remove size prop based on shouldUseMigrationPath,
512
501
  // add spacing="spacious" if
513
502
  // 1. it's in error metadata, which means size is medium
@@ -637,12 +626,12 @@ var throwAutoErrors = exports.throwAutoErrors = function throwAutoErrors(_ref10)
637
626
  }
638
627
  return result;
639
628
  }, new Set());
640
- //group errors by import source and remove any unwanted errors
629
+ // Group errors by import source and remove any unwanted errors
641
630
  var groupedErrorList = Object.entries(errorsAuto).reduce(function (result, option) {
642
631
  var _option2 = (0, _slicedToArray2.default)(option, 2),
643
632
  key = _option2[0],
644
633
  error = _option2[1];
645
- //return early if no data
634
+ // Return early if no data
646
635
  if (!error.data) {
647
636
  return result;
648
637
  }
@@ -28,6 +28,9 @@ var rule = (0, _createRule.createLintRule)({
28
28
  shouldErrorForAutoMigration: {
29
29
  type: 'boolean'
30
30
  },
31
+ shouldUseSafeMigrationMode: {
32
+ type: 'boolean'
33
+ },
31
34
  quiet: {
32
35
  type: 'boolean'
33
36
  },
@@ -26,7 +26,8 @@ var ruleSchema = exports.ruleSchema = {
26
26
  var defaultConfig = {
27
27
  failSilently: false,
28
28
  shouldEnforceFallbacks: false,
29
- enableUnsafeAutofix: false
29
+ enableUnsafeAutofix: false,
30
+ patterns: ['style-object']
30
31
  };
31
32
  var getConfig = exports.getConfig = function getConfig(overrides) {
32
33
  return Object.assign({}, defaultConfig, overrides);
@@ -7,18 +7,26 @@ exports.default = void 0;
7
7
  var _createRule = require("../utils/create-rule");
8
8
  var _errorBoundary = require("../utils/error-boundary");
9
9
  var _config = require("./config");
10
+ var _fontWeight = require("./transformers/font-weight");
10
11
  var _styleObject = require("./transformers/style-object");
11
12
  var create = function create(context) {
12
13
  var config = (0, _config.getConfig)(context.options[0]);
13
- return {
14
- // const styles = css({ fontSize: '14px, ... }), styled.div({ fontSize: 14, ... })
15
- ObjectExpression: (0, _errorBoundary.errorBoundary)(function (node) {
14
+ return (0, _errorBoundary.errorBoundary)({
15
+ // const styles = css({ fontSize: '14px', ... }), styled.div({ fontSize: 14, ... })
16
+ ObjectExpression: function ObjectExpression(node) {
16
17
  return _styleObject.StyleObject.lint(node, {
17
18
  context: context,
18
19
  config: config
19
20
  });
20
- }, config)
21
- };
21
+ },
22
+ // const styles = css({ fontWeight: 600, 'bold', ... })
23
+ 'ObjectExpression > Property > Identifier[name=/fontWeight/]': function ObjectExpressionPropertyIdentifierNameFontWeight(node) {
24
+ return _fontWeight.FontWeight.lint(node, {
25
+ context: context,
26
+ config: config
27
+ });
28
+ }
29
+ }, config);
22
30
  };
23
31
  var rule = (0, _createRule.createLintRule)({
24
32
  meta: {
@@ -32,7 +40,8 @@ var rule = (0, _createRule.createLintRule)({
32
40
  severity: 'warn'
33
41
  },
34
42
  messages: {
35
- noRawTypographyValues: 'Typography primitives or tokens should be used instead of hard-coded values.\n\n@meta <<{{payload}}>>.\n\nNOTE: Using tokens with the `fontSize` property is invalid. Any `font.heading` or `font.body` tokens must use the CSS `font` property.'
43
+ noRawTypographyValues: 'Typography primitives or tokens should be used instead of hard-coded values.\n\n@meta <<{{payload}}>>.\n\nNOTE: Using tokens with the `fontSize` property is invalid. Any `font.heading` or `font.body` tokens must use the CSS `font` property.',
44
+ noRawFontWeightValues: 'Font weight tokens should be used instead of hard-coded values.'
36
45
  },
37
46
  schema: _config.ruleSchema
38
47
  },
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FontWeight = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _astNodes = require("../../../ast-nodes");
9
+ var _utils = require("../../ensure-design-token-usage/utils");
10
+ var _isNode = require("../../utils/is-node");
11
+ var _utils2 = require("../utils");
12
+ /* eslint-disable @repo/internal/react/require-jsdoc */
13
+
14
+ var FontWeight = exports.FontWeight = {
15
+ lint: function lint(node, _ref) {
16
+ var context = _ref.context,
17
+ config = _ref.config;
18
+ // To force the correct node type
19
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'Identifier')) {
20
+ return;
21
+ }
22
+
23
+ // Check whether all criteria needed to make a transformation are met
24
+ var success = FontWeight._check(node, {
25
+ context: context,
26
+ config: config
27
+ });
28
+ if (success) {
29
+ return context.report({
30
+ node: node,
31
+ messageId: 'noRawFontWeightValues',
32
+ fix: FontWeight._fix(node, context)
33
+ });
34
+ }
35
+ },
36
+ _check: function _check(node, _ref2) {
37
+ var context = _ref2.context,
38
+ config = _ref2.config;
39
+ if (!config.patterns.includes('font-weight')) {
40
+ return false;
41
+ }
42
+ if (!(0, _isNode.isDecendantOfStyleBlock)(node) && !(0, _isNode.isDecendantOfType)(node, 'JSXExpressionContainer')) {
43
+ return false;
44
+ }
45
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'Property')) {
46
+ return false;
47
+ }
48
+ var fontWeightValue = (0, _utils.getValueForPropertyNode)(node.parent, context);
49
+ if (typeof fontWeightValue === 'string' && fontWeightValue.includes('font.weight.')) {
50
+ return false;
51
+ }
52
+ return true;
53
+ },
54
+ _fix: function _fix(node, context) {
55
+ return function (fixer) {
56
+ var _findFontWeightTokenF;
57
+ var fixes = [];
58
+
59
+ // -- Type assertions to force the correct node type --
60
+
61
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'Property')) {
62
+ return [];
63
+ }
64
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.parent.value, 'Literal')) {
65
+ return [];
66
+ }
67
+ if (!node.parent.value.raw) {
68
+ return [];
69
+ }
70
+
71
+ // -- Fix: Replace raw value with token --
72
+
73
+ var matchingToken = (_findFontWeightTokenF = (0, _utils2.findFontWeightTokenForValue)(node.parent.value.raw)) === null || _findFontWeightTokenF === void 0 ? void 0 : _findFontWeightTokenF.tokenName;
74
+ if (!matchingToken) {
75
+ return [];
76
+ }
77
+ var fontWeightValueFix = fixer.replaceText(node.parent.value, "token('".concat(matchingToken, "')"));
78
+ fixes.push(fontWeightValueFix);
79
+
80
+ // -- Fix: Add import if it doesn't exist --
81
+
82
+ var body = context.sourceCode.ast.body;
83
+ var tokensImportDeclarations = _astNodes.Root.findImportsByModule(body, '@atlaskit/tokens');
84
+
85
+ // If there is more than one `@atlaskit/tokens` import, then it becomes difficult to determine which import to transform
86
+ if (tokensImportDeclarations.length > 1) {
87
+ return fixes;
88
+ }
89
+ var tokensImportDeclaration = tokensImportDeclarations[0];
90
+ if (!tokensImportDeclaration) {
91
+ fixes.push((0, _utils2.insertTokensImport)(body, fixer));
92
+ }
93
+ return fixes;
94
+ };
95
+ }
96
+ };
@@ -204,6 +204,11 @@ var StyleObject = exports.StyleObject = {
204
204
  _check: function _check(node, _ref2) {
205
205
  var context = _ref2.context,
206
206
  config = _ref2.config;
207
+ if (!config.patterns.includes('style-object')) {
208
+ return {
209
+ success: false
210
+ };
211
+ }
207
212
  if (!(0, _isNode.isDecendantOfStyleBlock)(node) && !(0, _isNode.isDecendantOfType)(node, 'JSXExpressionContainer')) {
208
213
  return {
209
214
  success: false
@@ -99,6 +99,12 @@ var fontWeightTokens = exports.fontWeightTokens = _tokensRaw.typographyAdg3.filt
99
99
  };
100
100
  });
101
101
  function findFontWeightTokenForValue(fontWeight) {
102
+ if (fontWeight === "'normal'") {
103
+ fontWeight = '400';
104
+ }
105
+ if (fontWeight === "'bold'") {
106
+ fontWeight = '700';
107
+ }
102
108
  return fontWeightTokens.find(function (token) {
103
109
  return token.tokenValue === fontWeight;
104
110
  });
@@ -1,33 +1,30 @@
1
- import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils';
2
- import { createRule } from '../utils/create-rule';
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import { createLintRule } from '../utils/create-rule';
3
3
  import { getConfig } from '../utils/get-deprecated-config';
4
4
  import { isDeprecatedJSXAttributeConfig } from '../utils/types';
5
5
  export const noDeprecatedJSXAttributeMessageId = 'noDeprecatedJSXAttributes';
6
- const isNodeOfType = (node, nodeType) => ASTUtils.isNodeOfType(nodeType)(node);
7
6
  const isImportDeclaration = programStatement => {
8
7
  return (programStatement === null || programStatement === void 0 ? void 0 : programStatement.type) === 'ImportDeclaration';
9
8
  };
10
9
  const findJSXElementName = jsxAttributeNode => {
11
- if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode.parent, AST_NODE_TYPES.JSXOpeningElement)) {
10
+ if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode === null || jsxAttributeNode === void 0 ? void 0 : jsxAttributeNode.parent, 'JSXOpeningElement')) {
12
11
  return;
13
12
  }
14
13
  const openingElement = jsxAttributeNode.parent;
15
- if (!isNodeOfType(openingElement.name, AST_NODE_TYPES.JSXIdentifier)) {
14
+ if (!isNodeOfType(openingElement.name, 'JSXIdentifier')) {
16
15
  return;
17
16
  }
18
17
  return openingElement.name.name;
19
18
  };
20
19
  export const name = 'no-deprecated-apis';
21
- const rule = createRule({
22
- name,
23
- defaultOptions: [{
24
- deprecatedConfig: getConfig('jsxAttributes')
25
- }],
20
+ const rule = createLintRule({
26
21
  meta: {
22
+ name,
27
23
  type: 'suggestion',
28
24
  docs: {
29
25
  description: 'Disallow using deprecated APIs.',
30
- recommended: 'strict'
26
+ recommended: true,
27
+ severity: 'error'
31
28
  },
32
29
  messages: {
33
30
  noDeprecatedJSXAttributes: 'The JSX attribute {{propName}} has been deprecated.'
@@ -65,24 +62,18 @@ const rule = createRule({
65
62
  }
66
63
  }]
67
64
  },
68
- create(context, [options]) {
65
+ create(context) {
69
66
  var _context$options$;
70
- // Get rule configuration
71
- const {
72
- deprecatedConfig: defaultDeprecatedConfig
73
- } = options;
74
-
75
67
  // Get the rule configuration specified otherwise use default config.
76
68
  // A bit confusing as it seems that the default options have precedence over the user specified options.
77
- const deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || defaultDeprecatedConfig;
69
+ const deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || getConfig('jsxAttributes');
78
70
  return {
79
71
  // find JSX atribute - find name of attribute - get source and find relevant identifiers.
80
72
  JSXAttribute(node) {
81
- const jsxAttributeIdentifier = node.name;
82
- if (!isNodeOfType(jsxAttributeIdentifier, AST_NODE_TYPES.JSXIdentifier)) {
73
+ if (!isNodeOfType(node, 'JSXAttribute') || !isNodeOfType(node.name, 'JSXIdentifier')) {
83
74
  return;
84
75
  }
85
- const jsxAttributeName = jsxAttributeIdentifier.name;
76
+ const jsxAttributeName = node.name.name;
86
77
  if (!isDeprecatedJSXAttributeConfig(deprecatedConfig) || !deprecatedConfig[jsxAttributeName]) {
87
78
  return;
88
79
  }
@@ -90,12 +81,12 @@ const rule = createRule({
90
81
  if (!jsxElementName) {
91
82
  return;
92
83
  }
93
- const source = context.getSourceCode();
84
+ const source = context.sourceCode;
94
85
 
95
86
  // find an import for the path of the banned api
96
87
  deprecatedConfig[jsxAttributeName].forEach(importItem => {
97
88
  var _importItem$namedSpec;
98
- const importNode = source.ast.body.filter(isImportDeclaration).find(node => node.source.value.includes(importItem.moduleSpecifier));
89
+ const importNode = source.ast.body.filter(isImportDeclaration).find(node => node && node.source.value && typeof node.source.value === 'string' && node.source.value.includes(importItem.moduleSpecifier));
99
90
  if (!importNode) {
100
91
  return;
101
92
  }
@@ -1,7 +1,7 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
2
  import { addToListOfRanges, canAutoMigrateNewIconBasedOnSize, canMigrateColor, createAutoMigrationError, createCantFindSuitableReplacementError, createCantMigrateColorError, createCantMigrateFunctionUnknownError, createCantMigrateIdentifierError, createCantMigrateIdentifierMapOrArrayError, createCantMigrateReExportError, createCantMigrateSizeUnknown, createCantMigrateSpreadPropsError, createGuidance, createHelpers, getMigrationMapObject, getUpcomingIcons, isInsideLegacyButton, isInsideNewButton, isSize, locToString, throwAutoErrors, throwManualErrors } from './helpers';
3
3
  export const createChecks = context => {
4
- //create global variables to be shared by the checks
4
+ // Create global variables to be shared by the checks
5
5
  const {
6
6
  getPrimaryColor,
7
7
  getConfigFlag
@@ -19,6 +19,7 @@ export const createChecks = context => {
19
19
  const shouldErrorForAutoMigration = getConfigFlag('shouldErrorForAutoMigration', true);
20
20
  const isQuietMode = getConfigFlag('quiet', false);
21
21
  const shouldUseMigrationPath = getConfigFlag('shouldUseMigrationPath', true);
22
+ const shouldUseSafeMigrationMode = getConfigFlag('shouldUseSafeMigrationMode', false);
22
23
 
23
24
  // Sorted list of ranges
24
25
  let errorRanges = [];
@@ -334,10 +335,11 @@ export const createChecks = context => {
334
335
  // Find size prop on node
335
336
  let size = 'medium';
336
337
  let primaryColor = null;
338
+ let hasPrimaryColorProp = false;
339
+ let hasSecondaryColorProp = false;
337
340
  let afterSpreadSet = new Set();
338
341
  let requiredAttributesAfterSpread = new Set(['size', 'primaryColor', 'secondaryColor']);
339
342
  let hasSpread = false;
340
- let hasPrimaryColorProp = false;
341
343
  for (const attr of node.openingElement.attributes) {
342
344
  // Detect spread props
343
345
  if (isNodeOfType(attr, 'JSXSpreadAttribute')) {
@@ -368,9 +370,14 @@ export const createChecks = context => {
368
370
  primaryColor = getPrimaryColor(attr);
369
371
  hasPrimaryColorProp = true;
370
372
  break;
373
+ case 'secondaryColor':
374
+ hasSecondaryColorProp = true;
375
+ break;
371
376
  }
372
377
  }
373
378
  let hasManualMigration = false;
379
+
380
+ // Flag manual migration if primary color cannot be migrated
374
381
  if (primaryColor && !canMigrateColor(primaryColor) || hasPrimaryColorProp && !primaryColor) {
375
382
  createCantMigrateColorError(node, primaryColor ? `the value of '${primaryColor}'` : 'a statically unknown value', errorsManual, legacyIconImports[name].packageName, name);
376
383
  hasManualMigration = true;
@@ -382,12 +389,14 @@ export const createChecks = context => {
382
389
  createCantMigrateSizeUnknown(node, errorsManual, legacyIconImports[name].packageName, name);
383
390
  hasManualMigration = true;
384
391
  }
392
+
385
393
  // Do a set comparison - is requiredAttributesAfterSpread a subset of afterSpreadSet?
386
394
  if (hasSpread === true && !Array.from(requiredAttributesAfterSpread).every(val => afterSpreadSet.has(val)) && !insideNewButton) {
387
395
  const missingProps = Array.from(requiredAttributesAfterSpread).filter(val => !afterSpreadSet.has(val));
388
396
  createCantMigrateSpreadPropsError(node, missingProps, errorsManual, legacyIconImports[name].packageName, name);
389
397
  hasManualMigration = true;
390
398
  }
399
+
391
400
  // Check if it is an exported component?
392
401
  if (legacyIconImports[name].exported) {
393
402
  createCantMigrateReExportError(node, legacyIconImports[name].packageName, name, errorsManual);
@@ -415,7 +424,9 @@ export const createChecks = context => {
415
424
  spacing = 'spacious';
416
425
  }
417
426
  }
418
- if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
427
+ if (shouldUseSafeMigrationMode && !hasManualMigration && (newIcon !== null && newIcon !== void 0 && newIcon.isMigrationUnsafe || size !== 'medium' || hasSecondaryColorProp)) {
428
+ createCantFindSuitableReplacementError(node, legacyIconImports[name].packageName, name, errorsManual, upcomingIcon ? true : migrationMapObject ? true : false);
429
+ } else if (!hasManualMigration && (newIcon || upcomingIcon) && isNewIconMigratable) {
419
430
  createAutoMigrationError({
420
431
  node,
421
432
  importSource: legacyIconImports[name].packageName,
@@ -462,8 +462,7 @@ const createPropFixes = ({
462
462
  }) => {
463
463
  const fixes = [];
464
464
  const {
465
- spacing,
466
- insideNewButton
465
+ spacing
467
466
  } = metadata;
468
467
  if (shouldUseMigrationPath && !legacyImportNode) {
469
468
  return fixes;
@@ -485,16 +484,6 @@ const createPropFixes = ({
485
484
  fixes.push(fixer.replaceText(primaryColor.name, 'color'));
486
485
  }
487
486
 
488
- // add color="currentColor" if
489
- // 1. primaryColor prop is not set
490
- // 2. icon is not imported from migration entrypoint
491
- // 3. icon element is not inside a new button
492
- if (legacyImportNode && !primaryColor && !migrationImportNode &&
493
- // value type need to be a string in Rule.ReportDescriptor
494
- insideNewButton !== 'true') {
495
- fixes.push(fixer.insertTextAfter(openingElement.name, ` color="currentColor"`));
496
- }
497
-
498
487
  // rename or remove size prop based on shouldUseMigrationPath,
499
488
  // add spacing="spacious" if
500
489
  // 1. it's in error metadata, which means size is medium
@@ -611,10 +600,10 @@ export const throwAutoErrors = ({
611
600
  }
612
601
  return result;
613
602
  }, new Set());
614
- //group errors by import source and remove any unwanted errors
603
+ // Group errors by import source and remove any unwanted errors
615
604
  const groupedErrorList = Object.entries(errorsAuto).reduce((result, option) => {
616
605
  const [key, error] = option;
617
- //return early if no data
606
+ // Return early if no data
618
607
  if (!error.data) {
619
608
  return result;
620
609
  }
@@ -22,6 +22,9 @@ const rule = createLintRule({
22
22
  shouldErrorForAutoMigration: {
23
23
  type: 'boolean'
24
24
  },
25
+ shouldUseSafeMigrationMode: {
26
+ type: 'boolean'
27
+ },
25
28
  quiet: {
26
29
  type: 'boolean'
27
30
  },