@atlaskit/eslint-plugin-platform 2.0.1 → 2.1.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 +17 -0
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/rules/compiled/expand-background-shorthand/index.js +2 -17
- package/dist/cjs/rules/compiled/expand-spacing-shorthand/index.js +196 -0
- package/dist/cjs/rules/util/compiled-utils.js +21 -0
- package/dist/cjs/rules/util/context-compat.js +16 -2
- package/dist/es2019/index.js +3 -0
- package/dist/es2019/rules/compiled/expand-background-shorthand/index.js +1 -15
- package/dist/es2019/rules/compiled/expand-spacing-shorthand/index.js +162 -0
- package/dist/es2019/rules/util/compiled-utils.js +15 -0
- package/dist/es2019/rules/util/context-compat.js +15 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/rules/compiled/expand-background-shorthand/index.js +1 -16
- package/dist/esm/rules/compiled/expand-spacing-shorthand/index.js +189 -0
- package/dist/esm/rules/util/compiled-utils.js +16 -0
- package/dist/esm/rules/util/context-compat.js +15 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/rules/compiled/expand-spacing-shorthand/index.d.ts +3 -0
- package/dist/types/rules/util/compiled-utils.d.ts +3 -0
- package/dist/types/rules/util/context-compat.d.ts +22 -1
- package/dist/types-ts4.5/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/compiled/expand-spacing-shorthand/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/util/compiled-utils.d.ts +3 -0
- package/dist/types-ts4.5/rules/util/context-compat.d.ts +22 -1
- package/package.json +3 -3
- package/src/index.tsx +3 -0
- package/src/rules/compiled/expand-background-shorthand/__tests__/rule.test.ts +1 -1
- package/src/rules/compiled/expand-background-shorthand/index.tsx +1 -25
- package/src/rules/compiled/expand-spacing-shorthand/README.md +38 -0
- package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +344 -0
- package/src/rules/compiled/expand-spacing-shorthand/index.ts +150 -0
- package/src/rules/util/__tests__/context-compat.test.ts +59 -1
- package/src/rules/util/compiled-utils.ts +27 -0
- package/src/rules/util/context-compat.ts +14 -1
- package/tsconfig.app.json +0 -1
- package/tsconfig.dev.json +0 -1
- package/tsconfig.json +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/eslint-plugin-platform
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#98759](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/98759)
|
|
8
|
+
[`e6f89962ceaba`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e6f89962ceaba) -
|
|
9
|
+
ESLint rule for expand-spacing-shorthand (i.e. padding and margin)
|
|
10
|
+
|
|
11
|
+
## 2.0.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#182128](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/182128)
|
|
16
|
+
[`c00cde6230838`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c00cde6230838) -
|
|
17
|
+
fix v9 support regression
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 2.0.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/cjs/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var _noAlias = _interopRequireDefault(require("./rules/feature-gating/no-alias")
|
|
|
31
31
|
var _useEntrypointsInExamples = _interopRequireDefault(require("./rules/use-entrypoints-in-examples"));
|
|
32
32
|
var _useRecommendedUtils = _interopRequireDefault(require("./rules/feature-gating/use-recommended-utils"));
|
|
33
33
|
var _expandBackgroundShorthand = _interopRequireDefault(require("./rules/compiled/expand-background-shorthand"));
|
|
34
|
+
var _expandSpacingShorthand = _interopRequireDefault(require("./rules/compiled/expand-spacing-shorthand"));
|
|
34
35
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
35
36
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // eslint-disable-next-line import/no-extraneous-dependencies
|
|
36
37
|
var rules = exports.rules = {
|
|
@@ -44,6 +45,7 @@ var rules = exports.rules = {
|
|
|
44
45
|
'ensure-valid-bin-values': _ensureValidBinValues.default,
|
|
45
46
|
'expand-border-shorthand': _expandBorderShorthand.default,
|
|
46
47
|
'expand-background-shorthand': _expandBackgroundShorthand.default,
|
|
48
|
+
'expand-spacing-shorthand': _expandSpacingShorthand.default,
|
|
47
49
|
'no-duplicate-dependencies': _noDuplicateDependencies.default,
|
|
48
50
|
'no-invalid-feature-flag-usage': _noInvalidFeatureFlagUsage.default,
|
|
49
51
|
'no-pre-post-install-scripts': _noPrePostInstalls.default,
|
|
@@ -70,6 +72,7 @@ var commonConfig = {
|
|
|
70
72
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
71
73
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
72
74
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
75
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'warn',
|
|
73
76
|
'@compiled/jsx-pragma': ['error', {
|
|
74
77
|
importSources: ['@atlaskit/css'],
|
|
75
78
|
onlyRunIfImportingCompiled: true,
|
|
@@ -4,22 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.expandBackgroundShorthand = exports.default = void 0;
|
|
7
|
-
var
|
|
8
|
-
var _contextCompat = require("../../util/context-compat");
|
|
9
|
-
// Checks if the function that holds the border property is using an import package that this rule is targeting
|
|
10
|
-
var isCompiledAPI = function isCompiledAPI(context, node) {
|
|
11
|
-
var importSources = (0, _isSupportedImport.getImportSources)(context);
|
|
12
|
-
var _getScope = (0, _contextCompat.getScope)(context, node),
|
|
13
|
-
references = _getScope.references;
|
|
14
|
-
var ancestors = context.getAncestors();
|
|
15
|
-
if (ancestors.some(function (ancestor) {
|
|
16
|
-
return ancestor.type === 'CallExpression' && ancestor.callee && ((0, _isSupportedImport.isCompiled)(ancestor.callee, references, importSources) || (0, _isSupportedImport.isAtlasKitCSS)(ancestor.callee, references, importSources));
|
|
17
|
-
})) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
return false;
|
|
21
|
-
};
|
|
22
|
-
|
|
7
|
+
var _compiledUtils = require("../../util/compiled-utils");
|
|
23
8
|
// Checks if node is a call expression with identifier 'token'
|
|
24
9
|
var isTokenCallExpression = function isTokenCallExpression(node) {
|
|
25
10
|
if (node.type === 'CallExpression') {
|
|
@@ -43,7 +28,7 @@ var expandBackgroundShorthand = exports.expandBackgroundShorthand = {
|
|
|
43
28
|
create: function create(context) {
|
|
44
29
|
return {
|
|
45
30
|
'Property[key.name="background"]': function PropertyKeyNameBackground(node) {
|
|
46
|
-
if (isCompiledAPI(context, node) && isTokenCallExpression(node.value)) {
|
|
31
|
+
if ((0, _compiledUtils.isCompiledAPI)(context, node) && isTokenCallExpression(node.value)) {
|
|
47
32
|
context.report({
|
|
48
33
|
node: node,
|
|
49
34
|
messageId: 'expandBackgroundShorthand',
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.expandSpacingShorthand = exports.default = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _contextCompat = require("../../util/context-compat");
|
|
10
|
+
var _compiledUtils = require("../../util/compiled-utils");
|
|
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
|
+
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
|
+
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 = ["Top", "Right", "Bottom", "Left"];
|
|
15
|
+
;
|
|
16
|
+
|
|
17
|
+
// Checks if node is a call expression with identifier 'token'
|
|
18
|
+
var isTokenCallExpression = function isTokenCallExpression(node) {
|
|
19
|
+
if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Given a TemplateLiteral node, returns the value of the spacing property as an array of strings
|
|
26
|
+
// e.g. `0 ${token('a')} ${token('b')}` -> ['0', 'token('a')', 'token('b')']
|
|
27
|
+
var parseTemplateLiteral = function parseTemplateLiteral(templateLiteral, context) {
|
|
28
|
+
var expressions = templateLiteral.expressions;
|
|
29
|
+
var quasis = templateLiteral.quasis;
|
|
30
|
+
var propertyValues = [];
|
|
31
|
+
for (var i = 0; i < expressions.length || i < quasis.length; i++) {
|
|
32
|
+
if (i < quasis.length) {
|
|
33
|
+
var cookedQuasi = quasis[i].value.cooked;
|
|
34
|
+
if (cookedQuasi) {
|
|
35
|
+
var splitQuasi = cookedQuasi.split(" ").filter(function (str) {
|
|
36
|
+
return str.length > 0;
|
|
37
|
+
});
|
|
38
|
+
splitQuasi.forEach(function (str) {
|
|
39
|
+
propertyValues.push(isNaN(Number(str)) ? "'".concat(str, "'") : str);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (i < expressions.length) {
|
|
44
|
+
var expr = (0, _contextCompat.getSourceCode)(context).getText(expressions[i]);
|
|
45
|
+
propertyValues.push(expr);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return propertyValues;
|
|
49
|
+
};
|
|
50
|
+
var checkValidPropertyValues = function checkValidPropertyValues(propertyValues) {
|
|
51
|
+
if (!propertyValues.some(function (str) {
|
|
52
|
+
return str.includes("token(");
|
|
53
|
+
})) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (propertyValues.some(function (str) {
|
|
60
|
+
return str.includes("calc(");
|
|
61
|
+
})) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
68
|
+
var expandSpacingProperties = function expandSpacingProperties(_ref) {
|
|
69
|
+
var context = _ref.context,
|
|
70
|
+
node = _ref.node,
|
|
71
|
+
propertyValues = _ref.propertyValues,
|
|
72
|
+
fixer = _ref.fixer,
|
|
73
|
+
propertyShorthand = _ref.propertyShorthand;
|
|
74
|
+
var _propertyValues = (0, _slicedToArray2.default)(propertyValues, 4),
|
|
75
|
+
top = _propertyValues[0],
|
|
76
|
+
_propertyValues$ = _propertyValues[1],
|
|
77
|
+
right = _propertyValues$ === void 0 ? top : _propertyValues$,
|
|
78
|
+
_propertyValues$2 = _propertyValues[2],
|
|
79
|
+
bottom = _propertyValues$2 === void 0 ? top : _propertyValues$2,
|
|
80
|
+
_propertyValues$3 = _propertyValues[3],
|
|
81
|
+
left = _propertyValues$3 === void 0 ? right : _propertyValues$3;
|
|
82
|
+
var spacing = [top, right, bottom, left];
|
|
83
|
+
var fixes = [];
|
|
84
|
+
var parentNode = node.parent;
|
|
85
|
+
if (parentNode && parentNode.type === 'ObjectExpression') {
|
|
86
|
+
var _iterator = _createForOfIteratorHelper(parentNode.properties),
|
|
87
|
+
_step;
|
|
88
|
+
try {
|
|
89
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
90
|
+
var prop = _step.value;
|
|
91
|
+
if (prop.type !== 'Property') {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (prop.key.type === 'Identifier' && prop.range && prop.key.name !== "".concat(propertyShorthand)) {
|
|
95
|
+
for (var i = 0; i < spacing.length; i++) {
|
|
96
|
+
if (prop.key.name === "".concat(propertyShorthand).concat(spacingPos[i])) {
|
|
97
|
+
var _prop$range = (0, _slicedToArray2.default)(prop.range, 2),
|
|
98
|
+
start = _prop$range[0],
|
|
99
|
+
end = _prop$range[1];
|
|
100
|
+
// Remove the entire line for the duplicate property
|
|
101
|
+
while ((0, _contextCompat.getSourceCode)(context).text[end] !== "\n") {
|
|
102
|
+
end += 1;
|
|
103
|
+
}
|
|
104
|
+
while ((0, _contextCompat.getSourceCode)(context).text[start] !== "\n") {
|
|
105
|
+
start -= 1;
|
|
106
|
+
}
|
|
107
|
+
spacing[i] = (0, _contextCompat.getSourceCode)(context).getText(prop.value);
|
|
108
|
+
fixes.push(fixer.removeRange([start, end]));
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch (err) {
|
|
115
|
+
_iterator.e(err);
|
|
116
|
+
} finally {
|
|
117
|
+
_iterator.f();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
fixes.push(fixer.insertTextAfter(node, "".concat(propertyShorthand, "Top: ").concat(spacing[0], ",\n")));
|
|
121
|
+
fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Right: ").concat(spacing[1], ",\n")));
|
|
122
|
+
fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Bottom: ").concat(spacing[2], ",\n")));
|
|
123
|
+
fixes.push(fixer.insertTextAfter(node, "\t".concat(propertyShorthand, "Left: ").concat(spacing[3])));
|
|
124
|
+
fixes.push(fixer.remove(node));
|
|
125
|
+
return fixes;
|
|
126
|
+
};
|
|
127
|
+
var executeExpandSpacingRule = function executeExpandSpacingRule(context, node, propertyShorthand) {
|
|
128
|
+
if (!(0, _compiledUtils.isCompiledAPI)(context, node)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (node.value.type === 'TemplateLiteral') {
|
|
132
|
+
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
133
|
+
var propertyValues = parseTemplateLiteral(node.value, context);
|
|
134
|
+
if (!checkValidPropertyValues(propertyValues)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
context.report({
|
|
138
|
+
node: node,
|
|
139
|
+
messageId: 'expandSpacingShorthand',
|
|
140
|
+
data: {
|
|
141
|
+
property: propertyShorthand
|
|
142
|
+
},
|
|
143
|
+
fix: function fix(fixer) {
|
|
144
|
+
return expandSpacingProperties({
|
|
145
|
+
context: context,
|
|
146
|
+
node: node,
|
|
147
|
+
propertyValues: propertyValues,
|
|
148
|
+
fixer: fixer,
|
|
149
|
+
propertyShorthand: propertyShorthand
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
} else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
|
|
154
|
+
// Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
|
|
155
|
+
var _propertyValues2 = [(0, _contextCompat.getSourceCode)(context).getText(node.value)];
|
|
156
|
+
context.report({
|
|
157
|
+
node: node,
|
|
158
|
+
messageId: 'expandSpacingShorthand',
|
|
159
|
+
data: {
|
|
160
|
+
property: propertyShorthand
|
|
161
|
+
},
|
|
162
|
+
fix: function fix(fixer) {
|
|
163
|
+
return expandSpacingProperties({
|
|
164
|
+
context: context,
|
|
165
|
+
node: node,
|
|
166
|
+
propertyValues: _propertyValues2,
|
|
167
|
+
fixer: fixer,
|
|
168
|
+
propertyShorthand: propertyShorthand
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
var expandSpacingShorthand = exports.expandSpacingShorthand = {
|
|
175
|
+
meta: {
|
|
176
|
+
docs: {
|
|
177
|
+
url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/'
|
|
178
|
+
},
|
|
179
|
+
messages: {
|
|
180
|
+
expandSpacingShorthand: 'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand'
|
|
181
|
+
},
|
|
182
|
+
type: 'problem',
|
|
183
|
+
fixable: 'code'
|
|
184
|
+
},
|
|
185
|
+
create: function create(context) {
|
|
186
|
+
return {
|
|
187
|
+
'Property[key.name="padding"]': function PropertyKeyNamePadding(node) {
|
|
188
|
+
executeExpandSpacingRule(context, node, 'padding');
|
|
189
|
+
},
|
|
190
|
+
'Property[key.name="margin"]': function PropertyKeyNameMargin(node) {
|
|
191
|
+
executeExpandSpacingRule(context, node, 'margin');
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
var _default = exports.default = expandSpacingShorthand;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isCompiledAPI = void 0;
|
|
7
|
+
var _contextCompat = require("./context-compat");
|
|
8
|
+
var _isSupportedImport = require("@atlaskit/eslint-utils/is-supported-import");
|
|
9
|
+
// Checks if the function that holds the property is using a Compiled import package that this rule is targeting
|
|
10
|
+
var isCompiledAPI = exports.isCompiledAPI = function isCompiledAPI(context, node) {
|
|
11
|
+
var importSources = (0, _isSupportedImport.getImportSources)(context);
|
|
12
|
+
var _getScope = (0, _contextCompat.getScope)(context, node),
|
|
13
|
+
references = _getScope.references;
|
|
14
|
+
var ancestors = (0, _contextCompat.getAncestors)(context, node);
|
|
15
|
+
if (ancestors.some(function (ancestor) {
|
|
16
|
+
return ancestor.type === 'CallExpression' && ancestor.callee && ((0, _isSupportedImport.isCompiled)(ancestor.callee, references, importSources) || (0, _isSupportedImport.isAtlasKitCSS)(ancestor.callee, references, importSources));
|
|
17
|
+
})) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getScope = void 0;
|
|
6
|
+
exports.getSourceCode = exports.getScope = exports.getAncestors = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* TODO: Consider whether this should be replaced by ESLint's compat library.
|
|
9
9
|
* Either way, this should be removed once we no longer need to support ESLint versions less than 8.40.
|
|
@@ -15,7 +15,7 @@ exports.getScope = void 0;
|
|
|
15
15
|
* `context.getSourceCode()` is deprecated in v8 and removed in v9.
|
|
16
16
|
* @param context - The ESLint rule context
|
|
17
17
|
*/
|
|
18
|
-
var getSourceCode = function getSourceCode(context) {
|
|
18
|
+
var getSourceCode = exports.getSourceCode = function getSourceCode(context) {
|
|
19
19
|
var _context$sourceCode;
|
|
20
20
|
return (_context$sourceCode = context.sourceCode) !== null && _context$sourceCode !== void 0 ? _context$sourceCode : context.getSourceCode();
|
|
21
21
|
};
|
|
@@ -24,10 +24,24 @@ var getSourceCode = function getSourceCode(context) {
|
|
|
24
24
|
* A compatibility layer to support older versions of ESLint.
|
|
25
25
|
* `context.sourceCode.getScope()` is the preferred way to access Scope, as
|
|
26
26
|
* `context.getScope()` was removed in v9.
|
|
27
|
+
* https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context.getscope()
|
|
27
28
|
* @param context - The ESLint rule context
|
|
28
29
|
* @param node - The node to get the scope for
|
|
29
30
|
*/
|
|
30
31
|
var getScope = exports.getScope = function getScope(context, node) {
|
|
31
32
|
var _getSourceCode$getSco, _getSourceCode, _getSourceCode$getSco2;
|
|
32
33
|
return (_getSourceCode$getSco = (_getSourceCode = getSourceCode(context)) === null || _getSourceCode === void 0 || (_getSourceCode$getSco2 = _getSourceCode.getScope) === null || _getSourceCode$getSco2 === void 0 ? void 0 : _getSourceCode$getSco2.call(_getSourceCode, node)) !== null && _getSourceCode$getSco !== void 0 ? _getSourceCode$getSco : context.getScope();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A compatibility layer to support older versions of ESLint.
|
|
38
|
+
* `context.sourceCode.getAncestors()` is the preferred way to access Ancestors, as
|
|
39
|
+
* `context.getScope()` was removed in v9.
|
|
40
|
+
* https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context.getancestors()
|
|
41
|
+
* @param context - The ESLint rule context
|
|
42
|
+
* @param node - The node to get the scope for
|
|
43
|
+
*/
|
|
44
|
+
var getAncestors = exports.getAncestors = function getAncestors(context, node) {
|
|
45
|
+
var _getSourceCode$getAnc, _getSourceCode2, _getSourceCode2$getAn;
|
|
46
|
+
return (_getSourceCode$getAnc = (_getSourceCode2 = getSourceCode(context)) === null || _getSourceCode2 === void 0 || (_getSourceCode2$getAn = _getSourceCode2.getAncestors) === null || _getSourceCode2$getAn === void 0 ? void 0 : _getSourceCode2$getAn.call(_getSourceCode2, node)) !== null && _getSourceCode$getAnc !== void 0 ? _getSourceCode$getAnc : context.getAncestors();
|
|
33
47
|
};
|
package/dist/es2019/index.js
CHANGED
|
@@ -25,6 +25,7 @@ import noAlias from './rules/feature-gating/no-alias';
|
|
|
25
25
|
import useEntrypointsInExamples from './rules/use-entrypoints-in-examples';
|
|
26
26
|
import useRecommendedUtils from './rules/feature-gating/use-recommended-utils';
|
|
27
27
|
import expandBackgroundShorthand from './rules/compiled/expand-background-shorthand';
|
|
28
|
+
import expandSpacingShorthand from './rules/compiled/expand-spacing-shorthand';
|
|
28
29
|
export const rules = {
|
|
29
30
|
'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
|
|
30
31
|
'ensure-feature-flag-prefix': ensureFeatureFlagPrefix,
|
|
@@ -36,6 +37,7 @@ export const rules = {
|
|
|
36
37
|
'ensure-valid-bin-values': ensureValidBinValues,
|
|
37
38
|
'expand-border-shorthand': expandBorderShorthand,
|
|
38
39
|
'expand-background-shorthand': expandBackgroundShorthand,
|
|
40
|
+
'expand-spacing-shorthand': expandSpacingShorthand,
|
|
39
41
|
'no-duplicate-dependencies': noDuplicateDependencies,
|
|
40
42
|
'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
|
|
41
43
|
'no-pre-post-install-scripts': noPreAndPostInstallScripts,
|
|
@@ -62,6 +64,7 @@ const commonConfig = {
|
|
|
62
64
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
63
65
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
64
66
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
67
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'warn',
|
|
65
68
|
'@compiled/jsx-pragma': ['error', {
|
|
66
69
|
importSources: ['@atlaskit/css'],
|
|
67
70
|
onlyRunIfImportingCompiled: true,
|
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getScope } from '../../util/context-compat';
|
|
3
|
-
|
|
4
|
-
// Checks if the function that holds the border property is using an import package that this rule is targeting
|
|
5
|
-
const isCompiledAPI = (context, node) => {
|
|
6
|
-
const importSources = getImportSources(context);
|
|
7
|
-
const {
|
|
8
|
-
references
|
|
9
|
-
} = getScope(context, node);
|
|
10
|
-
const ancestors = context.getAncestors();
|
|
11
|
-
if (ancestors.some(ancestor => ancestor.type === 'CallExpression' && ancestor.callee && (isCompiled(ancestor.callee, references, importSources) || isAtlasKitCSS(ancestor.callee, references, importSources)))) {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
};
|
|
1
|
+
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
16
2
|
|
|
17
3
|
// Checks if node is a call expression with identifier 'token'
|
|
18
4
|
const isTokenCallExpression = node => {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { getSourceCode } from '../../util/context-compat';
|
|
2
|
+
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
3
|
+
const spacingPos = ["Top", "Right", "Bottom", "Left"];
|
|
4
|
+
;
|
|
5
|
+
|
|
6
|
+
// Checks if node is a call expression with identifier 'token'
|
|
7
|
+
const isTokenCallExpression = node => {
|
|
8
|
+
if (node.callee.type === 'Identifier' && node.callee.name === 'token') {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return false;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Given a TemplateLiteral node, returns the value of the spacing property as an array of strings
|
|
15
|
+
// e.g. `0 ${token('a')} ${token('b')}` -> ['0', 'token('a')', 'token('b')']
|
|
16
|
+
const parseTemplateLiteral = (templateLiteral, context) => {
|
|
17
|
+
const expressions = templateLiteral.expressions;
|
|
18
|
+
const quasis = templateLiteral.quasis;
|
|
19
|
+
let propertyValues = [];
|
|
20
|
+
for (let i = 0; i < expressions.length || i < quasis.length; i++) {
|
|
21
|
+
if (i < quasis.length) {
|
|
22
|
+
const cookedQuasi = quasis[i].value.cooked;
|
|
23
|
+
if (cookedQuasi) {
|
|
24
|
+
const splitQuasi = cookedQuasi.split(" ").filter(str => str.length > 0);
|
|
25
|
+
splitQuasi.forEach(str => {
|
|
26
|
+
propertyValues.push(isNaN(Number(str)) ? `'${str}'` : str);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (i < expressions.length) {
|
|
31
|
+
const expr = getSourceCode(context).getText(expressions[i]);
|
|
32
|
+
propertyValues.push(expr);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return propertyValues;
|
|
36
|
+
};
|
|
37
|
+
const checkValidPropertyValues = propertyValues => {
|
|
38
|
+
if (!propertyValues.some(str => str.includes("token("))) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (propertyValues.length < 1 || propertyValues.length > 4) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (propertyValues.some(str => str.includes("calc("))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// To fix spacing shorthands, given a list of spacing property values, expands the spacing property and adds autofix fixes
|
|
51
|
+
const expandSpacingProperties = ({
|
|
52
|
+
context,
|
|
53
|
+
node,
|
|
54
|
+
propertyValues,
|
|
55
|
+
fixer,
|
|
56
|
+
propertyShorthand
|
|
57
|
+
}) => {
|
|
58
|
+
const [top, right = top, bottom = top, left = right] = propertyValues;
|
|
59
|
+
const spacing = [top, right, bottom, left];
|
|
60
|
+
const fixes = [];
|
|
61
|
+
const parentNode = node.parent;
|
|
62
|
+
if (parentNode && parentNode.type === 'ObjectExpression') {
|
|
63
|
+
for (var prop of parentNode.properties) {
|
|
64
|
+
if (prop.type !== 'Property') {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (prop.key.type === 'Identifier' && prop.range && prop.key.name !== `${propertyShorthand}`) {
|
|
68
|
+
for (let i = 0; i < spacing.length; i++) {
|
|
69
|
+
if (prop.key.name === `${propertyShorthand}${spacingPos[i]}`) {
|
|
70
|
+
let [start, end] = prop.range;
|
|
71
|
+
// Remove the entire line for the duplicate property
|
|
72
|
+
while (getSourceCode(context).text[end] !== "\n") {
|
|
73
|
+
end += 1;
|
|
74
|
+
}
|
|
75
|
+
while (getSourceCode(context).text[start] !== "\n") {
|
|
76
|
+
start -= 1;
|
|
77
|
+
}
|
|
78
|
+
spacing[i] = getSourceCode(context).getText(prop.value);
|
|
79
|
+
fixes.push(fixer.removeRange([start, end]));
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
fixes.push(fixer.insertTextAfter(node, `${propertyShorthand}Top: ${spacing[0]},\n`));
|
|
87
|
+
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Right: ${spacing[1]},\n`));
|
|
88
|
+
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Bottom: ${spacing[2]},\n`));
|
|
89
|
+
fixes.push(fixer.insertTextAfter(node, `\t${propertyShorthand}Left: ${spacing[3]}`));
|
|
90
|
+
fixes.push(fixer.remove(node));
|
|
91
|
+
return fixes;
|
|
92
|
+
};
|
|
93
|
+
const executeExpandSpacingRule = (context, node, propertyShorthand) => {
|
|
94
|
+
if (!isCompiledAPI(context, node)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (node.value.type === 'TemplateLiteral') {
|
|
98
|
+
// Value of spacing property is a TemplateLiteral type that contains a token, e.g. padding: `0 token('a')`
|
|
99
|
+
const propertyValues = parseTemplateLiteral(node.value, context);
|
|
100
|
+
if (!checkValidPropertyValues(propertyValues)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
context.report({
|
|
104
|
+
node,
|
|
105
|
+
messageId: 'expandSpacingShorthand',
|
|
106
|
+
data: {
|
|
107
|
+
property: propertyShorthand
|
|
108
|
+
},
|
|
109
|
+
fix(fixer) {
|
|
110
|
+
return expandSpacingProperties({
|
|
111
|
+
context,
|
|
112
|
+
node,
|
|
113
|
+
propertyValues,
|
|
114
|
+
fixer,
|
|
115
|
+
propertyShorthand
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
} else if (node.value.type === 'CallExpression' && isTokenCallExpression(node.value)) {
|
|
120
|
+
// Value of spacing property is a token CallExpression type, e.g. margin: token('space.100', '8px')
|
|
121
|
+
const propertyValues = [getSourceCode(context).getText(node.value)];
|
|
122
|
+
context.report({
|
|
123
|
+
node,
|
|
124
|
+
messageId: 'expandSpacingShorthand',
|
|
125
|
+
data: {
|
|
126
|
+
property: propertyShorthand
|
|
127
|
+
},
|
|
128
|
+
fix(fixer) {
|
|
129
|
+
return expandSpacingProperties({
|
|
130
|
+
context,
|
|
131
|
+
node,
|
|
132
|
+
propertyValues,
|
|
133
|
+
fixer,
|
|
134
|
+
propertyShorthand
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
export const expandSpacingShorthand = {
|
|
141
|
+
meta: {
|
|
142
|
+
docs: {
|
|
143
|
+
url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/expand-spacing-shorthand/'
|
|
144
|
+
},
|
|
145
|
+
messages: {
|
|
146
|
+
expandSpacingShorthand: 'Use {{ property }}Top, {{ property }}Right, {{ property }}Bottom and {{ property }}Left instead of {{ property }} shorthand'
|
|
147
|
+
},
|
|
148
|
+
type: 'problem',
|
|
149
|
+
fixable: 'code'
|
|
150
|
+
},
|
|
151
|
+
create(context) {
|
|
152
|
+
return {
|
|
153
|
+
'Property[key.name="padding"]': function (node) {
|
|
154
|
+
executeExpandSpacingRule(context, node, 'padding');
|
|
155
|
+
},
|
|
156
|
+
'Property[key.name="margin"]': function (node) {
|
|
157
|
+
executeExpandSpacingRule(context, node, 'margin');
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
export default expandSpacingShorthand;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getAncestors, getScope } from './context-compat';
|
|
2
|
+
import { getImportSources, isCompiled, isAtlasKitCSS } from '@atlaskit/eslint-utils/is-supported-import';
|
|
3
|
+
|
|
4
|
+
// Checks if the function that holds the property is using a Compiled import package that this rule is targeting
|
|
5
|
+
export const isCompiledAPI = (context, node) => {
|
|
6
|
+
const importSources = getImportSources(context);
|
|
7
|
+
const {
|
|
8
|
+
references
|
|
9
|
+
} = getScope(context, node);
|
|
10
|
+
const ancestors = getAncestors(context, node);
|
|
11
|
+
if (ancestors.some(ancestor => ancestor.type === 'CallExpression' && ancestor.callee && (isCompiled(ancestor.callee, references, importSources) || isAtlasKitCSS(ancestor.callee, references, importSources)))) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* `context.getSourceCode()` is deprecated in v8 and removed in v9.
|
|
10
10
|
* @param context - The ESLint rule context
|
|
11
11
|
*/
|
|
12
|
-
const getSourceCode = context => {
|
|
12
|
+
export const getSourceCode = context => {
|
|
13
13
|
var _context$sourceCode;
|
|
14
14
|
return (_context$sourceCode = context.sourceCode) !== null && _context$sourceCode !== void 0 ? _context$sourceCode : context.getSourceCode();
|
|
15
15
|
};
|
|
@@ -18,10 +18,24 @@ const getSourceCode = context => {
|
|
|
18
18
|
* A compatibility layer to support older versions of ESLint.
|
|
19
19
|
* `context.sourceCode.getScope()` is the preferred way to access Scope, as
|
|
20
20
|
* `context.getScope()` was removed in v9.
|
|
21
|
+
* https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context.getscope()
|
|
21
22
|
* @param context - The ESLint rule context
|
|
22
23
|
* @param node - The node to get the scope for
|
|
23
24
|
*/
|
|
24
25
|
export const getScope = (context, node) => {
|
|
25
26
|
var _getSourceCode$getSco, _getSourceCode, _getSourceCode$getSco2;
|
|
26
27
|
return (_getSourceCode$getSco = (_getSourceCode = getSourceCode(context)) === null || _getSourceCode === void 0 ? void 0 : (_getSourceCode$getSco2 = _getSourceCode.getScope) === null || _getSourceCode$getSco2 === void 0 ? void 0 : _getSourceCode$getSco2.call(_getSourceCode, node)) !== null && _getSourceCode$getSco !== void 0 ? _getSourceCode$getSco : context.getScope();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A compatibility layer to support older versions of ESLint.
|
|
32
|
+
* `context.sourceCode.getAncestors()` is the preferred way to access Ancestors, as
|
|
33
|
+
* `context.getScope()` was removed in v9.
|
|
34
|
+
* https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context.getancestors()
|
|
35
|
+
* @param context - The ESLint rule context
|
|
36
|
+
* @param node - The node to get the scope for
|
|
37
|
+
*/
|
|
38
|
+
export const getAncestors = (context, node) => {
|
|
39
|
+
var _getSourceCode$getAnc, _getSourceCode2, _getSourceCode2$getAn;
|
|
40
|
+
return (_getSourceCode$getAnc = (_getSourceCode2 = getSourceCode(context)) === null || _getSourceCode2 === void 0 ? void 0 : (_getSourceCode2$getAn = _getSourceCode2.getAncestors) === null || _getSourceCode2$getAn === void 0 ? void 0 : _getSourceCode2$getAn.call(_getSourceCode2, node)) !== null && _getSourceCode$getAnc !== void 0 ? _getSourceCode$getAnc : context.getAncestors();
|
|
27
41
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import noAlias from './rules/feature-gating/no-alias';
|
|
|
28
28
|
import useEntrypointsInExamples from './rules/use-entrypoints-in-examples';
|
|
29
29
|
import useRecommendedUtils from './rules/feature-gating/use-recommended-utils';
|
|
30
30
|
import expandBackgroundShorthand from './rules/compiled/expand-background-shorthand';
|
|
31
|
+
import expandSpacingShorthand from './rules/compiled/expand-spacing-shorthand';
|
|
31
32
|
export var rules = {
|
|
32
33
|
'ensure-feature-flag-registration': ensureFeatureFlagRegistration,
|
|
33
34
|
'ensure-feature-flag-prefix': ensureFeatureFlagPrefix,
|
|
@@ -39,6 +40,7 @@ export var rules = {
|
|
|
39
40
|
'ensure-valid-bin-values': ensureValidBinValues,
|
|
40
41
|
'expand-border-shorthand': expandBorderShorthand,
|
|
41
42
|
'expand-background-shorthand': expandBackgroundShorthand,
|
|
43
|
+
'expand-spacing-shorthand': expandSpacingShorthand,
|
|
42
44
|
'no-duplicate-dependencies': noDuplicateDependencies,
|
|
43
45
|
'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
|
|
44
46
|
'no-pre-post-install-scripts': noPreAndPostInstallScripts,
|
|
@@ -65,6 +67,7 @@ var commonConfig = {
|
|
|
65
67
|
// Compiled: rules that are not included via `@compiled/recommended
|
|
66
68
|
'@atlaskit/platform/expand-border-shorthand': 'error',
|
|
67
69
|
'@atlaskit/platform/expand-background-shorthand': 'error',
|
|
70
|
+
'@atlaskit/platform/expand-spacing-shorthand': 'warn',
|
|
68
71
|
'@compiled/jsx-pragma': ['error', {
|
|
69
72
|
importSources: ['@atlaskit/css'],
|
|
70
73
|
onlyRunIfImportingCompiled: true,
|
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getScope } from '../../util/context-compat';
|
|
3
|
-
|
|
4
|
-
// Checks if the function that holds the border property is using an import package that this rule is targeting
|
|
5
|
-
var isCompiledAPI = function isCompiledAPI(context, node) {
|
|
6
|
-
var importSources = getImportSources(context);
|
|
7
|
-
var _getScope = getScope(context, node),
|
|
8
|
-
references = _getScope.references;
|
|
9
|
-
var ancestors = context.getAncestors();
|
|
10
|
-
if (ancestors.some(function (ancestor) {
|
|
11
|
-
return ancestor.type === 'CallExpression' && ancestor.callee && (isCompiled(ancestor.callee, references, importSources) || isAtlasKitCSS(ancestor.callee, references, importSources));
|
|
12
|
-
})) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
return false;
|
|
16
|
-
};
|
|
1
|
+
import { isCompiledAPI } from '../../util/compiled-utils';
|
|
17
2
|
|
|
18
3
|
// Checks if node is a call expression with identifier 'token'
|
|
19
4
|
var isTokenCallExpression = function isTokenCallExpression(node) {
|