@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.
- package/CHANGELOG.md +39 -0
- package/dist/cjs/rules/no-deprecated-apis/index.js +13 -26
- package/dist/cjs/rules/no-legacy-icons/checks.js +14 -3
- package/dist/cjs/rules/no-legacy-icons/helpers.js +3 -14
- package/dist/cjs/rules/no-legacy-icons/index.js +3 -0
- package/dist/cjs/rules/use-tokens-typography/config/index.js +2 -1
- package/dist/cjs/rules/use-tokens-typography/index.js +15 -6
- package/dist/cjs/rules/use-tokens-typography/transformers/font-weight.js +96 -0
- package/dist/cjs/rules/use-tokens-typography/transformers/style-object.js +5 -0
- package/dist/cjs/rules/use-tokens-typography/utils.js +6 -0
- package/dist/es2019/rules/no-deprecated-apis/index.js +14 -23
- package/dist/es2019/rules/no-legacy-icons/checks.js +14 -3
- package/dist/es2019/rules/no-legacy-icons/helpers.js +3 -14
- package/dist/es2019/rules/no-legacy-icons/index.js +3 -0
- package/dist/es2019/rules/use-tokens-typography/config/index.js +2 -1
- package/dist/es2019/rules/use-tokens-typography/index.js +13 -6
- package/dist/es2019/rules/use-tokens-typography/transformers/font-weight.js +92 -0
- package/dist/es2019/rules/use-tokens-typography/transformers/style-object.js +5 -0
- package/dist/es2019/rules/use-tokens-typography/utils.js +6 -0
- package/dist/esm/rules/no-deprecated-apis/index.js +14 -26
- package/dist/esm/rules/no-legacy-icons/checks.js +14 -3
- package/dist/esm/rules/no-legacy-icons/helpers.js +3 -14
- package/dist/esm/rules/no-legacy-icons/index.js +3 -0
- package/dist/esm/rules/use-tokens-typography/config/index.js +2 -1
- package/dist/esm/rules/use-tokens-typography/index.js +15 -6
- package/dist/esm/rules/use-tokens-typography/transformers/font-weight.js +90 -0
- package/dist/esm/rules/use-tokens-typography/transformers/style-object.js +5 -0
- package/dist/esm/rules/use-tokens-typography/utils.js +6 -0
- package/dist/types/index.codegen.d.ts +3 -9
- package/dist/types/rules/index.codegen.d.ts +1 -3
- package/dist/types/rules/no-deprecated-apis/index.d.ts +2 -4
- package/dist/types/rules/no-legacy-icons/helpers.d.ts +1 -0
- package/dist/types/rules/use-tokens-typography/config/index.d.ts +3 -0
- package/dist/types/rules/use-tokens-typography/transformers/font-weight.d.ts +13 -0
- package/dist/types-ts4.5/index.codegen.d.ts +3 -15
- package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -5
- package/dist/types-ts4.5/rules/no-deprecated-apis/index.d.ts +2 -6
- package/dist/types-ts4.5/rules/no-legacy-icons/helpers.d.ts +1 -0
- package/dist/types-ts4.5/rules/use-tokens-typography/config/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/use-tokens-typography/transformers/font-weight.d.ts +13 -0
- 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
|
|
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,
|
|
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,
|
|
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.
|
|
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:
|
|
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
|
|
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) ||
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
//
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
634
|
+
// Return early if no data
|
|
646
635
|
if (!error.data) {
|
|
647
636
|
return result;
|
|
648
637
|
}
|
|
@@ -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:
|
|
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
|
-
},
|
|
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 {
|
|
2
|
-
import {
|
|
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,
|
|
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,
|
|
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 =
|
|
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:
|
|
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
|
|
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) ||
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
//
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
606
|
+
// Return early if no data
|
|
618
607
|
if (!error.data) {
|
|
619
608
|
return result;
|
|
620
609
|
}
|