@atlaskit/eslint-plugin-design-system 13.15.0 → 13.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +65 -63
  3. package/dist/cjs/presets/all-flat.codegen.js +3 -1
  4. package/dist/cjs/presets/all.codegen.js +3 -1
  5. package/dist/cjs/presets/recommended-flat.codegen.js +2 -1
  6. package/dist/cjs/presets/recommended.codegen.js +2 -1
  7. package/dist/cjs/rules/ensure-proper-xcss-usage/index.js +157 -0
  8. package/dist/cjs/rules/index.codegen.js +5 -1
  9. package/dist/cjs/rules/no-utility-icons/checks.js +233 -0
  10. package/dist/cjs/rules/no-utility-icons/index.js +40 -0
  11. package/dist/es2019/presets/all-flat.codegen.js +3 -1
  12. package/dist/es2019/presets/all.codegen.js +3 -1
  13. package/dist/es2019/presets/recommended-flat.codegen.js +2 -1
  14. package/dist/es2019/presets/recommended.codegen.js +2 -1
  15. package/dist/es2019/rules/ensure-proper-xcss-usage/index.js +149 -0
  16. package/dist/es2019/rules/index.codegen.js +5 -1
  17. package/dist/es2019/rules/no-utility-icons/checks.js +164 -0
  18. package/dist/es2019/rules/no-utility-icons/index.js +35 -0
  19. package/dist/esm/presets/all-flat.codegen.js +3 -1
  20. package/dist/esm/presets/all.codegen.js +3 -1
  21. package/dist/esm/presets/recommended-flat.codegen.js +2 -1
  22. package/dist/esm/presets/recommended.codegen.js +2 -1
  23. package/dist/esm/rules/ensure-proper-xcss-usage/index.js +151 -0
  24. package/dist/esm/rules/index.codegen.js +5 -1
  25. package/dist/esm/rules/no-utility-icons/checks.js +226 -0
  26. package/dist/esm/rules/no-utility-icons/index.js +34 -0
  27. package/dist/types/index.codegen.d.ts +14 -0
  28. package/dist/types/presets/all-flat.codegen.d.ts +2 -0
  29. package/dist/types/presets/all.codegen.d.ts +2 -0
  30. package/dist/types/presets/recommended-flat.codegen.d.ts +1 -0
  31. package/dist/types/presets/recommended.codegen.d.ts +1 -0
  32. package/dist/types/rules/ensure-proper-xcss-usage/index.d.ts +3 -0
  33. package/dist/types/rules/index.codegen.d.ts +2 -0
  34. package/dist/types/rules/no-utility-icons/checks.d.ts +10 -0
  35. package/dist/types/rules/no-utility-icons/index.d.ts +3 -0
  36. package/dist/types-ts4.5/index.codegen.d.ts +14 -0
  37. package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +2 -0
  38. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -0
  39. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -0
  40. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -0
  41. package/dist/types-ts4.5/rules/ensure-proper-xcss-usage/index.d.ts +3 -0
  42. package/dist/types-ts4.5/rules/index.codegen.d.ts +2 -0
  43. package/dist/types-ts4.5/rules/no-utility-icons/checks.d.ts +10 -0
  44. package/dist/types-ts4.5/rules/no-utility-icons/index.d.ts +3 -0
  45. package/package.json +1 -1
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createChecks = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
10
+ 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; } } }; }
11
+ 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; } }
12
+ 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; }
13
+ var specialCases = {
14
+ '@atlaskit/icon/utility/cross': '@atlaskit/icon/core/close',
15
+ '@atlaskit/icon/utility/migration/cross--editor-close': '@atlaskit/icon/core/migration/close--editor-close'
16
+ };
17
+ var iconPropsinNewButton = ['icon', 'iconBefore', 'iconAfter'];
18
+ var createChecks = exports.createChecks = function createChecks(context) {
19
+ var importStatementsUtility = {};
20
+ var importStatementsCore = {};
21
+ var newButtonImports = new Set();
22
+ var errors = {};
23
+ var checkImportDeclarations = function checkImportDeclarations(node) {
24
+ var moduleSource = node.source.value;
25
+ if (typeof moduleSource !== 'string') {
26
+ return;
27
+ }
28
+ if (moduleSource.startsWith('@atlaskit/icon/utility/')) {
29
+ var _iterator = _createForOfIteratorHelper(node.specifiers),
30
+ _step;
31
+ try {
32
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
33
+ var specifier = _step.value;
34
+ if (specifier.type === 'ImportDefaultSpecifier') {
35
+ importStatementsUtility[specifier.local.name] = node;
36
+ }
37
+ }
38
+ } catch (err) {
39
+ _iterator.e(err);
40
+ } finally {
41
+ _iterator.f();
42
+ }
43
+ } else if (moduleSource.startsWith('@atlaskit/icon/core/')) {
44
+ var _iterator2 = _createForOfIteratorHelper(node.specifiers),
45
+ _step2;
46
+ try {
47
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
48
+ var _specifier = _step2.value;
49
+ if (_specifier.type === 'ImportDefaultSpecifier') {
50
+ importStatementsCore[moduleSource] = {
51
+ node: node,
52
+ localName: _specifier.local.name
53
+ };
54
+ }
55
+ }
56
+ } catch (err) {
57
+ _iterator2.e(err);
58
+ } finally {
59
+ _iterator2.f();
60
+ }
61
+ } else if (moduleSource.startsWith('@atlaskit/button/')) {
62
+ var _iterator3 = _createForOfIteratorHelper(node.specifiers),
63
+ _step3;
64
+ try {
65
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
66
+ var _specifier2 = _step3.value;
67
+ newButtonImports.add(_specifier2.local.name);
68
+ }
69
+ } catch (err) {
70
+ _iterator3.e(err);
71
+ } finally {
72
+ _iterator3.f();
73
+ }
74
+ }
75
+ };
76
+ var checkJSXElement = function checkJSXElement(node) {
77
+ if (!((0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier') && importStatementsUtility.hasOwnProperty(node.openingElement.name.name) && typeof importStatementsUtility[node.openingElement.name.name].source.value === 'string')) {
78
+ return;
79
+ }
80
+ if (!errors.hasOwnProperty(node.openingElement.name.name)) {
81
+ errors[node.openingElement.name.name] = [];
82
+ }
83
+ errors[node.openingElement.name.name].push({
84
+ node: node,
85
+ messageId: 'noUtilityIconsJSXElement',
86
+ localName: node.openingElement.name.name,
87
+ fixable: true,
88
+ inNewButton: false
89
+ });
90
+ };
91
+
92
+ // Cases: As Props, In Function Calls, In Arrays, In Maps, In Exports
93
+ var checkIconReference = function checkIconReference(node) {
94
+ //if this is an import statement then exit early
95
+ if (node.parent && ((0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportSpecifier') || (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportDefaultSpecifier'))) {
96
+ return;
97
+ }
98
+
99
+ //check the reference to see if it's a utility icon, if not exit early
100
+ if (!importStatementsUtility.hasOwnProperty(node.name)) {
101
+ return;
102
+ }
103
+
104
+ // if it is in new Button then we can fix it
105
+ if (node.parent && node.parent.parent && node.parent.parent.parent && (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'JSXExpressionContainer') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.name, 'JSXIdentifier') && iconPropsinNewButton.includes(node.parent.parent.name.name) && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.parent, 'JSXOpeningElement') && (0, _eslintCodemodUtils.isNodeOfType)(node.parent.parent.parent.name, 'JSXIdentifier') && newButtonImports.has(node.parent.parent.parent.name.name)) {
106
+ // if it is in new Button then we can fix it
107
+ if (!errors.hasOwnProperty(node.name)) {
108
+ errors[node.name] = [];
109
+ }
110
+ errors[node.name].push({
111
+ node: node,
112
+ messageId: 'noUtilityIconsReference',
113
+ localName: node.name,
114
+ fixable: true,
115
+ inNewButton: true
116
+ });
117
+ return;
118
+ }
119
+
120
+ // manually error
121
+ if (!errors.hasOwnProperty(node.name)) {
122
+ errors[node.name] = [];
123
+ }
124
+ errors[node.name].push({
125
+ node: node,
126
+ messageId: 'noUtilityIconsReference',
127
+ localName: node.name,
128
+ fixable: false,
129
+ inNewButton: false
130
+ });
131
+ };
132
+
133
+ /**
134
+ * Throws the relevant errors in the correct order.
135
+ */
136
+ var throwErrors = function throwErrors() {
137
+ var _loop = function _loop() {
138
+ var utilityIcon = _Object$keys[_i];
139
+ var allFixable = errors[utilityIcon].every(function (x) {
140
+ return x.fixable;
141
+ }); // Check if ALL errors for a giving import are fixable
142
+ var originalImportNode = importStatementsUtility[utilityIcon];
143
+ var oldImportName = importStatementsUtility[utilityIcon].source.value;
144
+ var newImportName = specialCases.hasOwnProperty(oldImportName) ? specialCases[oldImportName] : oldImportName.replace('@atlaskit/icon/utility/', '@atlaskit/icon/core/');
145
+ var existingImport = importStatementsCore.hasOwnProperty(newImportName) ? importStatementsCore[newImportName].localName : null;
146
+ var replacementImportName = existingImport ? existingImport : allFixable ? utilityIcon : "".concat(utilityIcon, "Core");
147
+ var importFixAdded = false;
148
+ var _iterator4 = _createForOfIteratorHelper(errors[utilityIcon].entries()),
149
+ _step4;
150
+ try {
151
+ var _loop2 = function _loop2() {
152
+ var _step4$value = (0, _slicedToArray2.default)(_step4.value, 2),
153
+ index = _step4$value[0],
154
+ error = _step4$value[1];
155
+ if (error.fixable) {
156
+ context.report({
157
+ node: error.node,
158
+ messageId: error.messageId,
159
+ fix: function fix(fixer) {
160
+ var fixes = [];
161
+
162
+ // Add a new import statement if it doesn't already exist
163
+ if (!existingImport && !importFixAdded) {
164
+ importFixAdded = true;
165
+ fixes.push(fixer.insertTextBeforeRange([0, 0], "import ".concat(replacementImportName, " from '").concat(newImportName, "';\n")));
166
+ }
167
+
168
+ // Handle JSX elements differently if they are in a "new Button"
169
+ if (error.inNewButton) {
170
+ // Replace the icon with a function that wraps it with iconProps and size="small"
171
+ var wrappedIcon = "(iconProps) => <".concat(replacementImportName, " {...iconProps} size=\"small\" />");
172
+ fixes.push(fixer.replaceText(error.node, wrappedIcon));
173
+ } else if ((0, _eslintCodemodUtils.isNodeOfType)(error.node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(error.node.openingElement.name, 'JSXIdentifier')) {
174
+ // Replace the JSX element's closing tag with size="small"
175
+ var newOpeningElementText = context.sourceCode.getText(error.node.openingElement).replace(/\s*\/\s*>$/, " size=\"small\"/>").replace(new RegExp('<\s*' + error.node.openingElement.name.name), "<".concat(replacementImportName));
176
+ fixes.push(fixer.replaceText(error.node.openingElement, newOpeningElementText));
177
+ }
178
+
179
+ // Handle the first fixable error for import removal if all fixable for this import
180
+ if (index === 0 && allFixable) {
181
+ fixes.push(fixer.remove(originalImportNode));
182
+ }
183
+ return fixes;
184
+ }
185
+ });
186
+ } else {
187
+ // Report non-fixable errors
188
+ context.report({
189
+ node: error.node,
190
+ messageId: error.messageId
191
+ });
192
+ }
193
+ };
194
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
195
+ _loop2();
196
+ }
197
+ } catch (err) {
198
+ _iterator4.e(err);
199
+ } finally {
200
+ _iterator4.f();
201
+ }
202
+ };
203
+ for (var _i = 0, _Object$keys = Object.keys(errors); _i < _Object$keys.length; _i++) {
204
+ _loop();
205
+ }
206
+
207
+ // If other utility icons are imported but there were no errors for them - (this should only be unused imports but good to have as a backup), report them
208
+ var otherUtilityImportsWithoutErrors = Object.keys(importStatementsUtility).filter(function (utilityIcon) {
209
+ return !errors.hasOwnProperty(utilityIcon);
210
+ });
211
+ var _iterator5 = _createForOfIteratorHelper(otherUtilityImportsWithoutErrors),
212
+ _step5;
213
+ try {
214
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
215
+ var utilityIcon = _step5.value;
216
+ context.report({
217
+ node: importStatementsUtility[utilityIcon],
218
+ messageId: 'noUtilityIconsImport'
219
+ });
220
+ }
221
+ } catch (err) {
222
+ _iterator5.e(err);
223
+ } finally {
224
+ _iterator5.f();
225
+ }
226
+ };
227
+ return {
228
+ checkImportDeclarations: checkImportDeclarations,
229
+ checkJSXElement: checkJSXElement,
230
+ checkIconReference: checkIconReference,
231
+ throwErrors: throwErrors
232
+ };
233
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _createRule = require("../utils/create-rule");
8
+ var _checks = require("./checks");
9
+ var rule = (0, _createRule.createLintRule)({
10
+ meta: {
11
+ name: 'no-utility-icons',
12
+ fixable: 'code',
13
+ hasSuggestions: true,
14
+ type: 'problem',
15
+ docs: {
16
+ description: 'Disallow use of deprecated utility icons, in favor of core icons with `size="small"`.',
17
+ recommended: true,
18
+ severity: 'warn'
19
+ },
20
+ messages: {
21
+ noUtilityIconsJSXElement: "Utility icons are deprecated. Please use core icons instead with the size prop set to small.",
22
+ noUtilityIconsImport: "Utility icons are deprecated. Please do not import them, use core icons instead.",
23
+ noUtilityIconsReference: "Utility icons are deprecated. To replace them, please use core icons with the size prop set to small instead."
24
+ }
25
+ },
26
+ create: function create(context) {
27
+ var _createChecks = (0, _checks.createChecks)(context),
28
+ checkImportDeclarations = _createChecks.checkImportDeclarations,
29
+ checkJSXElement = _createChecks.checkJSXElement,
30
+ checkIconReference = _createChecks.checkIconReference,
31
+ throwErrors = _createChecks.throwErrors;
32
+ return {
33
+ ImportDeclaration: checkImportDeclarations,
34
+ JSXElement: checkJSXElement,
35
+ Identifier: checkIconReference,
36
+ 'Program:exit': throwErrors
37
+ };
38
+ }
39
+ });
40
+ var _default = exports.default = rule;
@@ -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::c6c896451f2be4d48f04068f5bbb85f1>>
3
+ * @codegen <<SignedSource::5ceb45b21744434ca96a850461a3c574>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -12,6 +12,7 @@ export default {
12
12
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
13
13
  '@atlaskit/design-system/ensure-design-token-usage/preview': 'warn',
14
14
  '@atlaskit/design-system/ensure-icon-color': 'error',
15
+ '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
15
16
  '@atlaskit/design-system/icon-label': 'warn',
16
17
  '@atlaskit/design-system/no-banned-imports': 'error',
17
18
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
@@ -47,6 +48,7 @@ export default {
47
48
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
48
49
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
49
50
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
51
+ '@atlaskit/design-system/no-utility-icons': 'warn',
50
52
  '@atlaskit/design-system/prefer-primitives': 'warn',
51
53
  '@atlaskit/design-system/use-button-group-label': 'warn',
52
54
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
@@ -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::d4de619ac262298b2af11f905a02b0dd>>
3
+ * @codegen <<SignedSource::b96d8bb5115de6e0a230feef152a1365>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ export default {
11
11
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
12
12
  '@atlaskit/design-system/ensure-design-token-usage/preview': 'warn',
13
13
  '@atlaskit/design-system/ensure-icon-color': 'error',
14
+ '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
14
15
  '@atlaskit/design-system/icon-label': 'warn',
15
16
  '@atlaskit/design-system/no-banned-imports': 'error',
16
17
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
@@ -46,6 +47,7 @@ export default {
46
47
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
47
48
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
48
49
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
50
+ '@atlaskit/design-system/no-utility-icons': 'warn',
49
51
  '@atlaskit/design-system/prefer-primitives': 'warn',
50
52
  '@atlaskit/design-system/use-button-group-label': 'warn',
51
53
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
@@ -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::af96131434aa77c7882ceb200e4e2cf1>>
3
+ * @codegen <<SignedSource::10f372e16c048db9bfb1bc36cf48421c>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -36,6 +36,7 @@ export default {
36
36
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
37
37
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
38
38
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
39
+ '@atlaskit/design-system/no-utility-icons': 'warn',
39
40
  '@atlaskit/design-system/use-button-group-label': 'warn',
40
41
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
41
42
  '@atlaskit/design-system/use-datetime-picker-calendar-button': 'warn',
@@ -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::4bb65ab8e5c1cad968c6e74d7179e58b>>
3
+ * @codegen <<SignedSource::608f46f9cc8653226152a8edc34849d6>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -35,6 +35,7 @@ export default {
35
35
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
36
36
  '@atlaskit/design-system/no-unsafe-style-overrides': 'warn',
37
37
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
38
+ '@atlaskit/design-system/no-utility-icons': 'warn',
38
39
  '@atlaskit/design-system/use-button-group-label': 'warn',
39
40
  '@atlaskit/design-system/use-cx-function-in-xcss': 'error',
40
41
  '@atlaskit/design-system/use-datetime-picker-calendar-button': 'warn',
@@ -0,0 +1,149 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import { createLintRule } from '../utils/create-rule';
3
+ import { errorBoundary } from '../utils/error-boundary';
4
+ const rule = createLintRule({
5
+ meta: {
6
+ name: 'ensure-proper-xcss-usage',
7
+ docs: {
8
+ description: 'Enforces proper xcss usage: migrate from xcss() to cssMap() and use cssMap objects with specific keys.',
9
+ recommended: false,
10
+ severity: 'error'
11
+ },
12
+ messages: {
13
+ missingCssMapKey: 'xcss prop should use a specific key from cssMap (e.g., {{identifier}}.root) instead of the entire cssMap object.',
14
+ noXcssWithCompiled: 'Cannot use `xcss()` function with `@atlaskit/primitives/compiled`. Use `cssMap()` from `@atlaskit/css or `@compiled/react` instead.'
15
+ }
16
+ },
17
+ create(context) {
18
+ const tracker = {
19
+ // Components tracking
20
+ compiledComponents: new Set(),
21
+ // Function tracking
22
+ cssMapFunction: new Set(),
23
+ xcssFunction: new Set(),
24
+ // Variables tracking
25
+ cssMapVariables: new Map(),
26
+ xcssVariables: new Set()
27
+ };
28
+ return errorBoundary({
29
+ // Track all imports in a single handler
30
+ ImportDeclaration(node) {
31
+ const source = node.source.value;
32
+ node.specifiers.forEach(specifier => {
33
+ if (specifier.type !== 'ImportSpecifier') {
34
+ return;
35
+ }
36
+
37
+ // Handle different import sources
38
+ switch (source) {
39
+ case '@atlaskit/primitives/compiled':
40
+ tracker.compiledComponents.add(specifier.imported.name);
41
+ break;
42
+ case '@atlaskit/primitives':
43
+ if (specifier.imported.name === 'xcss') {
44
+ tracker.xcssFunction.add(specifier.local.name);
45
+ }
46
+ break;
47
+ case '@atlaskit/css':
48
+ case '@compiled/react':
49
+ if (specifier.imported.name === 'cssMap') {
50
+ tracker.cssMapFunction.add(specifier.local.name);
51
+ }
52
+ break;
53
+ }
54
+ });
55
+ },
56
+ // Track variable declarations
57
+ VariableDeclarator(node) {
58
+ if (!node.init || node.init.type !== 'CallExpression' || node.init.callee.type !== 'Identifier' || node.id.type !== 'Identifier') {
59
+ return;
60
+ }
61
+ const calleeName = node.init.callee.name;
62
+ const variableName = node.id.name;
63
+
64
+ // Track cssMap variables and extract their keys
65
+ if (tracker.cssMapFunction.has(calleeName)) {
66
+ const keys = new Set();
67
+
68
+ // Extract keys from the cssMap object argument
69
+ if (node.init.arguments.length > 0 && node.init.arguments[0].type === 'ObjectExpression') {
70
+ node.init.arguments[0].properties.forEach(prop => {
71
+ if (prop.type === 'Property' && prop.key.type === 'Identifier') {
72
+ keys.add(prop.key.name);
73
+ }
74
+ });
75
+ }
76
+ tracker.cssMapVariables.set(variableName, keys);
77
+ }
78
+
79
+ // Track xcss variables
80
+ if (tracker.xcssFunction.has(calleeName)) {
81
+ tracker.xcssVariables.add(variableName);
82
+ }
83
+ },
84
+ // Check JSX elements for xcss prop usage
85
+ JSXElement(node) {
86
+ var _xcssAttribute$value;
87
+ if (!isNodeOfType(node, 'JSXElement')) {
88
+ return;
89
+ }
90
+ const elementName = node.openingElement.name;
91
+ if (elementName.type !== 'JSXIdentifier') {
92
+ return;
93
+ }
94
+ const componentName = elementName.name;
95
+ if (!tracker.compiledComponents.has(componentName)) {
96
+ return;
97
+ }
98
+
99
+ // Find xcss attribute
100
+ const xcssAttribute = node.openingElement.attributes.find(attr => attr.type === 'JSXAttribute' && attr.name.name === 'xcss');
101
+ if ((xcssAttribute === null || xcssAttribute === void 0 ? void 0 : (_xcssAttribute$value = xcssAttribute.value) === null || _xcssAttribute$value === void 0 ? void 0 : _xcssAttribute$value.type) !== 'JSXExpressionContainer') {
102
+ return;
103
+ }
104
+ const expression = xcssAttribute.value.expression;
105
+
106
+ // Check for direct xcss function calls
107
+ if (expression.type === 'CallExpression' && expression.callee.type === 'Identifier' && tracker.xcssFunction.has(expression.callee.name)) {
108
+ context.report({
109
+ node: expression,
110
+ messageId: 'noXcssWithCompiled'
111
+ });
112
+ return;
113
+ }
114
+
115
+ // Check for variables
116
+ if (expression.type === 'Identifier') {
117
+ const identifierName = expression.name;
118
+ if (tracker.xcssVariables.has(identifierName)) {
119
+ context.report({
120
+ node: expression,
121
+ messageId: 'noXcssWithCompiled'
122
+ });
123
+ } else if (tracker.cssMapVariables.has(identifierName)) {
124
+ context.report({
125
+ node: expression,
126
+ messageId: 'missingCssMapKey',
127
+ data: {
128
+ identifier: identifierName
129
+ }
130
+ });
131
+ }
132
+ return;
133
+ }
134
+
135
+ // Check member expressions (e.g., styles.root)
136
+ if (expression.type === 'MemberExpression' && expression.object.type === 'Identifier') {
137
+ const objectName = expression.object.name;
138
+ if (tracker.xcssVariables.has(objectName)) {
139
+ context.report({
140
+ node: expression,
141
+ messageId: 'noXcssWithCompiled'
142
+ });
143
+ }
144
+ }
145
+ }
146
+ });
147
+ }
148
+ });
149
+ export default rule;
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::d42e0ce93d45d02a5c30dcfdb7110c17>>
3
+ * @codegen <<SignedSource::3de5d5b44aa01faabdb840bc7fb43d04>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
7
7
  import ensureDesignTokenUsage from './ensure-design-token-usage';
8
8
  import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
9
9
  import ensureIconColor from './ensure-icon-color';
10
+ import ensureProperXcssUsage from './ensure-proper-xcss-usage';
10
11
  import iconLabel from './icon-label';
11
12
  import noBannedImports from './no-banned-imports';
12
13
  import noBooleanAutofocusOnModalDialog from './no-boolean-autofocus-on-modal-dialog';
@@ -43,6 +44,7 @@ import noStyledTaggedTemplateExpression from './no-styled-tagged-template-expres
43
44
  import noUnsafeDesignTokenUsage from './no-unsafe-design-token-usage';
44
45
  import noUnsafeStyleOverrides from './no-unsafe-style-overrides';
45
46
  import noUnsupportedDragAndDropLibraries from './no-unsupported-drag-and-drop-libraries';
47
+ import noUtilityIcons from './no-utility-icons';
46
48
  import preferPrimitives from './prefer-primitives';
47
49
  import useButtonGroupLabel from './use-button-group-label';
48
50
  import useCxFunctionInXcss from './use-cx-function-in-xcss';
@@ -69,6 +71,7 @@ export const rules = {
69
71
  'ensure-design-token-usage': ensureDesignTokenUsage,
70
72
  'ensure-design-token-usage/preview': ensureDesignTokenUsagePreview,
71
73
  'ensure-icon-color': ensureIconColor,
74
+ 'ensure-proper-xcss-usage': ensureProperXcssUsage,
72
75
  'icon-label': iconLabel,
73
76
  'no-banned-imports': noBannedImports,
74
77
  'no-boolean-autofocus-on-modal-dialog': noBooleanAutofocusOnModalDialog,
@@ -105,6 +108,7 @@ export const rules = {
105
108
  'no-unsafe-design-token-usage': noUnsafeDesignTokenUsage,
106
109
  'no-unsafe-style-overrides': noUnsafeStyleOverrides,
107
110
  'no-unsupported-drag-and-drop-libraries': noUnsupportedDragAndDropLibraries,
111
+ 'no-utility-icons': noUtilityIcons,
108
112
  'prefer-primitives': preferPrimitives,
109
113
  'use-button-group-label': useButtonGroupLabel,
110
114
  'use-cx-function-in-xcss': useCxFunctionInXcss,