@atlaskit/eslint-plugin-platform 2.1.0 → 2.1.1
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 +8 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/rules/compiled/expand-spacing-shorthand/index.js +27 -9
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/rules/compiled/expand-spacing-shorthand/index.js +24 -8
- package/dist/esm/index.js +1 -1
- package/dist/esm/rules/compiled/expand-spacing-shorthand/index.js +27 -9
- package/package.json +1 -1
- package/src/index.tsx +1 -1
- package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +73 -17
- package/src/rules/compiled/expand-spacing-shorthand/index.ts +74 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 2.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#101753](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/101753)
|
|
8
|
+
[`ab8a4d93399e8`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/ab8a4d93399e8) -
|
|
9
|
+
AFB-822 Turn of expand-spacing-shorthand rule until all of Jira and Platform rollout is complete
|
|
10
|
+
|
|
3
11
|
## 2.1.0
|
|
4
12
|
|
|
5
13
|
### 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,8 +30,8 @@ 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 splitQuasi = cookedQuasi.split(
|
|
36
|
-
return str.length > 0;
|
|
33
|
+
var splitQuasi = cookedQuasi.split(' ').filter(function (str) {
|
|
34
|
+
return str.trim().length > 0;
|
|
37
35
|
});
|
|
38
36
|
splitQuasi.forEach(function (str) {
|
|
39
37
|
propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
|
|
@@ -49,7 +47,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
49
47
|
};
|
|
50
48
|
var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
|
|
51
49
|
if (!propertyValues.some(function (str) {
|
|
52
|
-
return str.includes(
|
|
50
|
+
return str.includes('token(');
|
|
53
51
|
})) {
|
|
54
52
|
return false;
|
|
55
53
|
}
|
|
@@ -57,13 +55,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
|
|
|
57
55
|
return false;
|
|
58
56
|
}
|
|
59
57
|
if (propertyValues.some(function (str) {
|
|
60
|
-
return str.includes(
|
|
58
|
+
return str.includes('calc(');
|
|
61
59
|
})) {
|
|
62
60
|
return false;
|
|
63
61
|
}
|
|
64
62
|
return true;
|
|
65
63
|
};
|
|
66
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
|
+
var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
|
|
69
|
+
var expressions = templateLiteral.expressions;
|
|
70
|
+
return expressions.every(function (expr) {
|
|
71
|
+
return expr.type === 'CallExpression' && isTokenCallExpression(expr);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
67
75
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
68
76
|
var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
69
77
|
var context = _ref.context,
|
|
@@ -98,10 +106,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
|
98
106
|
start = _prop$range[0],
|
|
99
107
|
end = _prop$range[1];
|
|
100
108
|
// Remove the entire line for the duplicate property
|
|
101
|
-
while ((0, _contextCompat.getSourceCode)(context).text[end] !==
|
|
109
|
+
while ((0, _contextCompat.getSourceCode)(context).text[end] !== '\n') {
|
|
102
110
|
end += 1;
|
|
103
111
|
}
|
|
104
|
-
while ((0, _contextCompat.getSourceCode)(context).text[start] !==
|
|
112
|
+
while ((0, _contextCompat.getSourceCode)(context).text[start] !== '\n') {
|
|
105
113
|
start -= 1;
|
|
106
114
|
}
|
|
107
115
|
spacing[i] = (0, _contextCompat.getSourceCode)(context).getText(prop.value);
|
|
@@ -130,6 +138,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
|
|
|
130
138
|
}
|
|
131
139
|
if (node.value.type === 'TemplateLiteral') {
|
|
132
140
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
141
|
+
if (!hasOnlyTokens(node.value)) {
|
|
142
|
+
context.report({
|
|
143
|
+
node: node,
|
|
144
|
+
messageId: 'expandSpacingShorthand',
|
|
145
|
+
data: {
|
|
146
|
+
property: propertyShorthand
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
133
151
|
var propertyValues = parseTemplateLiteral(node.value, context);
|
|
134
152
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
135
153
|
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,7 +19,7 @@ const parseTemplateLiteral = (templateLiteral, context) => {
|
|
|
21
19
|
if (i < quasis.length) {
|
|
22
20
|
const cookedQuasi = quasis[i].value.cooked;
|
|
23
21
|
if (cookedQuasi) {
|
|
24
|
-
const splitQuasi = cookedQuasi.split(
|
|
22
|
+
const splitQuasi = cookedQuasi.split(' ').filter(str => str.trim().length > 0);
|
|
25
23
|
splitQuasi.forEach(str => {
|
|
26
24
|
propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
|
|
27
25
|
});
|
|
@@ -35,18 +33,26 @@ const parseTemplateLiteral = (templateLiteral, context) => {
|
|
|
35
33
|
return propertyValues;
|
|
36
34
|
};
|
|
37
35
|
const checkValidPropertyValues = propertyValues => {
|
|
38
|
-
if (!propertyValues.some(str => str.includes(
|
|
36
|
+
if (!propertyValues.some(str => str.includes('token('))) {
|
|
39
37
|
return false;
|
|
40
38
|
}
|
|
41
39
|
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
42
40
|
return false;
|
|
43
41
|
}
|
|
44
|
-
if (propertyValues.some(str => str.includes(
|
|
42
|
+
if (propertyValues.some(str => str.includes('calc('))) {
|
|
45
43
|
return false;
|
|
46
44
|
}
|
|
47
45
|
return true;
|
|
48
46
|
};
|
|
49
47
|
|
|
48
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
49
|
+
// If true: create an autofix
|
|
50
|
+
// If false: report violation without autofix
|
|
51
|
+
const hasOnlyTokens = templateLiteral => {
|
|
52
|
+
const expressions = templateLiteral.expressions;
|
|
53
|
+
return expressions.every(expr => expr.type === 'CallExpression' && isTokenCallExpression(expr));
|
|
54
|
+
};
|
|
55
|
+
|
|
50
56
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
51
57
|
const expandSpacingProperties = ({
|
|
52
58
|
context,
|
|
@@ -69,10 +75,10 @@ const expandSpacingProperties = ({
|
|
|
69
75
|
if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
|
|
70
76
|
let [start, end] = prop.range;
|
|
71
77
|
// Remove the entire line for the duplicate property
|
|
72
|
-
while (getSourceCode(context).text[end] !==
|
|
78
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
73
79
|
end += 1;
|
|
74
80
|
}
|
|
75
|
-
while (getSourceCode(context).text[start] !==
|
|
81
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
76
82
|
start -= 1;
|
|
77
83
|
}
|
|
78
84
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -96,6 +102,16 @@ const executeExpandSpacingRule = (context, node, propertyShorthand) => {
|
|
|
96
102
|
}
|
|
97
103
|
if (node.value.type === 'TemplateLiteral') {
|
|
98
104
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
105
|
+
if (!hasOnlyTokens(node.value)) {
|
|
106
|
+
context.report({
|
|
107
|
+
node,
|
|
108
|
+
messageId: 'expandSpacingShorthand',
|
|
109
|
+
data: {
|
|
110
|
+
property: propertyShorthand
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
99
115
|
const propertyValues = parseTemplateLiteral(node.value, context);
|
|
100
116
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
101
117
|
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,8 +23,8 @@ 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 splitQuasi = cookedQuasi.split(
|
|
29
|
-
return str.length > 0;
|
|
26
|
+
var splitQuasi = cookedQuasi.split(' ').filter(function (str) {
|
|
27
|
+
return str.trim().length > 0;
|
|
30
28
|
});
|
|
31
29
|
splitQuasi.forEach(function (str) {
|
|
32
30
|
propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
|
|
@@ -42,7 +40,7 @@ var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, contex
|
|
|
42
40
|
};
|
|
43
41
|
var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
|
|
44
42
|
if (!propertyValues.some(function (str) {
|
|
45
|
-
return str.includes(
|
|
43
|
+
return str.includes('token(');
|
|
46
44
|
})) {
|
|
47
45
|
return false;
|
|
48
46
|
}
|
|
@@ -50,13 +48,23 @@ var checkValidPropertyValues = function checkValidPropertyValues(propertyValues)
|
|
|
50
48
|
return false;
|
|
51
49
|
}
|
|
52
50
|
if (propertyValues.some(function (str) {
|
|
53
|
-
return str.includes(
|
|
51
|
+
return str.includes('calc(');
|
|
54
52
|
})) {
|
|
55
53
|
return false;
|
|
56
54
|
}
|
|
57
55
|
return true;
|
|
58
56
|
};
|
|
59
57
|
|
|
58
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
59
|
+
// If true: create an autofix
|
|
60
|
+
// If false: report violation without autofix
|
|
61
|
+
var hasOnlyTokens = function hasOnlyTokens(templateLiteral) {
|
|
62
|
+
var expressions = templateLiteral.expressions;
|
|
63
|
+
return expressions.every(function (expr) {
|
|
64
|
+
return expr.type === 'CallExpression' && isTokenCallExpression(expr);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
60
68
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
61
69
|
var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
62
70
|
var context = _ref.context,
|
|
@@ -91,10 +99,10 @@ var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
|
91
99
|
start = _prop$range[0],
|
|
92
100
|
end = _prop$range[1];
|
|
93
101
|
// Remove the entire line for the duplicate property
|
|
94
|
-
while (getSourceCode(context).text[end] !==
|
|
102
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
95
103
|
end += 1;
|
|
96
104
|
}
|
|
97
|
-
while (getSourceCode(context).text[start] !==
|
|
105
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
98
106
|
start -= 1;
|
|
99
107
|
}
|
|
100
108
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -123,6 +131,16 @@ var executeExpandSpacingRule = function executeExpandSpacingRule(context, node,
|
|
|
123
131
|
}
|
|
124
132
|
if (node.value.type === 'TemplateLiteral') {
|
|
125
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: node,
|
|
137
|
+
messageId: 'expandSpacingShorthand',
|
|
138
|
+
data: {
|
|
139
|
+
property: propertyShorthand
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
126
144
|
var propertyValues = parseTemplateLiteral(node.value, context);
|
|
127
145
|
if (!checkValidPropertyValues(propertyValues)) {
|
|
128
146
|
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,54 @@ 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
|
+
`,
|
|
359
|
+
output: outdent`
|
|
360
|
+
import {css} from '@compiled/react';
|
|
361
|
+
const styles = css({
|
|
362
|
+
${property}Top: token('space.100'),
|
|
363
|
+
${property}Right: token('space.200'),
|
|
364
|
+
${property}Bottom: token('space.300'),
|
|
365
|
+
${property}Left: token('space.400'),
|
|
366
|
+
});
|
|
367
|
+
`,
|
|
368
|
+
errors: [{ messageId: 'expandSpacingShorthand' }],
|
|
369
|
+
},
|
|
370
|
+
// TODO (AFB-1022): Resolve this failing test
|
|
371
|
+
// {
|
|
372
|
+
// name: `${property}: styled components with prop input`,
|
|
373
|
+
// code: outdent`
|
|
374
|
+
// import { styled } from '@compiled/react';
|
|
375
|
+
// const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
|
|
376
|
+
// '& button': ({ isDisabled }) => ({
|
|
377
|
+
// ${property}: \`\${token('space.075', '6px')} \${token('space.200', '16px')}\`,
|
|
378
|
+
// }),
|
|
379
|
+
// });
|
|
380
|
+
// `,
|
|
381
|
+
// output: outdent`
|
|
382
|
+
// import { styled } from '@compiled/react';
|
|
383
|
+
// const MenuOptionWrapper = styled.div<{ isDisabled: boolean }>({
|
|
384
|
+
// '& button': ({ isDisabled }) => ({
|
|
385
|
+
// ${property}Top: token('space.075', '6px'),
|
|
386
|
+
// ${property}Right: token('space.200', '16px'),
|
|
387
|
+
// ${property}Bottom: token('space.075', '6px'),
|
|
388
|
+
// ${property}Left: token('space.200', '16px'),
|
|
389
|
+
// }),
|
|
390
|
+
// });
|
|
391
|
+
// `,
|
|
392
|
+
// errors: [{ messageId: 'expandSpacingShorthand' }],
|
|
393
|
+
// },
|
|
332
394
|
];
|
|
333
395
|
};
|
|
334
396
|
|
|
335
397
|
tester.run('expand-spacing-shorthand', expandSpacingShorthand, {
|
|
336
|
-
valid: [
|
|
337
|
-
|
|
338
|
-
...validTestCases('margin'),
|
|
339
|
-
],
|
|
340
|
-
invalid: [
|
|
341
|
-
...invalidTestCases('padding'),
|
|
342
|
-
...invalidTestCases('margin'),
|
|
343
|
-
],
|
|
398
|
+
valid: [...validTestCases('padding'), ...validTestCases('margin')],
|
|
399
|
+
invalid: [...invalidTestCases('padding'), ...invalidTestCases('margin')],
|
|
344
400
|
});
|
|
@@ -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,11 +29,11 @@ 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 splitQuasi = cookedQuasi.split(
|
|
36
|
-
splitQuasi.forEach(str => {
|
|
35
|
+
const splitQuasi = cookedQuasi.split(' ').filter((str) => str.trim().length > 0);
|
|
36
|
+
splitQuasi.forEach((str) => {
|
|
37
37
|
propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
|
|
38
38
|
});
|
|
39
39
|
}
|
|
@@ -47,14 +47,34 @@ const parseTemplateLiteral = (templateLiteral: TemplateLiteral, context: Rule.Ru
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const checkValidPropertyValues = (propertyValues: string[]) => {
|
|
50
|
-
if (!propertyValues.some(str => str.includes(
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if (!propertyValues.some((str) => str.includes('token('))) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (propertyValues.some((str) => str.includes('calc('))) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
53
59
|
return true;
|
|
54
|
-
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Check that all expressions in TemplateLiteral are token expressions
|
|
63
|
+
// If true: create an autofix
|
|
64
|
+
// If false: report violation without autofix
|
|
65
|
+
const hasOnlyTokens = (templateLiteral: TemplateLiteral) => {
|
|
66
|
+
const expressions = templateLiteral.expressions;
|
|
67
|
+
return expressions.every((expr) => expr.type === 'CallExpression' && isTokenCallExpression(expr));
|
|
68
|
+
};
|
|
55
69
|
|
|
56
70
|
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
57
|
-
const expandSpacingProperties = ({
|
|
71
|
+
const expandSpacingProperties = ({
|
|
72
|
+
context,
|
|
73
|
+
node,
|
|
74
|
+
propertyValues,
|
|
75
|
+
fixer,
|
|
76
|
+
propertyShorthand,
|
|
77
|
+
}: ExpandSpacingPropertiesType) => {
|
|
58
78
|
const [top, right = top, bottom = top, left = right] = propertyValues;
|
|
59
79
|
const spacing: string[] = [top, right, bottom, left];
|
|
60
80
|
|
|
@@ -63,16 +83,22 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
63
83
|
const parentNode = node.parent;
|
|
64
84
|
if (parentNode && parentNode.type === 'ObjectExpression') {
|
|
65
85
|
for (var prop of parentNode.properties) {
|
|
66
|
-
if (prop.type !== 'Property') {
|
|
67
|
-
|
|
86
|
+
if (prop.type !== 'Property') {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (
|
|
90
|
+
prop.key.type === 'Identifier' &&
|
|
91
|
+
prop.range &&
|
|
92
|
+
prop.key.name !== `${propertyShorthand}`
|
|
93
|
+
) {
|
|
68
94
|
for (let i = 0; i < spacing.length; i++) {
|
|
69
95
|
if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
|
|
70
96
|
let [start, end] = prop.range;
|
|
71
97
|
// Remove the entire line for the duplicate property
|
|
72
|
-
while (getSourceCode(context).text[end] !==
|
|
98
|
+
while (getSourceCode(context).text[end] !== '\n') {
|
|
73
99
|
end += 1;
|
|
74
100
|
}
|
|
75
|
-
while (getSourceCode(context).text[start] !==
|
|
101
|
+
while (getSourceCode(context).text[start] !== '\n') {
|
|
76
102
|
start -= 1;
|
|
77
103
|
}
|
|
78
104
|
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
@@ -83,7 +109,7 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
83
109
|
}
|
|
84
110
|
}
|
|
85
111
|
}
|
|
86
|
-
|
|
112
|
+
|
|
87
113
|
fixes.push(fixer.insertTextAfter(node, `${propertyShorthand}Top: ${spacing[0]},\n`));
|
|
88
114
|
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Right: ${spacing[1]},\n`));
|
|
89
115
|
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Bottom: ${spacing[2]},\n`));
|
|
@@ -92,12 +118,30 @@ const expandSpacingProperties = ({ context, node, propertyValues, fixer, propert
|
|
|
92
118
|
return fixes;
|
|
93
119
|
};
|
|
94
120
|
|
|
95
|
-
const executeExpandSpacingRule = (
|
|
96
|
-
|
|
121
|
+
const executeExpandSpacingRule = (
|
|
122
|
+
context: Rule.RuleContext,
|
|
123
|
+
node: Property,
|
|
124
|
+
propertyShorthand: string,
|
|
125
|
+
) => {
|
|
126
|
+
if (!isCompiledAPI(context, node)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
97
129
|
if (node.value.type === 'TemplateLiteral') {
|
|
98
130
|
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
131
|
+
if (!hasOnlyTokens(node.value)) {
|
|
132
|
+
context.report({
|
|
133
|
+
node,
|
|
134
|
+
messageId: 'expandSpacingShorthand',
|
|
135
|
+
data: {
|
|
136
|
+
property: propertyShorthand,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
99
141
|
const propertyValues = parseTemplateLiteral(node.value, context);
|
|
100
|
-
if (!checkValidPropertyValues(propertyValues)) {
|
|
142
|
+
if (!checkValidPropertyValues(propertyValues)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
101
145
|
context.report({
|
|
102
146
|
node,
|
|
103
147
|
messageId: 'expandSpacingShorthand',
|
|
@@ -105,12 +149,12 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
|
|
|
105
149
|
property: propertyShorthand,
|
|
106
150
|
},
|
|
107
151
|
fix(fixer) {
|
|
108
|
-
return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
|
|
152
|
+
return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
|
|
109
153
|
},
|
|
110
154
|
});
|
|
111
155
|
} else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
|
|
112
156
|
// Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
|
|
113
|
-
const propertyValues = [
|
|
157
|
+
const propertyValues = [getSourceCode(context).getText(node.value)];
|
|
114
158
|
context.report({
|
|
115
159
|
node,
|
|
116
160
|
messageId: 'expandSpacingShorthand',
|
|
@@ -118,11 +162,11 @@ const executeExpandSpacingRule = (context: Rule.RuleContext, node: Property, pro
|
|
|
118
162
|
property: propertyShorthand,
|
|
119
163
|
},
|
|
120
164
|
fix(fixer) {
|
|
121
|
-
return expandSpacingProperties({context, node, propertyValues, fixer, propertyShorthand});
|
|
165
|
+
return expandSpacingProperties({ context, node, propertyValues, fixer, propertyShorthand });
|
|
122
166
|
},
|
|
123
167
|
});
|
|
124
168
|
}
|
|
125
|
-
}
|
|
169
|
+
};
|
|
126
170
|
|
|
127
171
|
export const expandSpacingShorthand: Rule.RuleModule = {
|
|
128
172
|
meta: {
|
|
@@ -130,7 +174,8 @@ export const expandSpacingShorthand: Rule.RuleModule = {
|
|
|
130
174
|
url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/',
|
|
131
175
|
},
|
|
132
176
|
messages: {
|
|
133
|
-
expandSpacingShorthand:
|
|
177
|
+
expandSpacingShorthand:
|
|
178
|
+
'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand',
|
|
134
179
|
},
|
|
135
180
|
type: 'problem',
|
|
136
181
|
fixable: 'code',
|
|
@@ -147,4 +192,4 @@ export const expandSpacingShorthand: Rule.RuleModule = {
|
|
|
147
192
|
},
|
|
148
193
|
};
|
|
149
194
|
|
|
150
|
-
export default expandSpacingShorthand;
|
|
195
|
+
export default expandSpacingShorthand;
|