@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.
Files changed (68) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +4 -0
  3. package/constellation/index/usage.mdx +362 -0
  4. package/dist/cjs/presets/all.codegen.js +5 -1
  5. package/dist/cjs/presets/recommended.codegen.js +5 -1
  6. package/dist/cjs/rules/index.codegen.js +9 -1
  7. package/dist/cjs/rules/no-empty-styled-expression/index.js +75 -0
  8. package/dist/cjs/rules/no-exported-css/index.js +37 -0
  9. package/dist/cjs/rules/no-exported-keyframes/index.js +37 -0
  10. package/dist/cjs/rules/no-invalid-css-map/index.js +102 -0
  11. package/dist/cjs/rules/no-invalid-css-map/utils.js +193 -0
  12. package/dist/cjs/rules/utils/create-no-exported-rule/check-if-supported-export.js +158 -0
  13. package/dist/cjs/rules/utils/create-no-exported-rule/is-styled-component.js +84 -0
  14. package/dist/cjs/rules/utils/create-no-exported-rule/main.js +66 -0
  15. package/dist/cjs/rules/utils/is-supported-import.js +51 -15
  16. package/dist/es2019/presets/all.codegen.js +5 -1
  17. package/dist/es2019/presets/recommended.codegen.js +5 -1
  18. package/dist/es2019/rules/index.codegen.js +9 -1
  19. package/dist/es2019/rules/no-empty-styled-expression/index.js +65 -0
  20. package/dist/es2019/rules/no-exported-css/index.js +31 -0
  21. package/dist/es2019/rules/no-exported-keyframes/index.js +31 -0
  22. package/dist/es2019/rules/no-invalid-css-map/index.js +95 -0
  23. package/dist/es2019/rules/no-invalid-css-map/utils.js +134 -0
  24. package/dist/es2019/rules/utils/create-no-exported-rule/check-if-supported-export.js +142 -0
  25. package/dist/es2019/rules/utils/create-no-exported-rule/is-styled-component.js +74 -0
  26. package/dist/es2019/rules/utils/create-no-exported-rule/main.js +59 -0
  27. package/dist/es2019/rules/utils/is-supported-import.js +48 -14
  28. package/dist/esm/presets/all.codegen.js +5 -1
  29. package/dist/esm/presets/recommended.codegen.js +5 -1
  30. package/dist/esm/rules/index.codegen.js +9 -1
  31. package/dist/esm/rules/no-empty-styled-expression/index.js +68 -0
  32. package/dist/esm/rules/no-exported-css/index.js +31 -0
  33. package/dist/esm/rules/no-exported-keyframes/index.js +31 -0
  34. package/dist/esm/rules/no-invalid-css-map/index.js +96 -0
  35. package/dist/esm/rules/no-invalid-css-map/utils.js +186 -0
  36. package/dist/esm/rules/utils/create-no-exported-rule/check-if-supported-export.js +151 -0
  37. package/dist/esm/rules/utils/create-no-exported-rule/is-styled-component.js +78 -0
  38. package/dist/esm/rules/utils/create-no-exported-rule/main.js +60 -0
  39. package/dist/esm/rules/utils/is-supported-import.js +49 -14
  40. package/dist/types/index.codegen.d.ts +8 -0
  41. package/dist/types/presets/all.codegen.d.ts +5 -1
  42. package/dist/types/presets/recommended.codegen.d.ts +5 -1
  43. package/dist/types/rules/index.codegen.d.ts +4 -0
  44. package/dist/types/rules/no-empty-styled-expression/index.d.ts +3 -0
  45. package/dist/types/rules/no-exported-css/index.d.ts +3 -0
  46. package/dist/types/rules/no-exported-keyframes/index.d.ts +3 -0
  47. package/dist/types/rules/no-invalid-css-map/index.d.ts +3 -0
  48. package/dist/types/rules/no-invalid-css-map/utils.d.ts +14 -0
  49. package/dist/types/rules/utils/create-no-exported-rule/check-if-supported-export.d.ts +15 -0
  50. package/dist/types/rules/utils/create-no-exported-rule/is-styled-component.d.ts +14 -0
  51. package/dist/types/rules/utils/create-no-exported-rule/main.d.ts +19 -0
  52. package/dist/types/rules/utils/create-rule.d.ts +1 -1
  53. package/dist/types/rules/utils/is-supported-import.d.ts +25 -8
  54. package/dist/types-ts4.5/index.codegen.d.ts +8 -0
  55. package/dist/types-ts4.5/presets/all.codegen.d.ts +5 -1
  56. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +5 -1
  57. package/dist/types-ts4.5/rules/index.codegen.d.ts +4 -0
  58. package/dist/types-ts4.5/rules/no-empty-styled-expression/index.d.ts +3 -0
  59. package/dist/types-ts4.5/rules/no-exported-css/index.d.ts +3 -0
  60. package/dist/types-ts4.5/rules/no-exported-keyframes/index.d.ts +3 -0
  61. package/dist/types-ts4.5/rules/no-invalid-css-map/index.d.ts +3 -0
  62. package/dist/types-ts4.5/rules/no-invalid-css-map/utils.d.ts +14 -0
  63. package/dist/types-ts4.5/rules/utils/create-no-exported-rule/check-if-supported-export.d.ts +15 -0
  64. package/dist/types-ts4.5/rules/utils/create-no-exported-rule/is-styled-component.d.ts +14 -0
  65. package/dist/types-ts4.5/rules/utils/create-no-exported-rule/main.d.ts +19 -0
  66. package/dist/types-ts4.5/rules/utils/create-rule.d.ts +1 -1
  67. package/dist/types-ts4.5/rules/utils/is-supported-import.d.ts +25 -8
  68. 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
- // List of CSS-in-JS libraries an import of a valid css, cx, cssMap, etc.
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
- var _def$parent, _def$parent2;
18
- return def.node.type === 'ImportSpecifier' && def.node.imported.type === 'Identifier' && def.node.imported.name === functionName && ((_def$parent = def.parent) === null || _def$parent === void 0 ? void 0 : _def$parent.type) === 'ImportDeclaration' && importSources.includes((_def$parent2 = def.parent) === null || _def$parent2 === void 0 ? void 0 : _def$parent2.source.value);
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. a function name `nodeToCheck` matches the name of the function we
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. whether `nodeToCheck` originates from one of the libraries listed
60
+ * 2. Whether `nodeToCheck` originates from one of the libraries listed
27
61
  * in `importSources`.
28
62
  *
29
- * @param nodeToCheck the function callee we are checking (e.g. the `css` in `css()`)
30
- * @param referencesInScope list of references that are in scope. We'll use this
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 list of libraries that we want to ensure `nodeToCheck`
33
- * comes from
66
+ * @param importSources List of libraries that we want to ensure `nodeToCheck`
67
+ * comes from.
34
68
  *
35
- * @returns whether the above conditions are true
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
- // export const isCssMap = isLibraryImportWrapper('cssMap');
54
- // export const isKeyframes = isLibraryImportWrapper('keyframes');
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::5026ba2cb55b3c1bcacbfe7fb7728a6c>>
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::839224bfab98c1ddf6018dec5320968e>>
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;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const noEmptyStyledExpressionRule: Rule.RuleModule;
3
+ export default noEmptyStyledExpressionRule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const noExportedCssRule: Rule.RuleModule;
3
+ export default noExportedCssRule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const noExportedKeyframesRule: Rule.RuleModule;
3
+ export default noExportedKeyframesRule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const noInvalidCssMapRule: Rule.RuleModule;
3
+ export default noInvalidCssMapRule;