@atlaskit/eslint-plugin-platform 2.1.0 → 2.1.2
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/dist/cjs/index.js +1 -1
- package/dist/cjs/rules/compiled/expand-spacing-shorthand/index.js +31 -12
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/rules/compiled/expand-spacing-shorthand/index.js +29 -10
- package/dist/esm/index.js +1 -1
- package/dist/esm/rules/compiled/expand-spacing-shorthand/index.js +31 -12
- package/package.json +1 -1
- package/src/index.tsx +1 -1
- package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +89 -17
- package/src/rules/compiled/expand-spacing-shorthand/index.ts +78 -30
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 2.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#102248](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/102248)
|
|
8
|
+
[`05acb13c43541`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/05acb13c43541) -
|
|
9
|
+
AFB-825 Fixing edge case of expand-spacing-shorthand rule
|
|
10
|
+
|
|
11
|
+
## 2.1.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#101753](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/101753)
|
|
16
|
+
[`ab8a4d93399e8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/ab8a4d93399e8) -
|
|
17
|
+
AFB-822 Turn of expand-spacing-shorthand rule until all of Jira and Platform rollout is complete
|
|
18
|
+
|
|
3
19
|
## 2.1.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -72,7 +72,7 @@ var commonConfig = {
|
|
|
72
72
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
73
73
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
74
74
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
75
|
-
'@atlaskit/platform/expand-spacing-shorthand': '
|
|
75
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'off',
|
|
76
76
|
'@compiled/jsx-pragma': ['error', {
|
|
77
77
|
importSources: ['@atlaskit/css'],
|
|
78
78
|
onlyRunIfImportingCompiled: true,
|
|
@@ -11,9 +11,7 @@ var _compiledUtils = require("../../util/compiled-utils");
|
|
|
11
11
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
12
12
|
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; } }
|
|
13
13
|
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; }
|
|
14
|
-
var spacingPos = [
|
|
15
|
-
;
|
|
16
|
-
|
|
14
|
+
var spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
|
|
17
15
|
// Checks if node is a call expression with identifier 'token'
|
|
18
16
|
var isTokenCallExpression = function isTokenCallExpression(node) {
|
|
19
17
|
if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
|
|
@@ -32,11 +30,12 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
32
30
|
if (i < quasis.length) {
|
|
33
31
|
var cookedQuasi = quasis[i].value.cooked;
|
|
34
32
|
if (cookedQuasi) {
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
var splitQuasis = cookedQuasi.split(' ');
|
|
34
|
+
splitQuasis.forEach(function (str) {
|
|
35
|
+
str = str.trim().replace("\'", "");
|
|
36
|
+
if (str.length > 0) {
|
|
37
|
+
propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
|
|
38
|
+
}
|
|
40
39
|
});
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -49,7 +48,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
49
48
|
};
|
|
50
49
|
var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
|
|
51
50
|
if (!propertyValues.some(function (str) {
|
|
52
|
-
return str.includes(
|
|
51
|
+
return str.includes('token(');
|
|
53
52
|
})) {
|
|
54
53
|
return false;
|
|
55
54
|
}
|
|
@@ -57,13 +56,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
|
|
|
57
56
|
return false;
|
|
58
57
|
}
|
|
59
58
|
if (propertyValues.some(function (str) {
|
|
60
|
-
return str.includes(
|
|
59
|
+
return str.includes('calc(');
|
|
61
60
|
})) {
|
|
62
61
|
return false;
|
|
63
62
|
}
|
|
64
63
|
return true;
|
|
65
64
|
};
|
|
66
65
|
|
|
66
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
67
|
+
// If true: create an autofix
|
|
68
|
+
// If false: report violation without autofix
|
|
69
|
+
var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
|
|
70
|
+
var expressions = templateLiteral.expressions;
|
|
71
|
+
return expressions.every(function (expr) {
|
|
72
|
+
return expr.type === 'CallExpression' && isTokenCallExpression(expr);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
67
76
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
68
77
|
var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
69
78
|
var context = _ref.context,
|
|
@@ -98,10 +107,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
|
98
107
|
start = _prop$range[0],
|
|
99
108
|
end = _prop$range[1];
|
|
100
109
|
// Remove the entire line for the duplicate property
|
|
101
|
-
while ((0, _contextCompat.getSourceCode)(context).text[end] !==
|
|
110
|
+
while ((0, _contextCompat.getSourceCode)(context).text[end] !== '\n') {
|
|
102
111
|
end += 1;
|
|
103
112
|
}
|
|
104
|
-
while ((0, _contextCompat.getSourceCode)(context).text[start] !==
|
|
113
|
+
while ((0, _contextCompat.getSourceCode)(context).text[start] !== '\n') {
|
|
105
114
|
start -= 1;
|
|
106
115
|
}
|
|
107
116
|
spacing[i] = (0, _contextCompat.getSourceCode)(context).getText(prop.value);
|
|
@@ -130,6 +139,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
|
|
|
130
139
|
}
|
|
131
140
|
if (node.value.type === 'TemplateLiteral') {
|
|
132
141
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
142
|
+
if (!hasOnlyTokens(node.value)) {
|
|
143
|
+
context.report({
|
|
144
|
+
node: node,
|
|
145
|
+
messageId: 'expandSpacingShorthand',
|
|
146
|
+
data: {
|
|
147
|
+
property: propertyShorthand
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
133
152
|
var propertyValues = parseTemplateLiteral(node.value, context);
|
|
134
153
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
135
154
|
return;
|
package/dist/es2019/index.js
CHANGED
|
@@ -64,7 +64,7 @@ const commonConfig = {
|
|
|
64
64
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
65
65
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
66
66
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
67
|
-
'@atlaskit/platform/expand-spacing-shorthand': '
|
|
67
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'off',
|
|
68
68
|
'@compiled/jsx-pragma': ['error', {
|
|
69
69
|
importSources: ['@atlaskit/css'],
|
|
70
70
|
onlyRunIfImportingCompiled: true,
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { getSourceCode } from '../../util/context-compat';
|
|
2
2
|
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
3
|
-
const spacingPos = [
|
|
4
|
-
;
|
|
5
|
-
|
|
3
|
+
const spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
|
|
6
4
|
// Checks if node is a call expression with identifier 'token'
|
|
7
5
|
const isTokenCallExpression = node => {
|
|
8
6
|
if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
|
|
@@ -21,9 +19,12 @@ const parseTemplateLiteral = (templateLiteral, context) => {
|
|
|
21
19
|
if (i < quasis.length) {
|
|
22
20
|
const cookedQuasi = quasis[i].value.cooked;
|
|
23
21
|
if (cookedQuasi) {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
const splitQuasis = cookedQuasi.split(' ');
|
|
23
|
+
splitQuasis.forEach(str => {
|
|
24
|
+
str = str.trim().replace("\'", "");
|
|
25
|
+
if (str.length > 0) {
|
|
26
|
+
propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
|
|
27
|
+
}
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -35,18 +36,26 @@ const parseTemplateLiteral = (templateLiteral, context) => {
|
|
|
35
36
|
return propertyValues;
|
|
36
37
|
};
|
|
37
38
|
const checkValidPropertyValues = propertyValues => {
|
|
38
|
-
if (!propertyValues.some(str => str.includes(
|
|
39
|
+
if (!propertyValues.some(str => str.includes('token('))) {
|
|
39
40
|
return false;
|
|
40
41
|
}
|
|
41
42
|
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
42
43
|
return false;
|
|
43
44
|
}
|
|
44
|
-
if (propertyValues.some(str => str.includes(
|
|
45
|
+
if (propertyValues.some(str => str.includes('calc('))) {
|
|
45
46
|
return false;
|
|
46
47
|
}
|
|
47
48
|
return true;
|
|
48
49
|
};
|
|
49
50
|
|
|
51
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
52
|
+
// If true: create an autofix
|
|
53
|
+
// If false: report violation without autofix
|
|
54
|
+
const hasOnlyTokens = templateLiteral => {
|
|
55
|
+
const expressions = templateLiteral.expressions;
|
|
56
|
+
return expressions.every(expr => expr.type === 'CallExpression' && isTokenCallExpression(expr));
|
|
57
|
+
};
|
|
58
|
+
|
|
50
59
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
51
60
|
const expandSpacingProperties = ({
|
|
52
61
|
context,
|
|
@@ -69,10 +78,10 @@ const expandSpacingProperties = ({
|
|
|
69
78
|
if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
|
|
70
79
|
let [start, end] = prop.range;
|
|
71
80
|
// Remove the entire line for the duplicate property
|
|
72
|
-
while (getSourceCode(context).text[end] !==
|
|
81
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
73
82
|
end += 1;
|
|
74
83
|
}
|
|
75
|
-
while (getSourceCode(context).text[start] !==
|
|
84
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
76
85
|
start -= 1;
|
|
77
86
|
}
|
|
78
87
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -96,6 +105,16 @@ const executeExpandSpacingRule = (context, node, propertyShorthand) => {
|
|
|
96
105
|
}
|
|
97
106
|
if (node.value.type === 'TemplateLiteral') {
|
|
98
107
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
108
|
+
if (!hasOnlyTokens(node.value)) {
|
|
109
|
+
context.report({
|
|
110
|
+
node,
|
|
111
|
+
messageId: 'expandSpacingShorthand',
|
|
112
|
+
data: {
|
|
113
|
+
property: propertyShorthand
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
99
118
|
const propertyValues = parseTemplateLiteral(node.value, context);
|
|
100
119
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
101
120
|
return;
|
package/dist/esm/index.js
CHANGED
|
@@ -67,7 +67,7 @@ var commonConfig = {
|
|
|
67
67
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
68
68
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
69
69
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
70
|
-
'@atlaskit/platform/expand-spacing-shorthand': '
|
|
70
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'off',
|
|
71
71
|
'@compiled/jsx-pragma': ['error', {
|
|
72
72
|
importSources: ['@atlaskit/css'],
|
|
73
73
|
onlyRunIfImportingCompiled: true,
|
|
@@ -4,9 +4,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
4
4
|
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; }
|
|
5
5
|
import { getSourceCode } from '../../util/context-compat';
|
|
6
6
|
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
7
|
-
var spacingPos = [
|
|
8
|
-
;
|
|
9
|
-
|
|
7
|
+
var spacingPos = ['Top', 'Right', 'Bottom', 'Left'];
|
|
10
8
|
// Checks if node is a call expression with identifier 'token'
|
|
11
9
|
var isTokenCallExpression = function isTokenCallExpression(node) {
|
|
12
10
|
if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
|
|
@@ -25,11 +23,12 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
25
23
|
if (i < quasis.length) {
|
|
26
24
|
var cookedQuasi = quasis[i].value.cooked;
|
|
27
25
|
if (cookedQuasi) {
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
var splitQuasis = cookedQuasi.split(' ');
|
|
27
|
+
splitQuasis.forEach(function (str) {
|
|
28
|
+
str = str.trim().replace("\'", "");
|
|
29
|
+
if (str.length > 0) {
|
|
30
|
+
propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
|
|
31
|
+
}
|
|
33
32
|
});
|
|
34
33
|
}
|
|
35
34
|
}
|
|
@@ -42,7 +41,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
42
41
|
};
|
|
43
42
|
var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
|
|
44
43
|
if (!propertyValues.some(function (str) {
|
|
45
|
-
return str.includes(
|
|
44
|
+
return str.includes('token(');
|
|
46
45
|
})) {
|
|
47
46
|
return false;
|
|
48
47
|
}
|
|
@@ -50,13 +49,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
|
|
|
50
49
|
return false;
|
|
51
50
|
}
|
|
52
51
|
if (propertyValues.some(function (str) {
|
|
53
|
-
return str.includes(
|
|
52
|
+
return str.includes('calc(');
|
|
54
53
|
})) {
|
|
55
54
|
return false;
|
|
56
55
|
}
|
|
57
56
|
return true;
|
|
58
57
|
};
|
|
59
58
|
|
|
59
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
60
|
+
// If true: create an autofix
|
|
61
|
+
// If false: report violation without autofix
|
|
62
|
+
var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
|
|
63
|
+
var expressions = templateLiteral.expressions;
|
|
64
|
+
return expressions.every(function (expr) {
|
|
65
|
+
return expr.type === 'CallExpression' && isTokenCallExpression(expr);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
60
69
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
61
70
|
var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
62
71
|
var context = _ref.context,
|
|
@@ -91,10 +100,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
|
91
100
|
start = _prop$range[0],
|
|
92
101
|
end = _prop$range[1];
|
|
93
102
|
// Remove the entire line for the duplicate property
|
|
94
|
-
while (getSourceCode(context).text[end] !==
|
|
103
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
95
104
|
end += 1;
|
|
96
105
|
}
|
|
97
|
-
while (getSourceCode(context).text[start] !==
|
|
106
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
98
107
|
start -= 1;
|
|
99
108
|
}
|
|
100
109
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -123,6 +132,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
|
|
|
123
132
|
}
|
|
124
133
|
if (node.value.type === 'TemplateLiteral') {
|
|
125
134
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
135
|
+
if (!hasOnlyTokens(node.value)) {
|
|
136
|
+
context.report({
|
|
137
|
+
node: node,
|
|
138
|
+
messageId: 'expandSpacingShorthand',
|
|
139
|
+
data: {
|
|
140
|
+
property: propertyShorthand
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
126
145
|
var propertyValues = parseTemplateLiteral(node.value, context);
|
|
127
146
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
128
147
|
return;
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -66,7 +66,7 @@ const commonConfig = {
|
|
|
66
66
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
67
67
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
68
68
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
69
|
-
'@atlaskit/platform/expand-spacing-shorthand': '
|
|
69
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'off',
|
|
70
70
|
'@compiled/jsx-pragma': [
|
|
71
71
|
'error',
|
|
72
72
|
{
|
|
@@ -2,15 +2,8 @@ import { outdent } from 'outdent';
|
|
|
2
2
|
import { tester } from '../../../../__tests__/utils/_tester';
|
|
3
3
|
import { expandSpacingShorthand } from '../index';
|
|
4
4
|
|
|
5
|
-
const included_compiled_libraries = [
|
|
6
|
-
|
|
7
|
-
'@atlaskit/css'
|
|
8
|
-
];
|
|
9
|
-
const exempt_libraries = [
|
|
10
|
-
'@atlaskit/primitives',
|
|
11
|
-
'@emotion',
|
|
12
|
-
'styled-components',
|
|
13
|
-
];
|
|
5
|
+
const included_compiled_libraries = ['@compiled/react', '@atlaskit/css'];
|
|
6
|
+
const exempt_libraries = ['@emotion/react', 'styled-components'];
|
|
14
7
|
|
|
15
8
|
const validTestCases = (property: string) => {
|
|
16
9
|
return [
|
|
@@ -18,9 +11,14 @@ const validTestCases = (property: string) => {
|
|
|
18
11
|
name: `${property}: do not have to handle non-compiled packages (${imp})`,
|
|
19
12
|
code: outdent`
|
|
20
13
|
import {css} from '${imp}';
|
|
14
|
+
import {xcss} from '@atlaskit/primitives';
|
|
15
|
+
|
|
21
16
|
const styles = css({
|
|
22
17
|
${property}: token('space.200'),
|
|
23
18
|
});
|
|
19
|
+
const styles2 = xcss({
|
|
20
|
+
${property}: token('space.200'),
|
|
21
|
+
});
|
|
24
22
|
`,
|
|
25
23
|
})),
|
|
26
24
|
{
|
|
@@ -254,6 +252,26 @@ const invalidTestCases = (property: string) => {
|
|
|
254
252
|
`,
|
|
255
253
|
errors: [{ messageId: 'expandSpacingShorthand' }],
|
|
256
254
|
},
|
|
255
|
+
// Template literal containing expressions that is not token should only throw error with no autofix
|
|
256
|
+
{
|
|
257
|
+
name: `${property}: property value template string where it contains an expression that is not a token`,
|
|
258
|
+
code: outdent`
|
|
259
|
+
import {css} from '@compiled/react';
|
|
260
|
+
const styles = css({
|
|
261
|
+
${property}: \`\${token('space.100', '8px')} \${gridSize * 2}px\`,
|
|
262
|
+
});
|
|
263
|
+
const styles2 = css({
|
|
264
|
+
padding: \`\${DROPDOWN_HEADER_VERTICAL_PADDING} \${token('space.075','6px')}
|
|
265
|
+
\${DROPDOWN_HEADER_VERTICAL_PADDING} \${token('space.200', '16px')}\`,
|
|
266
|
+
});
|
|
267
|
+
const styles3 = css({
|
|
268
|
+
${property}: \`\${token('space.050', '4px')} \${token('space.150', '12px')} \${token('space.150', '12px')}
|
|
269
|
+
\${({ isSummaryView }: EditFormContentWrapperProps) =>
|
|
270
|
+
isSummaryView ? token('space.0', '0') : token('space.150', '12px')}\`,
|
|
271
|
+
});
|
|
272
|
+
`,
|
|
273
|
+
errors: Array.from(Array(3), () => ({ messageId: 'expandSpacingShorthand' })),
|
|
274
|
+
},
|
|
257
275
|
// Miscellaneous
|
|
258
276
|
{
|
|
259
277
|
name: `${property}: new property should not be created if existing property already exists`,
|
|
@@ -329,16 +347,70 @@ const invalidTestCases = (property: string) => {
|
|
|
329
347
|
`,
|
|
330
348
|
errors: Array.from(Array(3), () => ({ messageId: 'expandSpacingShorthand' })),
|
|
331
349
|
},
|
|
350
|
+
{
|
|
351
|
+
name: `${property}: property value includes newline and tab`,
|
|
352
|
+
code: outdent`
|
|
353
|
+
import {css} from '@compiled/react';
|
|
354
|
+
const styles = css({
|
|
355
|
+
${property}: \`\${token('space.100')} \${token('space.200')}
|
|
356
|
+
\${token('space.300')} \${token('space.400')}\`,
|
|
357
|
+
});
|
|
358
|
+
const styles2 = css({
|
|
359
|
+
paddingBottom: token('space.050', '4px'),
|
|
360
|
+
'&& > span': {
|
|
361
|
+
padding: \`\${token('space.100', '8px')} \${token('space.150', '12px')} 7px
|
|
362
|
+
\${token('space.150', '12px')}\`,
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
`,
|
|
366
|
+
output: outdent`
|
|
367
|
+
import {css} from '@compiled/react';
|
|
368
|
+
const styles = css({
|
|
369
|
+
${property}Top: token('space.100'),
|
|
370
|
+
${property}Right: token('space.200'),
|
|
371
|
+
${property}Bottom: token('space.300'),
|
|
372
|
+
${property}Left: token('space.400'),
|
|
373
|
+
});
|
|
374
|
+
const styles2 = css({
|
|
375
|
+
paddingBottom: token('space.050', '4px'),
|
|
376
|
+
'&& > span': {
|
|
377
|
+
paddingTop: token('space.100', '8px'),
|
|
378
|
+
paddingRight: token('space.150', '12px'),
|
|
379
|
+
paddingBottom: '7px',
|
|
380
|
+
paddingLeft: token('space.150', '12px'),
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
`,
|
|
384
|
+
errors: Array.from(Array(2), () => ({ messageId: 'expandSpacingShorthand' })),
|
|
385
|
+
},
|
|
386
|
+
// TODO (AFB-1022): Resolve this failing test
|
|
387
|
+
// {
|
|
388
|
+
// name: `${property}: styled components with prop input`,
|
|
389
|
+
// code: outdent`
|
|
390
|
+
// import { styled } from '@compiled/react';
|
|
391
|
+
// const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
|
|
392
|
+
// '& button': ({ isDisabled }) => ({
|
|
393
|
+
// ${property}: \`\${token('space.075', '6px')} \${token('space.200', '16px')}\`,
|
|
394
|
+
// }),
|
|
395
|
+
// });
|
|
396
|
+
// `,
|
|
397
|
+
// output: outdent`
|
|
398
|
+
// import { styled } from '@compiled/react';
|
|
399
|
+
// const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
|
|
400
|
+
// '& button': ({ isDisabled }) => ({
|
|
401
|
+
// ${property}Top: token('space.075', '6px'),
|
|
402
|
+
// ${property}Right: token('space.200', '16px'),
|
|
403
|
+
// ${property}Bottom: token('space.075', '6px'),
|
|
404
|
+
// ${property}Left: token('space.200', '16px'),
|
|
405
|
+
// }),
|
|
406
|
+
// });
|
|
407
|
+
// `,
|
|
408
|
+
// errors: [{ messageId: 'expandSpacingShorthand' }],
|
|
409
|
+
// },
|
|
332
410
|
];
|
|
333
411
|
};
|
|
334
412
|
|
|
335
413
|
tester.run('expand-spacing-shorthand', expandSpacingShorthand, {
|
|
336
|
-
valid: [
|
|
337
|
-
|
|
338
|
-
...validTestCases('margin'),
|
|
339
|
-
],
|
|
340
|
-
invalid: [
|
|
341
|
-
...invalidTestCases('padding'),
|
|
342
|
-
...invalidTestCases('margin'),
|
|
343
|
-
],
|
|
414
|
+
valid: [...validTestCases('padding'), ...validTestCases('margin')],
|
|
415
|
+
invalid: [...invalidTestCases('padding'), ...invalidTestCases('margin')],
|
|
344
416
|
});
|
|
@@ -3,15 +3,15 @@ import type { Property, Node, TemplateLiteral, CallExpression } from 'estree';
|
|
|
3
3
|
import { getSourceCode } from '../../util/context-compat';
|
|
4
4
|
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
5
5
|
|
|
6
|
-
const spacingPos = [
|
|
6
|
+
const spacingPos = ['Top', 'Right', 'Bottom', 'Left'] as const;
|
|
7
7
|
|
|
8
8
|
interface ExpandSpacingPropertiesType {
|
|
9
|
-
context: Rule.RuleContext
|
|
10
|
-
node: Property & { parent?: Node }
|
|
11
|
-
propertyValues: string[]
|
|
12
|
-
fixer: Rule.RuleFixer
|
|
13
|
-
propertyShorthand: string
|
|
14
|
-
}
|
|
9
|
+
context: Rule.RuleContext;
|
|
10
|
+
node: Property & { parent?: Node };
|
|
11
|
+
propertyValues: string[];
|
|
12
|
+
fixer: Rule.RuleFixer;
|
|
13
|
+
propertyShorthand: string;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
16
|
// Checks if node is a call expression with identifier 'token'
|
|
17
17
|
const isTokenCallExpression = (node: CallExpression) => {
|
|
@@ -29,12 +29,15 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
|
|
|
29
29
|
|
|
30
30
|
let propertyValues: string[] = [];
|
|
31
31
|
for (let i = 0; i < expressions.length || i < quasis.length; i++) {
|
|
32
|
-
if (i < quasis.length) {
|
|
32
|
+
if (i < quasis.length) {
|
|
33
33
|
const cookedQuasi = quasis[i].value.cooked;
|
|
34
34
|
if (cookedQuasi) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const splitQuasis = cookedQuasi.split(' ');
|
|
36
|
+
splitQuasis.forEach((str) => {
|
|
37
|
+
str = str.trim().replace("\'", "");
|
|
38
|
+
if (str.length > 0) {
|
|
39
|
+
propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
|
|
40
|
+
}
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
43
|
}
|
|
@@ -47,14 +50,34 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
|
|
|
47
50
|
};
|
|
48
51
|
|
|
49
52
|
const checkValidPropertyValues = (propertyValues: string[]) => {
|
|
50
|
-
if (!propertyValues.some(str => str.includes(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
if (!propertyValues.some((str) => str.includes('token('))) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (propertyValues.some((str) => str.includes('calc('))) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
53
62
|
return true;
|
|
54
|
-
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
66
|
+
// If true: create an autofix
|
|
67
|
+
// If false: report violation without autofix
|
|
68
|
+
const hasOnlyTokens = (templateLiteral: TemplateLiteral) => {
|
|
69
|
+
const expressions = templateLiteral.expressions;
|
|
70
|
+
return expressions.every((expr) => expr.type === 'CallExpression' && isTokenCallExpression(expr));
|
|
71
|
+
};
|
|
55
72
|
|
|
56
73
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
57
|
-
const expandSpacingProperties = ({
|
|
74
|
+
const expandSpacingProperties = ({
|
|
75
|
+
context,
|
|
76
|
+
node,
|
|
77
|
+
propertyValues,
|
|
78
|
+
fixer,
|
|
79
|
+
propertyShorthand,
|
|
80
|
+
}: ExpandSpacingPropertiesType) => {
|
|
58
81
|
const [top, right = top, bottom = top, left = right] = propertyValues;
|
|
59
82
|
const spacing: string[] = [top, right, bottom, left];
|
|
60
83
|
|
|
@@ -63,16 +86,22 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
63
86
|
const parentNode = node.parent;
|
|
64
87
|
if (parentNode && parentNode.type === 'ObjectExpression') {
|
|
65
88
|
for (var prop of parentNode.properties) {
|
|
66
|
-
if (prop.type !== 'Property') {
|
|
67
|
-
|
|
89
|
+
if (prop.type !== 'Property') {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (
|
|
93
|
+
prop.key.type === 'Identifier' &&
|
|
94
|
+
prop.range &&
|
|
95
|
+
prop.key.name !== `${propertyShorthand}`
|
|
96
|
+
) {
|
|
68
97
|
for (let i = 0; i < spacing.length; i++) {
|
|
69
98
|
if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
|
|
70
99
|
let [start, end] = prop.range;
|
|
71
100
|
// Remove the entire line for the duplicate property
|
|
72
|
-
while (getSourceCode(context).text[end] !==
|
|
101
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
73
102
|
end += 1;
|
|
74
103
|
}
|
|
75
|
-
while (getSourceCode(context).text[start] !==
|
|
104
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
76
105
|
start -= 1;
|
|
77
106
|
}
|
|
78
107
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -83,7 +112,7 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
83
112
|
}
|
|
84
113
|
}
|
|
85
114
|
}
|
|
86
|
-
|
|
115
|
+
|
|
87
116
|
fixes.push(fixer.insertTextAfter(node, `${propertyShorthand}Top: ${spacing[0]},\n`));
|
|
88
117
|
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Right: ${spacing[1]},\n`));
|
|
89
118
|
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Bottom: ${spacing[2]},\n`));
|
|
@@ -92,12 +121,30 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
92
121
|
return fixes;
|
|
93
122
|
};
|
|
94
123
|
|
|
95
|
-
const executeExpandSpacingRule = (
|
|
96
|
-
|
|
124
|
+
const executeExpandSpacingRule = (
|
|
125
|
+
context: Rule.RuleContext,
|
|
126
|
+
node: Property,
|
|
127
|
+
propertyShorthand: string,
|
|
128
|
+
) => {
|
|
129
|
+
if (!isCompiledAPI(context, node)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
97
132
|
if (node.value.type === 'TemplateLiteral') {
|
|
98
133
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
134
|
+
if (!hasOnlyTokens(node.value)) {
|
|
135
|
+
context.report({
|
|
136
|
+
node,
|
|
137
|
+
messageId: 'expandSpacingShorthand',
|
|
138
|
+
data: {
|
|
139
|
+
property: propertyShorthand,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
99
144
|
const propertyValues = parseTemplateLiteral(node.value, context);
|
|
100
|
-
if (!checkValidPropertyValues(propertyValues)) {
|
|
145
|
+
if (!checkValidPropertyValues(propertyValues)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
101
148
|
context.report({
|
|
102
149
|
node,
|
|
103
150
|
messageId: 'expandSpacingShorthand',
|
|
@@ -105,12 +152,12 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
|
|
|
105
152
|
property: propertyShorthand,
|
|
106
153
|
},
|
|
107
154
|
fix(fixer) {
|
|
108
|
-
return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
|
|
155
|
+
return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
|
|
109
156
|
},
|
|
110
157
|
});
|
|
111
158
|
} else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
|
|
112
159
|
// Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
|
|
113
|
-
const propertyValues = [
|
|
160
|
+
const propertyValues = [getSourceCode(context).getText(node.value)];
|
|
114
161
|
context.report({
|
|
115
162
|
node,
|
|
116
163
|
messageId: 'expandSpacingShorthand',
|
|
@@ -118,11 +165,11 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
|
|
|
118
165
|
property: propertyShorthand,
|
|
119
166
|
},
|
|
120
167
|
fix(fixer) {
|
|
121
|
-
return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
|
|
168
|
+
return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
|
|
122
169
|
},
|
|
123
170
|
});
|
|
124
171
|
}
|
|
125
|
-
}
|
|
172
|
+
};
|
|
126
173
|
|
|
127
174
|
export const expandSpacingShorthand: Rule.RuleModule = {
|
|
128
175
|
meta: {
|
|
@@ -130,7 +177,8 @@ export const expandSpacingShorthand: Rule.RuleModule = {
|
|
|
130
177
|
url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/',
|
|
131
178
|
},
|
|
132
179
|
messages: {
|
|
133
|
-
expandSpacingShorthand:
|
|
180
|
+
expandSpacingShorthand:
|
|
181
|
+
'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand',
|
|
134
182
|
},
|
|
135
183
|
type: 'problem',
|
|
136
184
|
fixable: 'code',
|
|
@@ -147,4 +195,4 @@ export const expandSpacingShorthand: Rule.RuleModule = {
|
|
|
147
195
|
},
|
|
148
196
|
};
|
|
149
197
|
|
|
150
|
-
export default expandSpacingShorthand;
|
|
198
|
+
export default expandSpacingShorthand;
|