@atlaskit/eslint-plugin-design-system 8.19.1 → 8.20.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 +16 -0
- package/constellation/index/usage.mdx +1 -1
- package/dist/cjs/rules/consistent-css-prop-usage/index.js +13 -4
- package/dist/cjs/rules/use-primitives/config/index.js +1 -1
- package/dist/cjs/rules/use-primitives/index.js +5 -6
- package/dist/cjs/rules/use-primitives/transformers/css-to-xcss.js +21 -7
- package/dist/cjs/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +32 -19
- package/dist/cjs/rules/use-primitives/utils/find-valid-styled-component-call.js +1 -0
- package/dist/cjs/rules/use-primitives/utils/get-variable-usage-count.js +1 -0
- package/dist/cjs/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +32 -8
- package/dist/es2019/rules/consistent-css-prop-usage/index.js +12 -4
- package/dist/es2019/rules/use-primitives/config/index.js +1 -1
- package/dist/es2019/rules/use-primitives/index.js +5 -6
- package/dist/es2019/rules/use-primitives/transformers/css-to-xcss.js +21 -7
- package/dist/es2019/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +31 -19
- package/dist/es2019/rules/use-primitives/utils/find-valid-styled-component-call.js +1 -0
- package/dist/es2019/rules/use-primitives/utils/get-variable-usage-count.js +1 -0
- package/dist/es2019/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +27 -8
- package/dist/esm/rules/consistent-css-prop-usage/index.js +13 -4
- package/dist/esm/rules/use-primitives/config/index.js +1 -1
- package/dist/esm/rules/use-primitives/index.js +5 -6
- package/dist/esm/rules/use-primitives/transformers/css-to-xcss.js +21 -7
- package/dist/esm/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +31 -19
- package/dist/esm/rules/use-primitives/utils/find-valid-styled-component-call.js +1 -0
- package/dist/esm/rules/use-primitives/utils/get-variable-usage-count.js +1 -0
- package/dist/esm/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +31 -8
- package/dist/types/rules/use-primitives/config/index.d.ts +3 -1
- package/dist/types/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts +11 -2
- package/dist/types/rules/use-primitives/utils/get-variable-usage-count.d.ts +1 -0
- package/dist/types/rules/use-primitives/utils/is-valid-css-properties-to-transform.d.ts +2 -1
- package/dist/types-ts4.5/rules/use-primitives/config/index.d.ts +3 -1
- package/dist/types-ts4.5/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts +11 -2
- package/dist/types-ts4.5/rules/use-primitives/utils/get-variable-usage-count.d.ts +1 -0
- package/dist/types-ts4.5/rules/use-primitives/utils/is-valid-css-properties-to-transform.d.ts +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-design-system
|
|
2
2
|
|
|
3
|
+
## 8.20.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#66409](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/66409) [`f6c48f4a67c1`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/f6c48f4a67c1) - Implemented functionality for the consistent-css-prop-usage rule to account for cssMap usages
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#66604](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/66604) [`3205b1daf57f`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/3205b1daf57f) - Refactor internal logic of `use-primitives` to better handle cases it will not suggest transformations for, based on the value of CSS properties.
|
|
12
|
+
|
|
13
|
+
## 8.19.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#66118](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/66118) [`93988e6fd035`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/93988e6fd035) - `use-primitives` now handles tokenised padding/margin properties. This change is guarded by a config flag and not enabled by default.
|
|
18
|
+
|
|
3
19
|
## 8.19.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -142,7 +142,7 @@ This rule comes with options to support different repository configurations.
|
|
|
142
142
|
|
|
143
143
|
#### cssFunctions
|
|
144
144
|
|
|
145
|
-
An array of function names the linting rule should target. Defaults to `['css', 'xcss']`.
|
|
145
|
+
An array of function names the linting rule should target. Defaults to `['css', 'xcss']`. Functionality of cssMap will be linted regardless of the configuration of `cssFunctions` as it can be used with either attribute.
|
|
146
146
|
|
|
147
147
|
#### stylesPlacement
|
|
148
148
|
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.default = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
10
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
11
|
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
11
12
|
var _assign = _interopRequireDefault(require("lodash/assign"));
|
|
@@ -25,9 +26,9 @@ function findSpreadProperties(node) {
|
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
28
|
-
var _getIdentifierInParen;
|
|
29
|
+
var _getIdentifierInParen, _getIdentifierInParen2;
|
|
29
30
|
var scope = context.getScope();
|
|
30
|
-
var _ref = (
|
|
31
|
+
var _ref = (_getIdentifierInParen = (_getIdentifierInParen2 = (0, _eslintCodemodUtils.getIdentifierInParentScope)(scope, sourceIdentifier.name)) === null || _getIdentifierInParen2 === void 0 ? void 0 : _getIdentifierInParen2.identifiers) !== null && _getIdentifierInParen !== void 0 ? _getIdentifierInParen : [],
|
|
31
32
|
_ref2 = (0, _slicedToArray2.default)(_ref, 1),
|
|
32
33
|
identifier = _ref2[0];
|
|
33
34
|
if (!identifier || !identifier.parent) {
|
|
@@ -50,7 +51,7 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
50
51
|
});
|
|
51
52
|
return;
|
|
52
53
|
}
|
|
53
|
-
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, configuration.cssFunctions)) {
|
|
54
|
+
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, [].concat((0, _toConsumableArray2.default)(configuration.cssFunctions), ['cssMap']))) {
|
|
54
55
|
// When variable value is not of type css({})
|
|
55
56
|
context.report({
|
|
56
57
|
node: identifier,
|
|
@@ -69,6 +70,13 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Handle different cases based on what's been passed in the css-related JSXAttribute
|
|
76
|
+
* @param context the context of the node
|
|
77
|
+
* @param expression the expression of the JSXAttribute value
|
|
78
|
+
* @param configuration what css-related functions to account for (eg. css, xcss, cssMap), and whether to detect bottom vs top expressions
|
|
79
|
+
*/
|
|
72
80
|
var traverseExpressionWithConfig = function traverseExpressionWithConfig(context, expression, configuration) {
|
|
73
81
|
function traverseExpression(expression) {
|
|
74
82
|
switch (expression.type) {
|
|
@@ -140,7 +148,8 @@ var rule = (0, _createRule.createLintRule)({
|
|
|
140
148
|
create: function create(context) {
|
|
141
149
|
var _ref3;
|
|
142
150
|
var mergedConfig = (0, _assign.default)({}, defaultConfig, context.options[0]);
|
|
143
|
-
var
|
|
151
|
+
var callSelectorFunctions = [].concat((0, _toConsumableArray2.default)(mergedConfig.cssFunctions), ['cssMap']);
|
|
152
|
+
var callSelector = callSelectorFunctions.map(function (fn) {
|
|
144
153
|
return "CallExpression[callee.name=".concat(fn, "]");
|
|
145
154
|
}).join(',');
|
|
146
155
|
return _ref3 = {}, (0, _defineProperty2.default)(_ref3, callSelector, function (node) {
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getConfig = void 0;
|
|
7
7
|
var defaults = {
|
|
8
|
-
patterns: ['
|
|
8
|
+
patterns: ['compiled-css-function']
|
|
9
9
|
};
|
|
10
10
|
var getConfig = exports.getConfig = function getConfig(overrides) {
|
|
11
11
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
|
|
@@ -37,7 +37,7 @@ var rule = (0, _createRule.createLintRule)({
|
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
var styledComponentVariableRef = (0, _utils.findValidStyledComponentCall)(node);
|
|
40
|
-
if (!styledComponentVariableRef || !(0, _eslintCodemodUtils.isNodeOfType)(styledComponentVariableRef.id, 'Identifier') || !(0, _utils.isValidCssPropertiesToTransform)(node)) {
|
|
40
|
+
if (!styledComponentVariableRef || !(0, _eslintCodemodUtils.isNodeOfType)(styledComponentVariableRef.id, 'Identifier') || !(0, _utils.isValidCssPropertiesToTransform)(node, config)) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
var styledComponentJsxRef = (0, _utils.findValidJsxUsageToTransform)(styledComponentVariableRef.id.name, context.getScope());
|
|
@@ -60,7 +60,9 @@ var rule = (0, _createRule.createLintRule)({
|
|
|
60
60
|
},
|
|
61
61
|
// transforms <div css={...}> usages
|
|
62
62
|
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
63
|
-
|
|
63
|
+
if (!config.patterns.includes('compiled-css-function')) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
64
66
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
@@ -135,9 +137,6 @@ var shouldSuggestBox = function shouldSuggestBox(node, context, config
|
|
|
135
137
|
if (!cssVariableValue || !(0, _utils.isFunctionNamed)(cssVariableValue, 'css')) {
|
|
136
138
|
return false;
|
|
137
139
|
}
|
|
138
|
-
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
return (0, _utils.isValidCssPropertiesToTransform)(cssVariableValue.node.init);
|
|
140
|
+
return (0, _utils.isValidCssPropertiesToTransform)(cssVariableValue.node.init, config);
|
|
142
141
|
};
|
|
143
142
|
var _default = exports.default = rule;
|
|
@@ -39,7 +39,7 @@ var cssToXcssTransformer = exports.cssToXcssTransformer = function cssToXcssTran
|
|
|
39
39
|
fixer.replaceText(cssVariableValue.node.init.callee, (0, _eslintCodemodUtils.identifier)('xcss').toString())].concat((0, _toConsumableArray2.default)(styledObjectToXcssTokens(cssObjectExpression, fixer)));
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
// Update css object values to xcss values
|
|
42
|
+
// Update css object values to xcss values
|
|
43
43
|
// Note: `properties` in this context is a group of AST nodes that make up a key/value pair in an object.
|
|
44
44
|
// e.g. `padding: '8px'`. For clarity, it's renamed to `entry` inside the `.map()`.
|
|
45
45
|
var styledObjectToXcssTokens = exports.styledObjectToXcssTokens = function styledObjectToXcssTokens(styles, fixer) {
|
|
@@ -50,16 +50,30 @@ var styledObjectToXcssTokens = exports.styledObjectToXcssTokens = function style
|
|
|
50
50
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(entry.key, 'Identifier')) {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
|
|
54
|
+
// maps literal values like: 8px to 'space.100'
|
|
55
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(entry.value, 'Literal')) {
|
|
56
|
+
var value = entry.value.value;
|
|
57
|
+
if (typeof value !== 'string') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
return fixer.replaceText(entry.value, (0, _eslintCodemodUtils.literal)("'".concat(supportedStylesMap[entry.key.name][value], "'")).toString());
|
|
55
61
|
}
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
|
|
62
|
+
// maps token calls like: token('space.100') to 'space.100'
|
|
63
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(entry.value, 'CallExpression')) {
|
|
64
|
+
var callExpression = entry.value;
|
|
65
|
+
// skip if not a call to `token`
|
|
66
|
+
if (!(0, _eslintCodemodUtils.isNodeOfType)(callExpression.callee, 'Identifier') || callExpression.callee.name !== 'token' || !(0, _eslintCodemodUtils.isNodeOfType)(callExpression.arguments[0], 'Literal')) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// the first argument of `token` is the token name and
|
|
70
|
+
// can be given directly to `xcss` as it has been validated already.
|
|
71
|
+
return fixer.replaceText(entry.value, (0, _eslintCodemodUtils.literal)("'".concat(callExpression.arguments[0].value, "'")).toString());
|
|
59
72
|
}
|
|
60
|
-
return fixer.replaceText(entry.value, (0, _eslintCodemodUtils.literal)("'".concat(supportedStylesMap[entry.key.name][value], "'")).toString());
|
|
61
73
|
});
|
|
62
74
|
};
|
|
75
|
+
|
|
76
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-16054
|
|
63
77
|
var spaceTokenMap = exports.spaceTokenMap = {
|
|
64
78
|
'0px': 'space.0',
|
|
65
79
|
'2px': 'space.025',
|
|
@@ -3,31 +3,23 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.convertASTObjectExpressionToJSObject = void 0;
|
|
6
|
+
exports.convertASTObjectExpressionToJSObject = exports.SPREAD_SYNTAX = void 0;
|
|
7
7
|
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
var SPREAD_SYNTAX = exports.SPREAD_SYNTAX = Symbol('SPREAD_SYNTAX');
|
|
10
9
|
/**
|
|
11
10
|
* Note: Not recursive. Only handles top level key/value pairs
|
|
12
11
|
*/
|
|
13
12
|
var convertASTObjectExpressionToJSObject = exports.convertASTObjectExpressionToJSObject = function convertASTObjectExpressionToJSObject(styles) {
|
|
14
|
-
var styleObj = {
|
|
13
|
+
var styleObj = {
|
|
14
|
+
unsupported: []
|
|
15
|
+
};
|
|
15
16
|
|
|
16
|
-
// if we see any spread props we
|
|
17
|
+
// if we see any spread props we indicate that as unsupported
|
|
17
18
|
if (!styles.properties.every(function (prop) {
|
|
18
19
|
return (0, _eslintCodemodUtils.isNodeOfType)(prop, 'Property');
|
|
19
20
|
})) {
|
|
20
|
-
|
|
21
|
+
styleObj.unsupported.push(SPREAD_SYNTAX);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
// TODO: We need to harden this logic.
|
|
24
|
-
// It currently generates a false positive for:
|
|
25
|
-
// styled.div({
|
|
26
|
-
// marginTop: "0px",
|
|
27
|
-
// marginBottom: token("space.100", "8px"),
|
|
28
|
-
// })
|
|
29
|
-
// as the value for `marginBottom` is not a string, so it is just skipped
|
|
30
|
-
// from the resulting map and this causes the rule to trigger when it shouldn't
|
|
31
23
|
styles.properties.forEach(function (prop) {
|
|
32
24
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(prop, 'Property')) {
|
|
33
25
|
return;
|
|
@@ -35,13 +27,34 @@ var convertASTObjectExpressionToJSObject = exports.convertASTObjectExpressionToJ
|
|
|
35
27
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(prop.key, 'Identifier')) {
|
|
36
28
|
return;
|
|
37
29
|
}
|
|
38
|
-
|
|
30
|
+
|
|
31
|
+
// a literal string value, the base case
|
|
32
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'Literal') && typeof prop.value.value === 'string') {
|
|
33
|
+
styleObj[prop.key.name] = prop.value.value;
|
|
39
34
|
return;
|
|
40
35
|
}
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
|
|
37
|
+
// try to handle a direct call to `token`
|
|
38
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'CallExpression')) {
|
|
39
|
+
var callExpression = prop.value;
|
|
40
|
+
// strictly handle calls to `token`
|
|
41
|
+
if ((0, _eslintCodemodUtils.isNodeOfType)(callExpression.callee, 'Identifier') && callExpression.callee.name === 'token') {
|
|
42
|
+
// only two valid cases are supported
|
|
43
|
+
// one argument => token('space.100')
|
|
44
|
+
// two arguments => token('space.100', '8px')
|
|
45
|
+
if ((callExpression.arguments.length === 1 || callExpression.arguments.length === 2) && (0, _eslintCodemodUtils.isNodeOfType)(callExpression.arguments[0], 'Literal') && (typeof callExpression.arguments[1] === 'undefined' || (0, _eslintCodemodUtils.isNodeOfType)(callExpression.arguments[1], 'Literal'))) {
|
|
46
|
+
var _callExpression$argum;
|
|
47
|
+
styleObj[prop.key.name] = {
|
|
48
|
+
tokenName: String(callExpression.arguments[0].value),
|
|
49
|
+
fallbackValue: (_callExpression$argum = callExpression.arguments[1]) !== null && _callExpression$argum !== void 0 && _callExpression$argum.value ? String(callExpression.arguments[1].value) : undefined
|
|
50
|
+
};
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
43
54
|
}
|
|
44
|
-
|
|
55
|
+
|
|
56
|
+
// if we get here we have an unsupported value
|
|
57
|
+
styleObj.unsupported.push(prop.key.name);
|
|
45
58
|
});
|
|
46
59
|
return styleObj;
|
|
47
60
|
};
|
|
@@ -34,6 +34,7 @@ var findValidStyledComponentCall = exports.findValidStyledComponentCall = functi
|
|
|
34
34
|
*
|
|
35
35
|
* In the future it could be enhanced to double check `styled` and `styled2`
|
|
36
36
|
* are Compiled imports but as is should work for the majority of use cases
|
|
37
|
+
* https://product-fabric.atlassian.net/browse/DSP-16058
|
|
37
38
|
*/
|
|
38
39
|
var isStyledCallExpression = function isStyledCallExpression(call) {
|
|
39
40
|
if (!(0, _eslintCodemodUtils.isNodeOfType)(call, 'CallExpression')) {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getVariableUsagesCount = void 0;
|
|
7
7
|
/**
|
|
8
|
+
* TODO: Update this logic: https://product-fabric.atlassian.net/browse/DSP-16059
|
|
8
9
|
* Using Regex here because otherwise we'd need to traverse the entire AST
|
|
9
10
|
* We should harden this logic as we go.
|
|
10
11
|
*/
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
7
|
exports.isValidCssPropertiesToTransform = void 0;
|
|
8
|
+
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
9
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
7
10
|
var _eslintCodemodUtils = require("eslint-codemod-utils");
|
|
8
11
|
var _cssToXcss = require("../transformers/css-to-xcss");
|
|
9
12
|
var _convertAstObjectExpressionToJsObject = require("./convert-ast-object-expression-to-js-object");
|
|
10
|
-
var
|
|
13
|
+
var _excluded = ["unsupported"];
|
|
14
|
+
var isValidCssPropertiesToTransform = exports.isValidCssPropertiesToTransform = function isValidCssPropertiesToTransform(node, config) {
|
|
11
15
|
var cssObjectExpression = node.arguments[0];
|
|
12
16
|
// Bail on empty object calls
|
|
13
17
|
if (!cssObjectExpression || !(0, _eslintCodemodUtils.isNodeOfType)(cssObjectExpression, 'ObjectExpression')) {
|
|
14
18
|
return false;
|
|
15
19
|
}
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
var _convertASTObjectExpr = (0, _convertAstObjectExpressionToJsObject.convertASTObjectExpressionToJSObject)(cssObjectExpression),
|
|
21
|
+
unsupported = _convertASTObjectExpr.unsupported,
|
|
22
|
+
cssObject = (0, _objectWithoutProperties2.default)(_convertASTObjectExpr, _excluded);
|
|
23
|
+
// Bail if there are any unsupported styles
|
|
24
|
+
if (unsupported.length > 0 || Object.keys(cssObject).length !== 1) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// Short-circuit when token calls are found but pattern is not enabled in config
|
|
28
|
+
if (!config.patterns.includes('css-property-with-tokens') && Object.values(cssObject).some(function (value) {
|
|
29
|
+
return (0, _typeof2.default)(value) === 'object' && value.tokenName;
|
|
30
|
+
})) {
|
|
19
31
|
return false;
|
|
20
32
|
}
|
|
21
33
|
|
|
@@ -25,10 +37,22 @@ var isValidCssPropertiesToTransform = exports.isValidCssPropertiesToTransform =
|
|
|
25
37
|
// than the rule reporting on things that can't be mapped.
|
|
26
38
|
var containsOnlyValidStyles = Object.keys(cssObject).every(function (styleProperty) {
|
|
27
39
|
var styleValue = cssObject[styleProperty];
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
|
|
41
|
+
// token function call
|
|
42
|
+
if ((0, _typeof2.default)(styleValue) === 'object') {
|
|
43
|
+
// if there is no fallback value, we just map to the token name, if one is found
|
|
44
|
+
if (!styleValue.fallbackValue) {
|
|
45
|
+
return _cssToXcss.supportedStylesMap[styleProperty] && Object.values(_cssToXcss.supportedStylesMap[styleProperty]).includes(styleValue.tokenName);
|
|
46
|
+
}
|
|
47
|
+
// token with fallback
|
|
48
|
+
return _cssToXcss.supportedStylesMap[styleProperty] && _cssToXcss.supportedStylesMap[styleProperty][styleValue.fallbackValue] === styleValue.tokenName;
|
|
49
|
+
} else {
|
|
50
|
+
// direct value used
|
|
51
|
+
return _cssToXcss.supportedStylesMap[styleProperty] &&
|
|
52
|
+
// Is the key something we can map
|
|
53
|
+
_cssToXcss.supportedStylesMap[styleProperty][styleValue] // Is the value something we can map
|
|
54
|
+
;
|
|
55
|
+
}
|
|
32
56
|
});
|
|
33
57
|
|
|
34
58
|
if (!containsOnlyValidStyles) {
|
|
@@ -14,9 +14,9 @@ function findSpreadProperties(node) {
|
|
|
14
14
|
property.type === 'ExperimentalSpreadProperty');
|
|
15
15
|
}
|
|
16
16
|
function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
17
|
-
var _getIdentifierInParen;
|
|
17
|
+
var _getIdentifierInParen, _getIdentifierInParen2;
|
|
18
18
|
const scope = context.getScope();
|
|
19
|
-
const [identifier] = (
|
|
19
|
+
const [identifier] = (_getIdentifierInParen = (_getIdentifierInParen2 = getIdentifierInParentScope(scope, sourceIdentifier.name)) === null || _getIdentifierInParen2 === void 0 ? void 0 : _getIdentifierInParen2.identifiers) !== null && _getIdentifierInParen !== void 0 ? _getIdentifierInParen : [];
|
|
20
20
|
if (!identifier || !identifier.parent) {
|
|
21
21
|
// Identifier isn't in the module, skip!
|
|
22
22
|
return;
|
|
@@ -37,7 +37,7 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
37
37
|
});
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, configuration.cssFunctions)) {
|
|
40
|
+
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, [...configuration.cssFunctions, 'cssMap'])) {
|
|
41
41
|
// When variable value is not of type css({})
|
|
42
42
|
context.report({
|
|
43
43
|
node: identifier,
|
|
@@ -56,6 +56,13 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Handle different cases based on what's been passed in the css-related JSXAttribute
|
|
62
|
+
* @param context the context of the node
|
|
63
|
+
* @param expression the expression of the JSXAttribute value
|
|
64
|
+
* @param configuration what css-related functions to account for (eg. css, xcss, cssMap), and whether to detect bottom vs top expressions
|
|
65
|
+
*/
|
|
59
66
|
const traverseExpressionWithConfig = (context, expression, configuration) => {
|
|
60
67
|
function traverseExpression(expression) {
|
|
61
68
|
switch (expression.type) {
|
|
@@ -124,7 +131,8 @@ const rule = createLintRule({
|
|
|
124
131
|
},
|
|
125
132
|
create(context) {
|
|
126
133
|
const mergedConfig = assign({}, defaultConfig, context.options[0]);
|
|
127
|
-
const
|
|
134
|
+
const callSelectorFunctions = [...mergedConfig.cssFunctions, 'cssMap'];
|
|
135
|
+
const callSelector = callSelectorFunctions.map(fn => `CallExpression[callee.name=${fn}]`).join(',');
|
|
128
136
|
return {
|
|
129
137
|
[callSelector]: node => {
|
|
130
138
|
if (node.parent.type !== 'VariableDeclarator') {
|
|
@@ -31,7 +31,7 @@ const rule = createLintRule({
|
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
const styledComponentVariableRef = findValidStyledComponentCall(node);
|
|
34
|
-
if (!styledComponentVariableRef || !isNodeOfType(styledComponentVariableRef.id, 'Identifier') || !isValidCssPropertiesToTransform(node)) {
|
|
34
|
+
if (!styledComponentVariableRef || !isNodeOfType(styledComponentVariableRef.id, 'Identifier') || !isValidCssPropertiesToTransform(node, config)) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
const styledComponentJsxRef = findValidJsxUsageToTransform(styledComponentVariableRef.id.name, context.getScope());
|
|
@@ -54,7 +54,9 @@ const rule = createLintRule({
|
|
|
54
54
|
},
|
|
55
55
|
// transforms <div css={...}> usages
|
|
56
56
|
JSXOpeningElement(node) {
|
|
57
|
-
|
|
57
|
+
if (!config.patterns.includes('compiled-css-function')) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
58
60
|
if (!isNodeOfType(node, 'JSXOpeningElement')) {
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
@@ -129,9 +131,6 @@ const shouldSuggestBox = (node, context, config
|
|
|
129
131
|
if (!cssVariableValue || !isFunctionNamed(cssVariableValue, 'css')) {
|
|
130
132
|
return false;
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
return isValidCssPropertiesToTransform(cssVariableValue.node.init);
|
|
134
|
+
return isValidCssPropertiesToTransform(cssVariableValue.node.init, config);
|
|
136
135
|
};
|
|
137
136
|
export default rule;
|
|
@@ -31,7 +31,7 @@ export const cssToXcssTransformer = (node, context, fixer) => {
|
|
|
31
31
|
fixer.replaceText(cssVariableValue.node.init.callee, identifier('xcss').toString()), ...styledObjectToXcssTokens(cssObjectExpression, fixer)];
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
// Update css object values to xcss values
|
|
34
|
+
// Update css object values to xcss values
|
|
35
35
|
// Note: `properties` in this context is a group of AST nodes that make up a key/value pair in an object.
|
|
36
36
|
// e.g. `padding: '8px'`. For clarity, it's renamed to `entry` inside the `.map()`.
|
|
37
37
|
export const styledObjectToXcssTokens = (styles, fixer) => {
|
|
@@ -42,16 +42,30 @@ export const styledObjectToXcssTokens = (styles, fixer) => {
|
|
|
42
42
|
if (!isNodeOfType(entry.key, 'Identifier')) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
|
|
46
|
+
// maps literal values like: 8px to 'space.100'
|
|
47
|
+
if (isNodeOfType(entry.value, 'Literal')) {
|
|
48
|
+
const value = entry.value.value;
|
|
49
|
+
if (typeof value !== 'string') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
return fixer.replaceText(entry.value, literal(`'${supportedStylesMap[entry.key.name][value]}'`).toString());
|
|
47
53
|
}
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
54
|
+
// maps token calls like: token('space.100') to 'space.100'
|
|
55
|
+
if (isNodeOfType(entry.value, 'CallExpression')) {
|
|
56
|
+
const callExpression = entry.value;
|
|
57
|
+
// skip if not a call to `token`
|
|
58
|
+
if (!isNodeOfType(callExpression.callee, 'Identifier') || callExpression.callee.name !== 'token' || !isNodeOfType(callExpression.arguments[0], 'Literal')) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// the first argument of `token` is the token name and
|
|
62
|
+
// can be given directly to `xcss` as it has been validated already.
|
|
63
|
+
return fixer.replaceText(entry.value, literal(`'${callExpression.arguments[0].value}'`).toString());
|
|
51
64
|
}
|
|
52
|
-
return fixer.replaceText(entry.value, literal(`'${supportedStylesMap[entry.key.name][value]}'`).toString());
|
|
53
65
|
});
|
|
54
66
|
};
|
|
67
|
+
|
|
68
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-16054
|
|
55
69
|
export const spaceTokenMap = {
|
|
56
70
|
'0px': 'space.0',
|
|
57
71
|
'2px': 'space.025',
|
package/dist/es2019/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js
CHANGED
|
@@ -1,26 +1,17 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
-
|
|
3
|
-
// FIXME: This is only loosely typed
|
|
4
|
-
|
|
2
|
+
export const SPREAD_SYNTAX = Symbol('SPREAD_SYNTAX');
|
|
5
3
|
/**
|
|
6
4
|
* Note: Not recursive. Only handles top level key/value pairs
|
|
7
5
|
*/
|
|
8
6
|
export const convertASTObjectExpressionToJSObject = styles => {
|
|
9
|
-
const styleObj = {
|
|
7
|
+
const styleObj = {
|
|
8
|
+
unsupported: []
|
|
9
|
+
};
|
|
10
10
|
|
|
11
|
-
// if we see any spread props we
|
|
11
|
+
// if we see any spread props we indicate that as unsupported
|
|
12
12
|
if (!styles.properties.every(prop => isNodeOfType(prop, 'Property'))) {
|
|
13
|
-
|
|
13
|
+
styleObj.unsupported.push(SPREAD_SYNTAX);
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
// TODO: We need to harden this logic.
|
|
17
|
-
// It currently generates a false positive for:
|
|
18
|
-
// styled.div({
|
|
19
|
-
// marginTop: "0px",
|
|
20
|
-
// marginBottom: token("space.100", "8px"),
|
|
21
|
-
// })
|
|
22
|
-
// as the value for `marginBottom` is not a string, so it is just skipped
|
|
23
|
-
// from the resulting map and this causes the rule to trigger when it shouldn't
|
|
24
15
|
styles.properties.forEach(prop => {
|
|
25
16
|
if (!isNodeOfType(prop, 'Property')) {
|
|
26
17
|
return;
|
|
@@ -28,13 +19,34 @@ export const convertASTObjectExpressionToJSObject = styles => {
|
|
|
28
19
|
if (!isNodeOfType(prop.key, 'Identifier')) {
|
|
29
20
|
return;
|
|
30
21
|
}
|
|
31
|
-
|
|
22
|
+
|
|
23
|
+
// a literal string value, the base case
|
|
24
|
+
if (isNodeOfType(prop.value, 'Literal') && typeof prop.value.value === 'string') {
|
|
25
|
+
styleObj[prop.key.name] = prop.value.value;
|
|
32
26
|
return;
|
|
33
27
|
}
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
|
|
29
|
+
// try to handle a direct call to `token`
|
|
30
|
+
if (isNodeOfType(prop.value, 'CallExpression')) {
|
|
31
|
+
const callExpression = prop.value;
|
|
32
|
+
// strictly handle calls to `token`
|
|
33
|
+
if (isNodeOfType(callExpression.callee, 'Identifier') && callExpression.callee.name === 'token') {
|
|
34
|
+
// only two valid cases are supported
|
|
35
|
+
// one argument => token('space.100')
|
|
36
|
+
// two arguments => token('space.100', '8px')
|
|
37
|
+
if ((callExpression.arguments.length === 1 || callExpression.arguments.length === 2) && isNodeOfType(callExpression.arguments[0], 'Literal') && (typeof callExpression.arguments[1] === 'undefined' || isNodeOfType(callExpression.arguments[1], 'Literal'))) {
|
|
38
|
+
var _callExpression$argum;
|
|
39
|
+
styleObj[prop.key.name] = {
|
|
40
|
+
tokenName: String(callExpression.arguments[0].value),
|
|
41
|
+
fallbackValue: (_callExpression$argum = callExpression.arguments[1]) !== null && _callExpression$argum !== void 0 && _callExpression$argum.value ? String(callExpression.arguments[1].value) : undefined
|
|
42
|
+
};
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
|
-
|
|
47
|
+
|
|
48
|
+
// if we get here we have an unsupported value
|
|
49
|
+
styleObj.unsupported.push(prop.key.name);
|
|
38
50
|
});
|
|
39
51
|
return styleObj;
|
|
40
52
|
};
|
|
@@ -29,6 +29,7 @@ export const findValidStyledComponentCall = node => {
|
|
|
29
29
|
*
|
|
30
30
|
* In the future it could be enhanced to double check `styled` and `styled2`
|
|
31
31
|
* are Compiled imports but as is should work for the majority of use cases
|
|
32
|
+
* https://product-fabric.atlassian.net/browse/DSP-16058
|
|
32
33
|
*/
|
|
33
34
|
const isStyledCallExpression = call => {
|
|
34
35
|
if (!isNodeOfType(call, 'CallExpression')) {
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
2
|
import { supportedStylesMap } from '../transformers/css-to-xcss';
|
|
3
3
|
import { convertASTObjectExpressionToJSObject } from './convert-ast-object-expression-to-js-object';
|
|
4
|
-
export const isValidCssPropertiesToTransform = node => {
|
|
4
|
+
export const isValidCssPropertiesToTransform = (node, config) => {
|
|
5
5
|
const cssObjectExpression = node.arguments[0];
|
|
6
6
|
// Bail on empty object calls
|
|
7
7
|
if (!cssObjectExpression || !isNodeOfType(cssObjectExpression, 'ObjectExpression')) {
|
|
8
8
|
return false;
|
|
9
9
|
}
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const {
|
|
11
|
+
unsupported,
|
|
12
|
+
...cssObject
|
|
13
|
+
} = convertASTObjectExpressionToJSObject(cssObjectExpression);
|
|
14
|
+
// Bail if there are any unsupported styles
|
|
15
|
+
if (unsupported.length > 0 || Object.keys(cssObject).length !== 1) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
// Short-circuit when token calls are found but pattern is not enabled in config
|
|
19
|
+
if (!config.patterns.includes('css-property-with-tokens') && Object.values(cssObject).some(value => typeof value === 'object' && value.tokenName)) {
|
|
13
20
|
return false;
|
|
14
21
|
}
|
|
15
22
|
|
|
@@ -19,10 +26,22 @@ export const isValidCssPropertiesToTransform = node => {
|
|
|
19
26
|
// than the rule reporting on things that can't be mapped.
|
|
20
27
|
const containsOnlyValidStyles = Object.keys(cssObject).every(styleProperty => {
|
|
21
28
|
const styleValue = cssObject[styleProperty];
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
// token function call
|
|
31
|
+
if (typeof styleValue === 'object') {
|
|
32
|
+
// if there is no fallback value, we just map to the token name, if one is found
|
|
33
|
+
if (!styleValue.fallbackValue) {
|
|
34
|
+
return supportedStylesMap[styleProperty] && Object.values(supportedStylesMap[styleProperty]).includes(styleValue.tokenName);
|
|
35
|
+
}
|
|
36
|
+
// token with fallback
|
|
37
|
+
return supportedStylesMap[styleProperty] && supportedStylesMap[styleProperty][styleValue.fallbackValue] === styleValue.tokenName;
|
|
38
|
+
} else {
|
|
39
|
+
// direct value used
|
|
40
|
+
return supportedStylesMap[styleProperty] &&
|
|
41
|
+
// Is the key something we can map
|
|
42
|
+
supportedStylesMap[styleProperty][styleValue] // Is the value something we can map
|
|
43
|
+
;
|
|
44
|
+
}
|
|
26
45
|
});
|
|
27
46
|
|
|
28
47
|
if (!containsOnlyValidStyles) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
3
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
4
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
4
5
|
|
|
@@ -18,9 +19,9 @@ function findSpreadProperties(node) {
|
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
21
|
function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
21
|
-
var _getIdentifierInParen;
|
|
22
|
+
var _getIdentifierInParen, _getIdentifierInParen2;
|
|
22
23
|
var scope = context.getScope();
|
|
23
|
-
var _ref = (
|
|
24
|
+
var _ref = (_getIdentifierInParen = (_getIdentifierInParen2 = getIdentifierInParentScope(scope, sourceIdentifier.name)) === null || _getIdentifierInParen2 === void 0 ? void 0 : _getIdentifierInParen2.identifiers) !== null && _getIdentifierInParen !== void 0 ? _getIdentifierInParen : [],
|
|
24
25
|
_ref2 = _slicedToArray(_ref, 1),
|
|
25
26
|
identifier = _ref2[0];
|
|
26
27
|
if (!identifier || !identifier.parent) {
|
|
@@ -43,7 +44,7 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
43
44
|
});
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
|
-
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, configuration.cssFunctions)) {
|
|
47
|
+
if (identifier.parent && identifier.parent.init && !isCssCallExpression(identifier.parent.init, [].concat(_toConsumableArray(configuration.cssFunctions), ['cssMap']))) {
|
|
47
48
|
// When variable value is not of type css({})
|
|
48
49
|
context.report({
|
|
49
50
|
node: identifier,
|
|
@@ -62,6 +63,13 @@ function analyzeIdentifier(context, sourceIdentifier, configuration) {
|
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Handle different cases based on what's been passed in the css-related JSXAttribute
|
|
69
|
+
* @param context the context of the node
|
|
70
|
+
* @param expression the expression of the JSXAttribute value
|
|
71
|
+
* @param configuration what css-related functions to account for (eg. css, xcss, cssMap), and whether to detect bottom vs top expressions
|
|
72
|
+
*/
|
|
65
73
|
var traverseExpressionWithConfig = function traverseExpressionWithConfig(context, expression, configuration) {
|
|
66
74
|
function traverseExpression(expression) {
|
|
67
75
|
switch (expression.type) {
|
|
@@ -133,7 +141,8 @@ var rule = createLintRule({
|
|
|
133
141
|
create: function create(context) {
|
|
134
142
|
var _ref3;
|
|
135
143
|
var mergedConfig = assign({}, defaultConfig, context.options[0]);
|
|
136
|
-
var
|
|
144
|
+
var callSelectorFunctions = [].concat(_toConsumableArray(mergedConfig.cssFunctions), ['cssMap']);
|
|
145
|
+
var callSelector = callSelectorFunctions.map(function (fn) {
|
|
137
146
|
return "CallExpression[callee.name=".concat(fn, "]");
|
|
138
147
|
}).join(',');
|
|
139
148
|
return _ref3 = {}, _defineProperty(_ref3, callSelector, function (node) {
|
|
@@ -31,7 +31,7 @@ var rule = createLintRule({
|
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
var styledComponentVariableRef = findValidStyledComponentCall(node);
|
|
34
|
-
if (!styledComponentVariableRef || !isNodeOfType(styledComponentVariableRef.id, 'Identifier') || !isValidCssPropertiesToTransform(node)) {
|
|
34
|
+
if (!styledComponentVariableRef || !isNodeOfType(styledComponentVariableRef.id, 'Identifier') || !isValidCssPropertiesToTransform(node, config)) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
var styledComponentJsxRef = findValidJsxUsageToTransform(styledComponentVariableRef.id.name, context.getScope());
|
|
@@ -54,7 +54,9 @@ var rule = createLintRule({
|
|
|
54
54
|
},
|
|
55
55
|
// transforms <div css={...}> usages
|
|
56
56
|
JSXOpeningElement: function JSXOpeningElement(node) {
|
|
57
|
-
|
|
57
|
+
if (!config.patterns.includes('compiled-css-function')) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
58
60
|
if (!isNodeOfType(node, 'JSXOpeningElement')) {
|
|
59
61
|
return;
|
|
60
62
|
}
|
|
@@ -129,9 +131,6 @@ var shouldSuggestBox = function shouldSuggestBox(node, context, config
|
|
|
129
131
|
if (!cssVariableValue || !isFunctionNamed(cssVariableValue, 'css')) {
|
|
130
132
|
return false;
|
|
131
133
|
}
|
|
132
|
-
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
return isValidCssPropertiesToTransform(cssVariableValue.node.init);
|
|
134
|
+
return isValidCssPropertiesToTransform(cssVariableValue.node.init, config);
|
|
136
135
|
};
|
|
137
136
|
export default rule;
|
|
@@ -32,7 +32,7 @@ export var cssToXcssTransformer = function cssToXcssTransformer(node, context, f
|
|
|
32
32
|
fixer.replaceText(cssVariableValue.node.init.callee, identifier('xcss').toString())].concat(_toConsumableArray(styledObjectToXcssTokens(cssObjectExpression, fixer)));
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
// Update css object values to xcss values
|
|
35
|
+
// Update css object values to xcss values
|
|
36
36
|
// Note: `properties` in this context is a group of AST nodes that make up a key/value pair in an object.
|
|
37
37
|
// e.g. `padding: '8px'`. For clarity, it's renamed to `entry` inside the `.map()`.
|
|
38
38
|
export var styledObjectToXcssTokens = function styledObjectToXcssTokens(styles, fixer) {
|
|
@@ -43,16 +43,30 @@ export var styledObjectToXcssTokens = function styledObjectToXcssTokens(styles,
|
|
|
43
43
|
if (!isNodeOfType(entry.key, 'Identifier')) {
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
|
|
47
|
+
// maps literal values like: 8px to 'space.100'
|
|
48
|
+
if (isNodeOfType(entry.value, 'Literal')) {
|
|
49
|
+
var value = entry.value.value;
|
|
50
|
+
if (typeof value !== 'string') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
return fixer.replaceText(entry.value, literal("'".concat(supportedStylesMap[entry.key.name][value], "'")).toString());
|
|
48
54
|
}
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
55
|
+
// maps token calls like: token('space.100') to 'space.100'
|
|
56
|
+
if (isNodeOfType(entry.value, 'CallExpression')) {
|
|
57
|
+
var callExpression = entry.value;
|
|
58
|
+
// skip if not a call to `token`
|
|
59
|
+
if (!isNodeOfType(callExpression.callee, 'Identifier') || callExpression.callee.name !== 'token' || !isNodeOfType(callExpression.arguments[0], 'Literal')) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// the first argument of `token` is the token name and
|
|
63
|
+
// can be given directly to `xcss` as it has been validated already.
|
|
64
|
+
return fixer.replaceText(entry.value, literal("'".concat(callExpression.arguments[0].value, "'")).toString());
|
|
52
65
|
}
|
|
53
|
-
return fixer.replaceText(entry.value, literal("'".concat(supportedStylesMap[entry.key.name][value], "'")).toString());
|
|
54
66
|
});
|
|
55
67
|
};
|
|
68
|
+
|
|
69
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-16054
|
|
56
70
|
export var spaceTokenMap = {
|
|
57
71
|
'0px': 'space.0',
|
|
58
72
|
'2px': 'space.025',
|
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
-
|
|
3
|
-
// FIXME: This is only loosely typed
|
|
4
|
-
|
|
2
|
+
export var SPREAD_SYNTAX = Symbol('SPREAD_SYNTAX');
|
|
5
3
|
/**
|
|
6
4
|
* Note: Not recursive. Only handles top level key/value pairs
|
|
7
5
|
*/
|
|
8
6
|
export var convertASTObjectExpressionToJSObject = function convertASTObjectExpressionToJSObject(styles) {
|
|
9
|
-
var styleObj = {
|
|
7
|
+
var styleObj = {
|
|
8
|
+
unsupported: []
|
|
9
|
+
};
|
|
10
10
|
|
|
11
|
-
// if we see any spread props we
|
|
11
|
+
// if we see any spread props we indicate that as unsupported
|
|
12
12
|
if (!styles.properties.every(function (prop) {
|
|
13
13
|
return isNodeOfType(prop, 'Property');
|
|
14
14
|
})) {
|
|
15
|
-
|
|
15
|
+
styleObj.unsupported.push(SPREAD_SYNTAX);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
// TODO: We need to harden this logic.
|
|
19
|
-
// It currently generates a false positive for:
|
|
20
|
-
// styled.div({
|
|
21
|
-
// marginTop: "0px",
|
|
22
|
-
// marginBottom: token("space.100", "8px"),
|
|
23
|
-
// })
|
|
24
|
-
// as the value for `marginBottom` is not a string, so it is just skipped
|
|
25
|
-
// from the resulting map and this causes the rule to trigger when it shouldn't
|
|
26
17
|
styles.properties.forEach(function (prop) {
|
|
27
18
|
if (!isNodeOfType(prop, 'Property')) {
|
|
28
19
|
return;
|
|
@@ -30,13 +21,34 @@ export var convertASTObjectExpressionToJSObject = function convertASTObjectExpre
|
|
|
30
21
|
if (!isNodeOfType(prop.key, 'Identifier')) {
|
|
31
22
|
return;
|
|
32
23
|
}
|
|
33
|
-
|
|
24
|
+
|
|
25
|
+
// a literal string value, the base case
|
|
26
|
+
if (isNodeOfType(prop.value, 'Literal') && typeof prop.value.value === 'string') {
|
|
27
|
+
styleObj[prop.key.name] = prop.value.value;
|
|
34
28
|
return;
|
|
35
29
|
}
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
|
|
31
|
+
// try to handle a direct call to `token`
|
|
32
|
+
if (isNodeOfType(prop.value, 'CallExpression')) {
|
|
33
|
+
var callExpression = prop.value;
|
|
34
|
+
// strictly handle calls to `token`
|
|
35
|
+
if (isNodeOfType(callExpression.callee, 'Identifier') && callExpression.callee.name === 'token') {
|
|
36
|
+
// only two valid cases are supported
|
|
37
|
+
// one argument => token('space.100')
|
|
38
|
+
// two arguments => token('space.100', '8px')
|
|
39
|
+
if ((callExpression.arguments.length === 1 || callExpression.arguments.length === 2) && isNodeOfType(callExpression.arguments[0], 'Literal') && (typeof callExpression.arguments[1] === 'undefined' || isNodeOfType(callExpression.arguments[1], 'Literal'))) {
|
|
40
|
+
var _callExpression$argum;
|
|
41
|
+
styleObj[prop.key.name] = {
|
|
42
|
+
tokenName: String(callExpression.arguments[0].value),
|
|
43
|
+
fallbackValue: (_callExpression$argum = callExpression.arguments[1]) !== null && _callExpression$argum !== void 0 && _callExpression$argum.value ? String(callExpression.arguments[1].value) : undefined
|
|
44
|
+
};
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
38
48
|
}
|
|
39
|
-
|
|
49
|
+
|
|
50
|
+
// if we get here we have an unsupported value
|
|
51
|
+
styleObj.unsupported.push(prop.key.name);
|
|
40
52
|
});
|
|
41
53
|
return styleObj;
|
|
42
54
|
};
|
|
@@ -29,6 +29,7 @@ export var findValidStyledComponentCall = function findValidStyledComponentCall(
|
|
|
29
29
|
*
|
|
30
30
|
* In the future it could be enhanced to double check `styled` and `styled2`
|
|
31
31
|
* are Compiled imports but as is should work for the majority of use cases
|
|
32
|
+
* https://product-fabric.atlassian.net/browse/DSP-16058
|
|
32
33
|
*/
|
|
33
34
|
var isStyledCallExpression = function isStyledCallExpression(call) {
|
|
34
35
|
if (!isNodeOfType(call, 'CallExpression')) {
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
import _typeof from "@babel/runtime/helpers/typeof";
|
|
2
|
+
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
|
+
var _excluded = ["unsupported"];
|
|
1
4
|
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
5
|
import { supportedStylesMap } from '../transformers/css-to-xcss';
|
|
3
6
|
import { convertASTObjectExpressionToJSObject } from './convert-ast-object-expression-to-js-object';
|
|
4
|
-
export var isValidCssPropertiesToTransform = function isValidCssPropertiesToTransform(node) {
|
|
7
|
+
export var isValidCssPropertiesToTransform = function isValidCssPropertiesToTransform(node, config) {
|
|
5
8
|
var cssObjectExpression = node.arguments[0];
|
|
6
9
|
// Bail on empty object calls
|
|
7
10
|
if (!cssObjectExpression || !isNodeOfType(cssObjectExpression, 'ObjectExpression')) {
|
|
8
11
|
return false;
|
|
9
12
|
}
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
var _convertASTObjectExpr = convertASTObjectExpressionToJSObject(cssObjectExpression),
|
|
14
|
+
unsupported = _convertASTObjectExpr.unsupported,
|
|
15
|
+
cssObject = _objectWithoutProperties(_convertASTObjectExpr, _excluded);
|
|
16
|
+
// Bail if there are any unsupported styles
|
|
17
|
+
if (unsupported.length > 0 || Object.keys(cssObject).length !== 1) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
// Short-circuit when token calls are found but pattern is not enabled in config
|
|
21
|
+
if (!config.patterns.includes('css-property-with-tokens') && Object.values(cssObject).some(function (value) {
|
|
22
|
+
return _typeof(value) === 'object' && value.tokenName;
|
|
23
|
+
})) {
|
|
13
24
|
return false;
|
|
14
25
|
}
|
|
15
26
|
|
|
@@ -19,10 +30,22 @@ export var isValidCssPropertiesToTransform = function isValidCssPropertiesToTran
|
|
|
19
30
|
// than the rule reporting on things that can't be mapped.
|
|
20
31
|
var containsOnlyValidStyles = Object.keys(cssObject).every(function (styleProperty) {
|
|
21
32
|
var styleValue = cssObject[styleProperty];
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
|
|
34
|
+
// token function call
|
|
35
|
+
if (_typeof(styleValue) === 'object') {
|
|
36
|
+
// if there is no fallback value, we just map to the token name, if one is found
|
|
37
|
+
if (!styleValue.fallbackValue) {
|
|
38
|
+
return supportedStylesMap[styleProperty] && Object.values(supportedStylesMap[styleProperty]).includes(styleValue.tokenName);
|
|
39
|
+
}
|
|
40
|
+
// token with fallback
|
|
41
|
+
return supportedStylesMap[styleProperty] && supportedStylesMap[styleProperty][styleValue.fallbackValue] === styleValue.tokenName;
|
|
42
|
+
} else {
|
|
43
|
+
// direct value used
|
|
44
|
+
return supportedStylesMap[styleProperty] &&
|
|
45
|
+
// Is the key something we can map
|
|
46
|
+
supportedStylesMap[styleProperty][styleValue] // Is the value something we can map
|
|
47
|
+
;
|
|
48
|
+
}
|
|
26
49
|
});
|
|
27
50
|
|
|
28
51
|
if (!containsOnlyValidStyles) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
type Pattern = 'compiled-css-function' | 'compiled-styled-object' | 'css-template-literal' | 'css-property-with-tokens' | 'css-property-multiple-values';
|
|
1
2
|
export interface RuleConfig {
|
|
2
|
-
patterns:
|
|
3
|
+
patterns: Pattern[];
|
|
3
4
|
}
|
|
4
5
|
export declare const getConfig: (overrides: Partial<RuleConfig>) => Required<RuleConfig>;
|
|
6
|
+
export {};
|
package/dist/types/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
1
2
|
import type { Rule } from 'eslint';
|
|
2
3
|
import { ObjectExpression } from 'eslint-codemod-utils';
|
|
4
|
+
export declare const SPREAD_SYNTAX: unique symbol;
|
|
5
|
+
type Token = {
|
|
6
|
+
tokenName: string;
|
|
7
|
+
fallbackValue: string | undefined;
|
|
8
|
+
};
|
|
3
9
|
export type CSSPropStyleObject = {
|
|
4
|
-
[key
|
|
10
|
+
[key in keyof CSSProperties]: string | number | Token;
|
|
11
|
+
} & {
|
|
12
|
+
unsupported: (keyof CSSProperties | typeof SPREAD_SYNTAX)[];
|
|
5
13
|
};
|
|
6
14
|
/**
|
|
7
15
|
* Note: Not recursive. Only handles top level key/value pairs
|
|
8
16
|
*/
|
|
9
|
-
export declare const convertASTObjectExpressionToJSObject: (styles: ObjectExpression & Partial<Rule.NodeParentExtension>) => CSSPropStyleObject
|
|
17
|
+
export declare const convertASTObjectExpressionToJSObject: (styles: ObjectExpression & Partial<Rule.NodeParentExtension>) => CSSPropStyleObject;
|
|
18
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
2
|
import { SimpleCallExpression } from 'eslint-codemod-utils';
|
|
3
|
-
|
|
3
|
+
import { RuleConfig } from '../config';
|
|
4
|
+
export declare const isValidCssPropertiesToTransform: (node: SimpleCallExpression & Rule.NodeParentExtension, config: RuleConfig) => boolean;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
type Pattern = 'compiled-css-function' | 'compiled-styled-object' | 'css-template-literal' | 'css-property-with-tokens' | 'css-property-multiple-values';
|
|
1
2
|
export interface RuleConfig {
|
|
2
|
-
patterns:
|
|
3
|
+
patterns: Pattern[];
|
|
3
4
|
}
|
|
4
5
|
export declare const getConfig: (overrides: Partial<RuleConfig>) => Required<RuleConfig>;
|
|
6
|
+
export {};
|
package/dist/types-ts4.5/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
1
2
|
import type { Rule } from 'eslint';
|
|
2
3
|
import { ObjectExpression } from 'eslint-codemod-utils';
|
|
4
|
+
export declare const SPREAD_SYNTAX: unique symbol;
|
|
5
|
+
type Token = {
|
|
6
|
+
tokenName: string;
|
|
7
|
+
fallbackValue: string | undefined;
|
|
8
|
+
};
|
|
3
9
|
export type CSSPropStyleObject = {
|
|
4
|
-
[key
|
|
10
|
+
[key in keyof CSSProperties]: string | number | Token;
|
|
11
|
+
} & {
|
|
12
|
+
unsupported: (keyof CSSProperties | typeof SPREAD_SYNTAX)[];
|
|
5
13
|
};
|
|
6
14
|
/**
|
|
7
15
|
* Note: Not recursive. Only handles top level key/value pairs
|
|
8
16
|
*/
|
|
9
|
-
export declare const convertASTObjectExpressionToJSObject: (styles: ObjectExpression & Partial<Rule.NodeParentExtension>) => CSSPropStyleObject
|
|
17
|
+
export declare const convertASTObjectExpressionToJSObject: (styles: ObjectExpression & Partial<Rule.NodeParentExtension>) => CSSPropStyleObject;
|
|
18
|
+
export {};
|
package/dist/types-ts4.5/rules/use-primitives/utils/is-valid-css-properties-to-transform.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Rule } from 'eslint';
|
|
2
2
|
import { SimpleCallExpression } from 'eslint-codemod-utils';
|
|
3
|
-
|
|
3
|
+
import { RuleConfig } from '../config';
|
|
4
|
+
export declare const isValidCssPropertiesToTransform: (node: SimpleCallExpression & Rule.NodeParentExtension, config: RuleConfig) => boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/eslint-plugin-design-system",
|
|
3
3
|
"description": "The essential plugin for use with the Atlassian Design System.",
|
|
4
|
-
"version": "8.
|
|
4
|
+
"version": "8.20.0",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|