@atlaskit/eslint-plugin-design-system 8.25.2 → 8.26.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/README.md +4 -0
- package/constellation/index/usage.mdx +362 -0
- package/dist/cjs/presets/all.codegen.js +5 -1
- package/dist/cjs/presets/recommended.codegen.js +5 -1
- package/dist/cjs/rules/index.codegen.js +9 -1
- package/dist/cjs/rules/no-empty-styled-expression/index.js +75 -0
- package/dist/cjs/rules/no-exported-css/index.js +37 -0
- package/dist/cjs/rules/no-exported-keyframes/index.js +37 -0
- package/dist/cjs/rules/no-invalid-css-map/index.js +102 -0
- package/dist/cjs/rules/no-invalid-css-map/utils.js +193 -0
- package/dist/cjs/rules/utils/create-no-exported-rule/check-if-supported-export.js +158 -0
- package/dist/cjs/rules/utils/create-no-exported-rule/is-styled-component.js +84 -0
- package/dist/cjs/rules/utils/create-no-exported-rule/main.js +66 -0
- package/dist/cjs/rules/utils/is-supported-import.js +51 -15
- package/dist/es2019/presets/all.codegen.js +5 -1
- package/dist/es2019/presets/recommended.codegen.js +5 -1
- package/dist/es2019/rules/index.codegen.js +9 -1
- package/dist/es2019/rules/no-empty-styled-expression/index.js +65 -0
- package/dist/es2019/rules/no-exported-css/index.js +31 -0
- package/dist/es2019/rules/no-exported-keyframes/index.js +31 -0
- package/dist/es2019/rules/no-invalid-css-map/index.js +95 -0
- package/dist/es2019/rules/no-invalid-css-map/utils.js +134 -0
- package/dist/es2019/rules/utils/create-no-exported-rule/check-if-supported-export.js +142 -0
- package/dist/es2019/rules/utils/create-no-exported-rule/is-styled-component.js +74 -0
- package/dist/es2019/rules/utils/create-no-exported-rule/main.js +59 -0
- package/dist/es2019/rules/utils/is-supported-import.js +48 -14
- package/dist/esm/presets/all.codegen.js +5 -1
- package/dist/esm/presets/recommended.codegen.js +5 -1
- package/dist/esm/rules/index.codegen.js +9 -1
- package/dist/esm/rules/no-empty-styled-expression/index.js +68 -0
- package/dist/esm/rules/no-exported-css/index.js +31 -0
- package/dist/esm/rules/no-exported-keyframes/index.js +31 -0
- package/dist/esm/rules/no-invalid-css-map/index.js +96 -0
- package/dist/esm/rules/no-invalid-css-map/utils.js +186 -0
- package/dist/esm/rules/utils/create-no-exported-rule/check-if-supported-export.js +151 -0
- package/dist/esm/rules/utils/create-no-exported-rule/is-styled-component.js +78 -0
- package/dist/esm/rules/utils/create-no-exported-rule/main.js +60 -0
- package/dist/esm/rules/utils/is-supported-import.js +49 -14
- package/dist/types/index.codegen.d.ts +8 -0
- package/dist/types/presets/all.codegen.d.ts +5 -1
- package/dist/types/presets/recommended.codegen.d.ts +5 -1
- package/dist/types/rules/index.codegen.d.ts +4 -0
- package/dist/types/rules/no-empty-styled-expression/index.d.ts +3 -0
- package/dist/types/rules/no-exported-css/index.d.ts +3 -0
- package/dist/types/rules/no-exported-keyframes/index.d.ts +3 -0
- package/dist/types/rules/no-invalid-css-map/index.d.ts +3 -0
- package/dist/types/rules/no-invalid-css-map/utils.d.ts +14 -0
- package/dist/types/rules/utils/create-no-exported-rule/check-if-supported-export.d.ts +15 -0
- package/dist/types/rules/utils/create-no-exported-rule/is-styled-component.d.ts +14 -0
- package/dist/types/rules/utils/create-no-exported-rule/main.d.ts +19 -0
- package/dist/types/rules/utils/create-rule.d.ts +1 -1
- package/dist/types/rules/utils/is-supported-import.d.ts +25 -8
- package/dist/types-ts4.5/index.codegen.d.ts +8 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +5 -1
- package/dist/types-ts4.5/presets/recommended.codegen.d.ts +5 -1
- package/dist/types-ts4.5/rules/index.codegen.d.ts +4 -0
- package/dist/types-ts4.5/rules/no-empty-styled-expression/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-exported-css/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-exported-keyframes/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-invalid-css-map/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-invalid-css-map/utils.d.ts +14 -0
- package/dist/types-ts4.5/rules/utils/create-no-exported-rule/check-if-supported-export.d.ts +15 -0
- package/dist/types-ts4.5/rules/utils/create-no-exported-rule/is-styled-component.d.ts +14 -0
- package/dist/types-ts4.5/rules/utils/create-no-exported-rule/main.d.ts +19 -0
- package/dist/types-ts4.5/rules/utils/create-rule.d.ts +1 -1
- package/dist/types-ts4.5/rules/utils/is-supported-import.d.ts +25 -8
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
4
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
5
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
6
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
7
|
+
export var getCssMapObject = function getCssMapObject(node) {
|
|
8
|
+
// We assume the argument `node` is already a cssMap() call.
|
|
9
|
+
|
|
10
|
+
// Things like the number of arguments to cssMap and the type of
|
|
11
|
+
// cssMap's argument are handled by the TypeScript compiler, so
|
|
12
|
+
// we don't bother with creating eslint errors for these here
|
|
13
|
+
|
|
14
|
+
if (node.arguments.length !== 1 || node.arguments[0].type !== 'ObjectExpression') {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
return node.arguments[0];
|
|
18
|
+
};
|
|
19
|
+
var findNodeReference = function findNodeReference(references, node) {
|
|
20
|
+
return references.find(function (reference) {
|
|
21
|
+
return reference.identifier === node;
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
var getAllowedFunctionCalls = function getAllowedFunctionCalls(options) {
|
|
25
|
+
var _options$;
|
|
26
|
+
if (options.length === 0 || ((_options$ = options[0]) === null || _options$ === void 0 ? void 0 : _options$.allowedFunctionCalls) === undefined) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Beyond the basic check of "does allowedFunctionCalls exist?",
|
|
31
|
+
// we assume ESLint's rule checker type checks the contents of allowedFunctionCalls
|
|
32
|
+
// as it should
|
|
33
|
+
return options[0].allowedFunctionCalls;
|
|
34
|
+
};
|
|
35
|
+
export var CssMapObjectChecker = /*#__PURE__*/function () {
|
|
36
|
+
function CssMapObjectChecker(cssMapObject, context) {
|
|
37
|
+
_classCallCheck(this, CssMapObjectChecker);
|
|
38
|
+
this.allowedFunctionCalls = getAllowedFunctionCalls(context.options);
|
|
39
|
+
this.cssMapObject = cssMapObject;
|
|
40
|
+
this.report = context.report;
|
|
41
|
+
this.references = context.getScope().references;
|
|
42
|
+
}
|
|
43
|
+
_createClass(CssMapObjectChecker, [{
|
|
44
|
+
key: "isNotWhitelistedFunction",
|
|
45
|
+
value: function isNotWhitelistedFunction(callee) {
|
|
46
|
+
var _reference$resolved,
|
|
47
|
+
_this = this;
|
|
48
|
+
if (callee.type !== 'Identifier' || this.allowedFunctionCalls.length === 0) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
var reference = findNodeReference(this.references, callee);
|
|
52
|
+
var definitions = reference === null || reference === void 0 || (_reference$resolved = reference.resolved) === null || _reference$resolved === void 0 ? void 0 : _reference$resolved.defs;
|
|
53
|
+
if (!definitions) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return definitions.some(function (definition) {
|
|
57
|
+
// We add some restrictions to keep this simple...
|
|
58
|
+
// Forbid non-imported functions
|
|
59
|
+
if (definition.type !== 'ImportBinding') {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// Forbid default imports (e.g. `import React from 'react'`)
|
|
63
|
+
if (definition.node.type !== 'ImportSpecifier') {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
var packageName = definition.parent.source.value;
|
|
67
|
+
var importedFunctionName = definition.node.imported.name;
|
|
68
|
+
return !_this.allowedFunctionCalls.some(function (_ref) {
|
|
69
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
70
|
+
allowedPackageName = _ref2[0],
|
|
71
|
+
allowedFunctionName = _ref2[1];
|
|
72
|
+
return allowedPackageName === packageName && allowedFunctionName === importedFunctionName;
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}, {
|
|
77
|
+
key: "checkCssMapObjectValue",
|
|
78
|
+
value: function checkCssMapObjectValue(value) {
|
|
79
|
+
if (value.type === 'CallExpression' && this.isNotWhitelistedFunction(value.callee)) {
|
|
80
|
+
// object value is a function call in the style
|
|
81
|
+
// {
|
|
82
|
+
// key: functionCall(), ...
|
|
83
|
+
// }
|
|
84
|
+
this.report({
|
|
85
|
+
node: value,
|
|
86
|
+
messageId: 'noFunctionCalls'
|
|
87
|
+
});
|
|
88
|
+
} else if (value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression') {
|
|
89
|
+
// object value is a function call in the style
|
|
90
|
+
// {
|
|
91
|
+
// key: (prop) => prop.color, // ArrowFunctionExpression
|
|
92
|
+
// get danger() { return { ... } }, // FunctionExpression
|
|
93
|
+
// }
|
|
94
|
+
this.report({
|
|
95
|
+
node: value,
|
|
96
|
+
messageId: 'noInlineFunctions'
|
|
97
|
+
});
|
|
98
|
+
} else if (value.type === 'BinaryExpression' || value.type === 'LogicalExpression') {
|
|
99
|
+
this.checkCssMapObjectValue(value.left);
|
|
100
|
+
this.checkCssMapObjectValue(value.right);
|
|
101
|
+
} else if (value.type === 'Identifier') {
|
|
102
|
+
var _reference$resolved2;
|
|
103
|
+
var reference = findNodeReference(this.references, value);
|
|
104
|
+
|
|
105
|
+
// Get the variable's definition when initialised. Assume that the last definition
|
|
106
|
+
// is the most recent one.
|
|
107
|
+
//
|
|
108
|
+
// Ideally we would try to get the variable's value at the point at which
|
|
109
|
+
// cssMap() is run, but ESLint doesn't seem to give us an easy way to
|
|
110
|
+
// do that...
|
|
111
|
+
var definitions = reference === null || reference === void 0 || (_reference$resolved2 = reference.resolved) === null || _reference$resolved2 === void 0 ? void 0 : _reference$resolved2.defs;
|
|
112
|
+
if (!definitions || definitions.length === 0) {
|
|
113
|
+
// Variable is not defined :thinking:
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
var _iterator = _createForOfIteratorHelper(definitions),
|
|
117
|
+
_step;
|
|
118
|
+
try {
|
|
119
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
120
|
+
var definition = _step.value;
|
|
121
|
+
if (definition.type === 'Variable' && definition.node.init) {
|
|
122
|
+
return this.checkCssMapObjectValue(definition.node.init);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (err) {
|
|
126
|
+
_iterator.e(err);
|
|
127
|
+
} finally {
|
|
128
|
+
_iterator.f();
|
|
129
|
+
}
|
|
130
|
+
} else if (value.type === 'ObjectExpression') {
|
|
131
|
+
// Object inside another object
|
|
132
|
+
this.checkCssMapObject(value);
|
|
133
|
+
} else if (value.type === 'TemplateLiteral') {
|
|
134
|
+
// object value is a template literal, something like
|
|
135
|
+
// `hello world`
|
|
136
|
+
// `hello ${functionCall()} world`
|
|
137
|
+
// `hello ${someVariable} world`
|
|
138
|
+
// etc.
|
|
139
|
+
//
|
|
140
|
+
// where the expressions are the parts enclosed within the
|
|
141
|
+
// ${ ... }
|
|
142
|
+
var _iterator2 = _createForOfIteratorHelper(value.expressions),
|
|
143
|
+
_step2;
|
|
144
|
+
try {
|
|
145
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
146
|
+
var expression = _step2.value;
|
|
147
|
+
this.checkCssMapObjectValue(expression);
|
|
148
|
+
}
|
|
149
|
+
} catch (err) {
|
|
150
|
+
_iterator2.e(err);
|
|
151
|
+
} finally {
|
|
152
|
+
_iterator2.f();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}, {
|
|
157
|
+
key: "checkCssMapObject",
|
|
158
|
+
value: function checkCssMapObject(cssMapObject) {
|
|
159
|
+
var _iterator3 = _createForOfIteratorHelper(cssMapObject.properties),
|
|
160
|
+
_step3;
|
|
161
|
+
try {
|
|
162
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
163
|
+
var property = _step3.value;
|
|
164
|
+
if (property.type === 'SpreadElement') {
|
|
165
|
+
this.report({
|
|
166
|
+
node: property,
|
|
167
|
+
messageId: 'noSpreadElement'
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
this.checkCssMapObjectValue(property.value);
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
_iterator3.e(err);
|
|
175
|
+
} finally {
|
|
176
|
+
_iterator3.f();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}, {
|
|
180
|
+
key: "run",
|
|
181
|
+
value: function run() {
|
|
182
|
+
this.checkCssMapObject(this.cssMapObject);
|
|
183
|
+
}
|
|
184
|
+
}]);
|
|
185
|
+
return CssMapObjectChecker;
|
|
186
|
+
}();
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
5
|
+
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; }
|
|
6
|
+
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) { _defineProperty(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; }
|
|
7
|
+
import { isStyledComponent } from './is-styled-component';
|
|
8
|
+
var getStack = function getStack(context, node) {
|
|
9
|
+
var _scope;
|
|
10
|
+
var _context$getSourceCod = context.getSourceCode(),
|
|
11
|
+
scopeManager = _context$getSourceCod.scopeManager;
|
|
12
|
+
var stack = {
|
|
13
|
+
nodes: [],
|
|
14
|
+
root: node
|
|
15
|
+
};
|
|
16
|
+
var scope;
|
|
17
|
+
for (var current = node; current.type !== 'Program'; current = current.parent) {
|
|
18
|
+
if (!scope) {
|
|
19
|
+
var currentScope = scopeManager.acquire(current);
|
|
20
|
+
if (currentScope) {
|
|
21
|
+
scope = currentScope;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
switch (current.type) {
|
|
25
|
+
case 'ExportDefaultDeclaration':
|
|
26
|
+
case 'ExportNamedDeclaration':
|
|
27
|
+
stack.root = current;
|
|
28
|
+
break;
|
|
29
|
+
case 'VariableDeclarator':
|
|
30
|
+
stack.root = current;
|
|
31
|
+
break;
|
|
32
|
+
case 'ExportSpecifier':
|
|
33
|
+
case 'ObjectExpression':
|
|
34
|
+
case 'VariableDeclaration':
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
stack.nodes.unshift(current);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return _objectSpread(_objectSpread({}, stack), {}, {
|
|
41
|
+
scope: (_scope = scope) !== null && _scope !== void 0 ? _scope : context.getScope()
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var matches = function matches(defs, refs) {
|
|
45
|
+
// When there are no defs, the definition is inlined. This must be a match as we know the refs contain the initial
|
|
46
|
+
// definition.
|
|
47
|
+
if (!defs.length) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// When there are no refs, the reference refers to the entire definition and therefore must be a match.
|
|
52
|
+
if (!refs.length) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// When both the references and definitions exist, they should match in length
|
|
57
|
+
if (defs.length !== refs.length) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return defs.every(function (def, i) {
|
|
61
|
+
var ref = refs[i];
|
|
62
|
+
if (def.type === 'Property') {
|
|
63
|
+
// There is a match between the def and the ref when both names match:
|
|
64
|
+
//
|
|
65
|
+
// const fooDef = { bar: '' };
|
|
66
|
+
// const barRef = fooDef.bar
|
|
67
|
+
//
|
|
68
|
+
// There is no match when the ref property does not match the definition key name:
|
|
69
|
+
//
|
|
70
|
+
// const barRef = fooDef.notFound
|
|
71
|
+
return def.key.type === 'Identifier' && ref.type === 'MemberExpression' && ref.property.type === 'Identifier' && ref.property.name === def.key.name;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Anything here is either unsupported or should not match...
|
|
75
|
+
return false;
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
export var checkIfSupportedExport = function checkIfSupportedExport(context, node, importSources) {
|
|
79
|
+
var _resolved$references;
|
|
80
|
+
var scope = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : context.getScope();
|
|
81
|
+
// Ignore any expression defined outside of the global or module scope as we have no way of statically analysing them
|
|
82
|
+
if (scope.type !== 'global' && scope.type !== 'module') {
|
|
83
|
+
return {
|
|
84
|
+
isExport: false
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
var _getStack = getStack(context, node.parent),
|
|
88
|
+
root = _getStack.root,
|
|
89
|
+
nodes = _getStack.nodes;
|
|
90
|
+
// Exporting a component with a css reference should be allowed
|
|
91
|
+
if (isStyledComponent(nodes, context, importSources)) {
|
|
92
|
+
return {
|
|
93
|
+
isExport: false
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (root.type === 'ExportDefaultDeclaration' || root.type === 'ExportNamedDeclaration') {
|
|
97
|
+
return {
|
|
98
|
+
isExport: true,
|
|
99
|
+
node: root
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (root.type !== 'VariableDeclarator') {
|
|
103
|
+
return {
|
|
104
|
+
isExport: false
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Find the reference to the variable declarator
|
|
109
|
+
var reference = scope.references.find(function (_ref) {
|
|
110
|
+
var identifier = _ref.identifier;
|
|
111
|
+
return identifier === root.id;
|
|
112
|
+
});
|
|
113
|
+
if (!reference) {
|
|
114
|
+
return {
|
|
115
|
+
isExport: false
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Iterate through all of the references to the resolved variable declarator node
|
|
120
|
+
var resolved = reference.resolved;
|
|
121
|
+
var _iterator = _createForOfIteratorHelper((_resolved$references = resolved === null || resolved === void 0 ? void 0 : resolved.references) !== null && _resolved$references !== void 0 ? _resolved$references : []),
|
|
122
|
+
_step;
|
|
123
|
+
try {
|
|
124
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
125
|
+
var identifier = _step.value.identifier;
|
|
126
|
+
// Skip references to the root, since it has already been processed above
|
|
127
|
+
if (identifier === root.id) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
var _getStack2 = getStack(context, identifier.parent),
|
|
131
|
+
refs = _getStack2.nodes,
|
|
132
|
+
nextScope = _getStack2.scope;
|
|
133
|
+
|
|
134
|
+
// Only validate the resolved reference if it accesses the definition node
|
|
135
|
+
if (matches(nodes, refs.reverse())) {
|
|
136
|
+
// Now validate the identifier reference as a definition
|
|
137
|
+
var validity = checkIfSupportedExport(context, identifier, importSources, nextScope);
|
|
138
|
+
if (validity.isExport) {
|
|
139
|
+
return validity;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} catch (err) {
|
|
144
|
+
_iterator.e(err);
|
|
145
|
+
} finally {
|
|
146
|
+
_iterator.f();
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
isExport: false
|
|
150
|
+
};
|
|
151
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
/**
|
|
3
|
+
* Given a list of node, find and return the callee of the first Compiled or styled-components `styled` function call found in the list.
|
|
4
|
+
*
|
|
5
|
+
* For example, given `styled.div({ ... })`, we return the node corresponding to the
|
|
6
|
+
* `styled.div` part. Alternatively, given `styled(button)(style)`, we return the `styled`
|
|
7
|
+
* part.
|
|
8
|
+
*
|
|
9
|
+
* @param nodes
|
|
10
|
+
* @returns The callee of the first `styled` function call found.
|
|
11
|
+
*/
|
|
12
|
+
var findNode = function findNode(nodes) {
|
|
13
|
+
var node = nodes.find(function (n) {
|
|
14
|
+
return n.type === 'TaggedTemplateExpression' || n.type === 'CallExpression';
|
|
15
|
+
});
|
|
16
|
+
if (!node) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (node.type === 'CallExpression') {
|
|
20
|
+
// Eg. const Component = styled.button(style)
|
|
21
|
+
if (node.callee.type === 'MemberExpression') {
|
|
22
|
+
return node.callee;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Eg. const Component = styled(button)(style)
|
|
26
|
+
if (node.callee.type === 'CallExpression' && node.callee.callee.type === 'Identifier') {
|
|
27
|
+
return node.callee.callee;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Eg. const Component = styled.div`${styles}`;
|
|
32
|
+
if (node.type === 'TaggedTemplateExpression' && node.tag.type === 'MemberExpression') {
|
|
33
|
+
return node.tag;
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Given a rule, return the local name used to import the `styled` API. (for Compiled or styled-components).
|
|
40
|
+
*
|
|
41
|
+
* @param context Rule context.
|
|
42
|
+
* @returns The local name used to import the `styled` API.
|
|
43
|
+
*/
|
|
44
|
+
var getStyledImportSpecifierName = function getStyledImportSpecifierName(context, importSources) {
|
|
45
|
+
var _supportedImports$0$s;
|
|
46
|
+
var isSupportedImport = function isSupportedImport(node) {
|
|
47
|
+
return isNodeOfType(node, 'ImportDeclaration') && typeof node.source.value === 'string' && importSources.includes(node.source.value);
|
|
48
|
+
};
|
|
49
|
+
var source = context.getSourceCode();
|
|
50
|
+
var supportedImports = source.ast.body.filter(isSupportedImport);
|
|
51
|
+
return (_supportedImports$0$s = supportedImports[0].specifiers.find(function (spec) {
|
|
52
|
+
return spec.type === 'ImportSpecifier' && spec.imported.name === 'styled';
|
|
53
|
+
})) === null || _supportedImports$0$s === void 0 ? void 0 : _supportedImports$0$s.local.name;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Returns whether the node is a usage of the `styled` API in the libraries we support.
|
|
58
|
+
*
|
|
59
|
+
* @param nodes Nodes to check.
|
|
60
|
+
* @param context Rule context.
|
|
61
|
+
* @param importSources A list of libraries we support.
|
|
62
|
+
* @returns Whether the node is a usage of the `styled` API.
|
|
63
|
+
*/
|
|
64
|
+
export var isStyledComponent = function isStyledComponent(nodes, context, importSources) {
|
|
65
|
+
var node = findNode(nodes);
|
|
66
|
+
if (!node) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
var styledImportSpecifierName = getStyledImportSpecifierName(context, importSources);
|
|
70
|
+
if (styledImportSpecifierName) {
|
|
71
|
+
if (node.type === 'Identifier') {
|
|
72
|
+
return node.name === styledImportSpecifierName;
|
|
73
|
+
} else {
|
|
74
|
+
return node.object.type === 'Identifier' && node.object.name === styledImportSpecifierName;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { getImportSources } from '../is-supported-import';
|
|
2
|
+
import { checkIfSupportedExport } from './check-if-supported-export';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new ESLint rule for banning exporting certain function calls, e.g.
|
|
5
|
+
* `css` and `keyframes`.
|
|
6
|
+
*
|
|
7
|
+
* Copied from the `utils/create-no-exported-rule/` folder in @compiled/eslint-plugin.
|
|
8
|
+
*
|
|
9
|
+
* Requires an importSources option defined on the rule, which is used to define additional
|
|
10
|
+
* packages which should be checked as part of this rule.
|
|
11
|
+
*
|
|
12
|
+
* @param isUsage A function that checks whether the current node matches the desired
|
|
13
|
+
* function call to check.
|
|
14
|
+
* @param messageId The ESLint error message to use for lint violations.
|
|
15
|
+
* @returns An eslint rule.
|
|
16
|
+
*/
|
|
17
|
+
export var createNoExportedRule = function createNoExportedRule(isUsage, messageId) {
|
|
18
|
+
return function (context) {
|
|
19
|
+
var importSources = getImportSources(context);
|
|
20
|
+
var _context$getSourceCod = context.getSourceCode(),
|
|
21
|
+
text = _context$getSourceCod.text;
|
|
22
|
+
if (importSources.every(function (importSource) {
|
|
23
|
+
return !text.includes(importSource);
|
|
24
|
+
})) {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
CallExpression: function CallExpression(node) {
|
|
29
|
+
var _context$getScope = context.getScope(),
|
|
30
|
+
references = _context$getScope.references;
|
|
31
|
+
if (!isUsage(node.callee, references, importSources)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
var state = checkIfSupportedExport(context, node, importSources);
|
|
35
|
+
if (!state.isExport) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
context.report({
|
|
39
|
+
messageId: messageId,
|
|
40
|
+
node: state.node
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
TaggedTemplateExpression: function TaggedTemplateExpression(node) {
|
|
44
|
+
var _context$getScope2 = context.getScope(),
|
|
45
|
+
references = _context$getScope2.references;
|
|
46
|
+
if (!isUsage(node.tag, references, importSources)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
var state = checkIfSupportedExport(context, node, importSources);
|
|
50
|
+
if (!state.isExport) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
context.report({
|
|
54
|
+
messageId: messageId,
|
|
55
|
+
node: state.node
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
1
2
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
3
|
|
|
3
4
|
export var CSS_IN_JS_IMPORTS = {
|
|
@@ -8,31 +9,64 @@ export var CSS_IN_JS_IMPORTS = {
|
|
|
8
9
|
atlaskitCss: '@atlaskit/css'
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
//
|
|
12
|
+
// A CSS-in-JS library an import of a valid css, cx, cssMap, etc.
|
|
12
13
|
// function might originate from, e.g. @compiled/react, @emotion/core.
|
|
14
|
+
// All ESLint rules originating from `@compiled/eslint-plugin` should apply to these libraries.
|
|
15
|
+
export var DEFAULT_IMPORT_SOURCES = [CSS_IN_JS_IMPORTS.compiled, CSS_IN_JS_IMPORTS.atlaskitCss];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Given the ESLint rule context, extract and parse the value of the importSources rule option.
|
|
19
|
+
* The importSources option is used to define additional libraries for which an ESLint rule
|
|
20
|
+
* should apply to.
|
|
21
|
+
*
|
|
22
|
+
* Note that `@compiled/react` and `@atlaskit/css` are always included in importSources, regardless
|
|
23
|
+
* of what importSources is configured to by the user.
|
|
24
|
+
*
|
|
25
|
+
* @param context The rule context.
|
|
26
|
+
* @returns An array of strings representing what CSS-in-JS packages that should be checked, based
|
|
27
|
+
* on the rule options configuration.
|
|
28
|
+
*/
|
|
29
|
+
export var getImportSources = function getImportSources(context) {
|
|
30
|
+
var options = context.options;
|
|
31
|
+
if (!options.length) {
|
|
32
|
+
return DEFAULT_IMPORT_SOURCES;
|
|
33
|
+
}
|
|
34
|
+
if (options[0].importSources && Array.isArray(options[0].importSources)) {
|
|
35
|
+
return [].concat(DEFAULT_IMPORT_SOURCES, _toConsumableArray(options[0].importSources));
|
|
36
|
+
}
|
|
37
|
+
return DEFAULT_IMPORT_SOURCES;
|
|
38
|
+
};
|
|
13
39
|
var isSupportedImportWrapper = function isSupportedImportWrapper(functionName) {
|
|
14
|
-
// This will need to be extended to support default imports once we start
|
|
15
|
-
// checking cases like `import css from '@emotion/css'`
|
|
16
40
|
var checkDefinitionHasImport = function checkDefinitionHasImport(def, importSources) {
|
|
17
|
-
|
|
18
|
-
|
|
41
|
+
if (def.type !== 'ImportBinding') {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (!def.parent || !importSources.includes(def.parent.source.value)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return (
|
|
48
|
+
// import { functionName } from 'import-source';
|
|
49
|
+
def.node.type === 'ImportSpecifier' && def.node.imported.name === functionName ||
|
|
50
|
+
// import functionName from 'import-source';
|
|
51
|
+
def.node.type === 'ImportDefaultSpecifier' && def.node.local.name === functionName
|
|
52
|
+
);
|
|
19
53
|
};
|
|
20
54
|
|
|
21
55
|
/**
|
|
22
56
|
* Checks whether:
|
|
23
57
|
*
|
|
24
|
-
* 1.
|
|
58
|
+
* 1. A function name `nodeToCheck` matches the name of the function we
|
|
25
59
|
* want to check for (e.g. `cx`, `css`, `cssMap`, or `keyframes`), and
|
|
26
|
-
* 2.
|
|
60
|
+
* 2. Whether `nodeToCheck` originates from one of the libraries listed
|
|
27
61
|
* in `importSources`.
|
|
28
62
|
*
|
|
29
|
-
* @param nodeToCheck
|
|
30
|
-
* @param referencesInScope
|
|
63
|
+
* @param nodeToCheck The function callee we are checking (e.g. The `css` in `css()`).
|
|
64
|
+
* @param referencesInScope List of references that are in scope. We'll use this
|
|
31
65
|
* to check where the function callee is imported from.
|
|
32
|
-
* @param importSources
|
|
33
|
-
* comes from
|
|
66
|
+
* @param importSources List of libraries that we want to ensure `nodeToCheck`
|
|
67
|
+
* comes from.
|
|
34
68
|
*
|
|
35
|
-
* @returns
|
|
69
|
+
* @returns Whether the above conditions are true.
|
|
36
70
|
*/
|
|
37
71
|
var isSupportedImport = function isSupportedImport(nodeToCheck, referencesInScope, importSources) {
|
|
38
72
|
return nodeToCheck.type === 'Identifier' && referencesInScope.some(function (reference) {
|
|
@@ -50,5 +84,6 @@ var isSupportedImportWrapper = function isSupportedImportWrapper(functionName) {
|
|
|
50
84
|
//
|
|
51
85
|
export var isCss = isSupportedImportWrapper('css');
|
|
52
86
|
export var isCxFunction = isSupportedImportWrapper('cx');
|
|
53
|
-
|
|
54
|
-
|
|
87
|
+
export var isCssMap = isSupportedImportWrapper('cssMap');
|
|
88
|
+
export var isKeyframes = isSupportedImportWrapper('keyframes');
|
|
89
|
+
export var isStyled = isSupportedImportWrapper('styled');
|
|
@@ -13,6 +13,10 @@ export declare const configs: {
|
|
|
13
13
|
'@atlaskit/design-system/no-deprecated-apis': string;
|
|
14
14
|
'@atlaskit/design-system/no-deprecated-design-token-usage': string;
|
|
15
15
|
'@atlaskit/design-system/no-deprecated-imports': string;
|
|
16
|
+
'@atlaskit/design-system/no-empty-styled-expression': string;
|
|
17
|
+
'@atlaskit/design-system/no-exported-css': string;
|
|
18
|
+
'@atlaskit/design-system/no-exported-keyframes': string;
|
|
19
|
+
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
16
20
|
'@atlaskit/design-system/no-margin': string;
|
|
17
21
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
18
22
|
'@atlaskit/design-system/no-physical-properties': string;
|
|
@@ -39,6 +43,10 @@ export declare const configs: {
|
|
|
39
43
|
'@atlaskit/design-system/no-deprecated-apis': string;
|
|
40
44
|
'@atlaskit/design-system/no-deprecated-design-token-usage': string;
|
|
41
45
|
'@atlaskit/design-system/no-deprecated-imports': string;
|
|
46
|
+
'@atlaskit/design-system/no-empty-styled-expression': string;
|
|
47
|
+
'@atlaskit/design-system/no-exported-css': string;
|
|
48
|
+
'@atlaskit/design-system/no-exported-keyframes': string;
|
|
49
|
+
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
42
50
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
43
51
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
44
52
|
'@atlaskit/design-system/no-unsafe-style-overrides': string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::914085544778f4543f43e3e30d0982e0>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -16,6 +16,10 @@ declare const _default: {
|
|
|
16
16
|
'@atlaskit/design-system/no-deprecated-apis': string;
|
|
17
17
|
'@atlaskit/design-system/no-deprecated-design-token-usage': string;
|
|
18
18
|
'@atlaskit/design-system/no-deprecated-imports': string;
|
|
19
|
+
'@atlaskit/design-system/no-empty-styled-expression': string;
|
|
20
|
+
'@atlaskit/design-system/no-exported-css': string;
|
|
21
|
+
'@atlaskit/design-system/no-exported-keyframes': string;
|
|
22
|
+
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
19
23
|
'@atlaskit/design-system/no-margin': string;
|
|
20
24
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
21
25
|
'@atlaskit/design-system/no-physical-properties': string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
|
|
3
|
-
* @codegen <<SignedSource::
|
|
3
|
+
* @codegen <<SignedSource::577269c832952ce359cde6a50f26f4e0>>
|
|
4
4
|
* @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
|
|
5
5
|
*/
|
|
6
6
|
declare const _default: {
|
|
@@ -14,6 +14,10 @@ declare const _default: {
|
|
|
14
14
|
'@atlaskit/design-system/no-deprecated-apis': string;
|
|
15
15
|
'@atlaskit/design-system/no-deprecated-design-token-usage': string;
|
|
16
16
|
'@atlaskit/design-system/no-deprecated-imports': string;
|
|
17
|
+
'@atlaskit/design-system/no-empty-styled-expression': string;
|
|
18
|
+
'@atlaskit/design-system/no-exported-css': string;
|
|
19
|
+
'@atlaskit/design-system/no-exported-keyframes': string;
|
|
20
|
+
'@atlaskit/design-system/no-invalid-css-map': string;
|
|
17
21
|
'@atlaskit/design-system/no-nested-styles': string;
|
|
18
22
|
'@atlaskit/design-system/no-unsafe-design-token-usage': string;
|
|
19
23
|
'@atlaskit/design-system/no-unsafe-style-overrides': string;
|
|
@@ -13,6 +13,10 @@ declare const _default: {
|
|
|
13
13
|
'no-deprecated-imports': import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, [{
|
|
14
14
|
deprecatedConfig: import("./utils/types").DeprecatedConfig;
|
|
15
15
|
}], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
|
|
16
|
+
'no-empty-styled-expression': import("eslint").Rule.RuleModule;
|
|
17
|
+
'no-exported-css': import("eslint").Rule.RuleModule;
|
|
18
|
+
'no-exported-keyframes': import("eslint").Rule.RuleModule;
|
|
19
|
+
'no-invalid-css-map': import("eslint").Rule.RuleModule;
|
|
16
20
|
'no-margin': import("eslint").Rule.RuleModule;
|
|
17
21
|
'no-nested-styles': import("eslint").Rule.RuleModule;
|
|
18
22
|
'no-physical-properties': import("eslint").Rule.RuleModule;
|