@atlaskit/eslint-plugin-design-system 13.31.0 → 13.33.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 (46) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +76 -75
  3. package/dist/cjs/presets/all-flat.codegen.js +3 -2
  4. package/dist/cjs/presets/all.codegen.js +3 -2
  5. package/dist/cjs/presets/recommended-flat.codegen.js +3 -2
  6. package/dist/cjs/presets/recommended.codegen.js +3 -2
  7. package/dist/cjs/rules/index.codegen.js +5 -3
  8. package/dist/cjs/rules/no-placeholder/index.js +162 -0
  9. package/dist/cjs/rules/use-simple-field/index.js +138 -0
  10. package/dist/es2019/presets/all-flat.codegen.js +3 -2
  11. package/dist/es2019/presets/all.codegen.js +3 -2
  12. package/dist/es2019/presets/recommended-flat.codegen.js +3 -2
  13. package/dist/es2019/presets/recommended.codegen.js +3 -2
  14. package/dist/es2019/rules/index.codegen.js +5 -3
  15. package/dist/es2019/rules/no-placeholder/index.js +142 -0
  16. package/dist/es2019/rules/use-simple-field/index.js +124 -0
  17. package/dist/esm/presets/all-flat.codegen.js +3 -2
  18. package/dist/esm/presets/all.codegen.js +3 -2
  19. package/dist/esm/presets/recommended-flat.codegen.js +3 -2
  20. package/dist/esm/presets/recommended.codegen.js +3 -2
  21. package/dist/esm/rules/index.codegen.js +5 -3
  22. package/dist/esm/rules/no-placeholder/index.js +154 -0
  23. package/dist/esm/rules/use-simple-field/index.js +132 -0
  24. package/dist/types/presets/all-flat.codegen.d.ts +1 -1
  25. package/dist/types/presets/all.codegen.d.ts +1 -1
  26. package/dist/types/presets/recommended-flat.codegen.d.ts +1 -1
  27. package/dist/types/presets/recommended.codegen.d.ts +1 -1
  28. package/dist/types/rules/index.codegen.d.ts +1 -1
  29. package/dist/types/rules/no-placeholder/index.d.ts +6 -0
  30. package/dist/types/rules/{no-utility-icons → use-simple-field}/index.d.ts +1 -0
  31. package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +1 -1
  32. package/dist/types-ts4.5/presets/all.codegen.d.ts +1 -1
  33. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -1
  34. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -1
  35. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -1
  36. package/dist/types-ts4.5/rules/no-placeholder/index.d.ts +6 -0
  37. package/dist/types-ts4.5/rules/{no-utility-icons → use-simple-field}/index.d.ts +1 -0
  38. package/package.json +2 -2
  39. package/dist/cjs/rules/no-utility-icons/checks.js +0 -246
  40. package/dist/cjs/rules/no-utility-icons/index.js +0 -49
  41. package/dist/es2019/rules/no-utility-icons/checks.js +0 -177
  42. package/dist/es2019/rules/no-utility-icons/index.js +0 -44
  43. package/dist/esm/rules/no-utility-icons/checks.js +0 -239
  44. package/dist/esm/rules/no-utility-icons/index.js +0 -43
  45. package/dist/types/rules/no-utility-icons/checks.d.ts +0 -10
  46. package/dist/types-ts4.5/rules/no-utility-icons/checks.d.ts +0 -10
@@ -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::760141a986e4947e8a1ce74480931f43>>
3
+ * @codegen <<SignedSource::f2a8bbab8acdaf84ca6e295124378517>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { ESLint } from 'eslint';
@@ -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::ba71ef89188bdc20d0ec948cc00f6436>>
3
+ * @codegen <<SignedSource::2ca5e0a897270a5cfe3e234d7948ed0f>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { Linter } from 'eslint';
@@ -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::5c119e0ab08e1f39d471b2b827bbb4de>>
3
+ * @codegen <<SignedSource::aee2986e6e48e70acef7dfa4ba53747d>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { ESLint } from 'eslint';
@@ -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::7b80dfb4568d4c5f7c84d7c382b81de9>>
3
+ * @codegen <<SignedSource::030718cab57dce4d3b39031485e53af4>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { Rule } from 'eslint';
@@ -0,0 +1,6 @@
1
+ export declare const AFFECTED_HTML_ELEMENTS: string[];
2
+ export declare const AFFECTED_ATLASKIT_PACKAGES: Record<string, string[]>;
3
+ export declare const ATLASKIT_FORM_PACKAGE = "@atlaskit/form";
4
+ export declare const ATLASKIT_FIELD_IMPORT = "Field";
5
+ declare const rule: import("eslint").Rule.RuleModule;
6
+ export default rule;
@@ -1,3 +1,4 @@
1
1
  import type { Rule } from 'eslint';
2
+ export declare const convertField = "Convert field to simple field";
2
3
  declare const rule: Rule.RuleModule;
3
4
  export default rule;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
3
  "description": "The essential plugin for use with the Atlassian Design System.",
4
- "version": "13.31.0",
4
+ "version": "13.33.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {
@@ -40,7 +40,7 @@
40
40
  "dependencies": {
41
41
  "@atlaskit/eslint-utils": "^2.0.0",
42
42
  "@atlaskit/icon": "^29.4.0",
43
- "@atlaskit/icon-lab": "^5.13.0",
43
+ "@atlaskit/icon-lab": "^5.14.0",
44
44
  "@atlaskit/tokens": "^9.1.0",
45
45
  "@babel/runtime": "^7.0.0",
46
46
  "@typescript-eslint/utils": "^7.1.0",
@@ -1,246 +0,0 @@
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/migration/cross--editor-close': '@atlaskit/icon/core/migration/cross--editor-close'
15
- };
16
- var iconPropsinNewButton = ['icon', 'iconBefore', 'iconAfter'];
17
- var createChecks = exports.createChecks = function createChecks(context) {
18
- var importStatementsUtility = {};
19
- var importStatementsCore = {};
20
- var newButtonImports = new Set();
21
- var errors = {};
22
-
23
- /**
24
- * Gets the value of a boolean configuration flag
25
- * @param key the key of the configuration flag
26
- * @param defaultValue The default value of the configuration flag
27
- * @returns defaultValue if the configuration flag is not set, the defaultValue of the configuration flag otherwise
28
- */
29
- var getConfigFlag = function getConfigFlag(key, defaultValue) {
30
- if (context.options && context.options.length > 0 && context.options[0] && context.options[0].hasOwnProperty(key)) {
31
- return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
32
- }
33
- return defaultValue;
34
- };
35
- var checkImportDeclarations = function checkImportDeclarations(node) {
36
- var moduleSource = node.source.value;
37
- if (typeof moduleSource !== 'string') {
38
- return;
39
- }
40
- if (moduleSource.startsWith('@atlaskit/icon/utility/')) {
41
- var _iterator = _createForOfIteratorHelper(node.specifiers),
42
- _step;
43
- try {
44
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
45
- var specifier = _step.value;
46
- if (specifier.type === 'ImportDefaultSpecifier') {
47
- importStatementsUtility[specifier.local.name] = node;
48
- }
49
- }
50
- } catch (err) {
51
- _iterator.e(err);
52
- } finally {
53
- _iterator.f();
54
- }
55
- } else if (moduleSource.startsWith('@atlaskit/icon/core/')) {
56
- var _iterator2 = _createForOfIteratorHelper(node.specifiers),
57
- _step2;
58
- try {
59
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
60
- var _specifier = _step2.value;
61
- if (_specifier.type === 'ImportDefaultSpecifier') {
62
- importStatementsCore[moduleSource] = {
63
- node: node,
64
- localName: _specifier.local.name
65
- };
66
- }
67
- }
68
- } catch (err) {
69
- _iterator2.e(err);
70
- } finally {
71
- _iterator2.f();
72
- }
73
- } else if (moduleSource.startsWith('@atlaskit/button/')) {
74
- var _iterator3 = _createForOfIteratorHelper(node.specifiers),
75
- _step3;
76
- try {
77
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
78
- var _specifier2 = _step3.value;
79
- newButtonImports.add(_specifier2.local.name);
80
- }
81
- } catch (err) {
82
- _iterator3.e(err);
83
- } finally {
84
- _iterator3.f();
85
- }
86
- }
87
- };
88
- var checkJSXElement = function checkJSXElement(node) {
89
- 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')) {
90
- return;
91
- }
92
- if (!errors.hasOwnProperty(node.openingElement.name.name)) {
93
- errors[node.openingElement.name.name] = [];
94
- }
95
- errors[node.openingElement.name.name].push({
96
- node: node,
97
- messageId: 'noUtilityIconsJSXElement',
98
- localName: node.openingElement.name.name,
99
- fixable: true,
100
- inNewButton: false
101
- });
102
- };
103
-
104
- // Cases: As Props, In Function Calls, In Arrays, In Maps, In Exports
105
- var checkIconReference = function checkIconReference(node) {
106
- //if this is an import statement then exit early
107
- if (node.parent && ((0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportSpecifier') || (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'ImportDefaultSpecifier'))) {
108
- return;
109
- }
110
-
111
- //check the reference to see if it's a utility icon, if not exit early
112
- if (!importStatementsUtility.hasOwnProperty(node.name)) {
113
- return;
114
- }
115
-
116
- // if it is in new Button then we can fix it
117
- 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)) {
118
- // if it is in new Button then we can fix it
119
- if (!errors.hasOwnProperty(node.name)) {
120
- errors[node.name] = [];
121
- }
122
- errors[node.name].push({
123
- node: node,
124
- messageId: 'noUtilityIconsReference',
125
- localName: node.name,
126
- fixable: true,
127
- inNewButton: true
128
- });
129
- return;
130
- }
131
-
132
- // manually error
133
- if (!errors.hasOwnProperty(node.name)) {
134
- errors[node.name] = [];
135
- }
136
- errors[node.name].push({
137
- node: node,
138
- messageId: 'noUtilityIconsReference',
139
- localName: node.name,
140
- fixable: false,
141
- inNewButton: false
142
- });
143
- };
144
-
145
- /**
146
- * Throws the relevant errors in the correct order.
147
- */
148
- var throwErrors = function throwErrors() {
149
- var shouldAutoFix = getConfigFlag('enableAutoFixer', false);
150
- var _loop = function _loop() {
151
- var utilityIcon = _Object$keys[_i];
152
- var allFixable = errors[utilityIcon].every(function (x) {
153
- return x.fixable;
154
- }); // Check if ALL errors for a giving import are fixable
155
- var originalImportNode = importStatementsUtility[utilityIcon];
156
- var oldImportName = importStatementsUtility[utilityIcon].source.value;
157
- var newImportName = specialCases.hasOwnProperty(oldImportName) ? specialCases[oldImportName] : oldImportName.replace('@atlaskit/icon/utility/', '@atlaskit/icon/core/');
158
- var existingImport = importStatementsCore.hasOwnProperty(newImportName) ? importStatementsCore[newImportName].localName : null;
159
- var replacementImportName = existingImport ? existingImport : allFixable ? utilityIcon : "".concat(utilityIcon, "Core");
160
- var importFixAdded = false;
161
- var _iterator4 = _createForOfIteratorHelper(errors[utilityIcon].entries()),
162
- _step4;
163
- try {
164
- var _loop2 = function _loop2() {
165
- var _step4$value = (0, _slicedToArray2.default)(_step4.value, 2),
166
- index = _step4$value[0],
167
- error = _step4$value[1];
168
- if (error.fixable && shouldAutoFix) {
169
- context.report({
170
- node: error.node,
171
- messageId: error.messageId,
172
- fix: function fix(fixer) {
173
- var fixes = [];
174
-
175
- // Add a new import statement if it doesn't already exist
176
- if (!existingImport && !importFixAdded) {
177
- importFixAdded = true;
178
- fixes.push(fixer.insertTextBefore(originalImportNode, "import ".concat(replacementImportName, " from '").concat(newImportName, "';\n")));
179
- }
180
-
181
- // Handle JSX elements differently if they are in a "new Button"
182
- if (error.inNewButton) {
183
- // Replace the icon with a function that wraps it with iconProps and size="small"
184
- var wrappedIcon = "(iconProps) => <".concat(replacementImportName, " {...iconProps} size=\"small\" />");
185
- fixes.push(fixer.replaceText(error.node, wrappedIcon));
186
- } else if ((0, _eslintCodemodUtils.isNodeOfType)(error.node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(error.node.openingElement.name, 'JSXIdentifier')) {
187
- // Replace the JSX element's closing tag with size="small"
188
- var newOpeningElementText = context.sourceCode.getText(error.node.openingElement).replace(/\s*\/\s*>$/, " size=\"small\"/>").replace(new RegExp('<s*' + error.node.openingElement.name.name), "<".concat(replacementImportName));
189
- fixes.push(fixer.replaceText(error.node.openingElement, newOpeningElementText));
190
- }
191
-
192
- // Handle the first fixable error for import removal if all fixable for this import
193
- if (index === 0 && allFixable) {
194
- fixes.push(fixer.remove(originalImportNode));
195
- }
196
- return fixes;
197
- }
198
- });
199
- } else {
200
- // Report non-fixable errors
201
- context.report({
202
- node: error.node,
203
- messageId: error.messageId
204
- });
205
- }
206
- };
207
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
208
- _loop2();
209
- }
210
- } catch (err) {
211
- _iterator4.e(err);
212
- } finally {
213
- _iterator4.f();
214
- }
215
- };
216
- for (var _i = 0, _Object$keys = Object.keys(errors); _i < _Object$keys.length; _i++) {
217
- _loop();
218
- }
219
-
220
- // 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
221
- var otherUtilityImportsWithoutErrors = Object.keys(importStatementsUtility).filter(function (utilityIcon) {
222
- return !errors.hasOwnProperty(utilityIcon);
223
- });
224
- var _iterator5 = _createForOfIteratorHelper(otherUtilityImportsWithoutErrors),
225
- _step5;
226
- try {
227
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
228
- var utilityIcon = _step5.value;
229
- context.report({
230
- node: importStatementsUtility[utilityIcon],
231
- messageId: 'noUtilityIconsImport'
232
- });
233
- }
234
- } catch (err) {
235
- _iterator5.e(err);
236
- } finally {
237
- _iterator5.f();
238
- }
239
- };
240
- return {
241
- checkImportDeclarations: checkImportDeclarations,
242
- checkJSXElement: checkJSXElement,
243
- checkIconReference: checkIconReference,
244
- throwErrors: throwErrors
245
- };
246
- };
@@ -1,49 +0,0 @@
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
- schema: [{
16
- type: 'object',
17
- properties: {
18
- enableAutoFixer: {
19
- type: 'boolean'
20
- }
21
- },
22
- additionalProperties: false
23
- }],
24
- docs: {
25
- description: 'Disallow use of deprecated utility icons, in favor of core icons with `size="small"`.',
26
- recommended: true,
27
- severity: 'warn'
28
- },
29
- messages: {
30
- noUtilityIconsJSXElement: "Utility icons are deprecated. Please use core icons instead with the size prop set to small.",
31
- noUtilityIconsImport: "Utility icons are deprecated. Please do not import them, use core icons instead.",
32
- noUtilityIconsReference: "Utility icons are deprecated. To replace them, please use core icons with the size prop set to small instead."
33
- }
34
- },
35
- create: function create(context) {
36
- var _createChecks = (0, _checks.createChecks)(context),
37
- checkImportDeclarations = _createChecks.checkImportDeclarations,
38
- checkJSXElement = _createChecks.checkJSXElement,
39
- checkIconReference = _createChecks.checkIconReference,
40
- throwErrors = _createChecks.throwErrors;
41
- return {
42
- ImportDeclaration: checkImportDeclarations,
43
- JSXElement: checkJSXElement,
44
- Identifier: checkIconReference,
45
- 'Program:exit': throwErrors
46
- };
47
- }
48
- });
49
- var _default = exports.default = rule;
@@ -1,177 +0,0 @@
1
- import { isNodeOfType } from 'eslint-codemod-utils';
2
- const specialCases = {
3
- '@atlaskit/icon/utility/migration/cross--editor-close': '@atlaskit/icon/core/migration/cross--editor-close'
4
- };
5
- const iconPropsinNewButton = ['icon', 'iconBefore', 'iconAfter'];
6
- export const createChecks = context => {
7
- const importStatementsUtility = {};
8
- const importStatementsCore = {};
9
- const newButtonImports = new Set();
10
- const errors = {};
11
-
12
- /**
13
- * Gets the value of a boolean configuration flag
14
- * @param key the key of the configuration flag
15
- * @param defaultValue The default value of the configuration flag
16
- * @returns defaultValue if the configuration flag is not set, the defaultValue of the configuration flag otherwise
17
- */
18
- const getConfigFlag = (key, defaultValue) => {
19
- if (context.options && context.options.length > 0 && context.options[0] && context.options[0].hasOwnProperty(key)) {
20
- return context.options[0][key] === !defaultValue ? !defaultValue : defaultValue;
21
- }
22
- return defaultValue;
23
- };
24
- const checkImportDeclarations = node => {
25
- const moduleSource = node.source.value;
26
- if (typeof moduleSource !== 'string') {
27
- return;
28
- }
29
- if (moduleSource.startsWith('@atlaskit/icon/utility/')) {
30
- for (const specifier of node.specifiers) {
31
- if (specifier.type === 'ImportDefaultSpecifier') {
32
- importStatementsUtility[specifier.local.name] = node;
33
- }
34
- }
35
- } else if (moduleSource.startsWith('@atlaskit/icon/core/')) {
36
- for (const specifier of node.specifiers) {
37
- if (specifier.type === 'ImportDefaultSpecifier') {
38
- importStatementsCore[moduleSource] = {
39
- node,
40
- localName: specifier.local.name
41
- };
42
- }
43
- }
44
- } else if (moduleSource.startsWith('@atlaskit/button/')) {
45
- for (const specifier of node.specifiers) {
46
- newButtonImports.add(specifier.local.name);
47
- }
48
- }
49
- };
50
- const checkJSXElement = node => {
51
- if (!(isNodeOfType(node, 'JSXElement') && isNodeOfType(node.openingElement.name, 'JSXIdentifier') && importStatementsUtility.hasOwnProperty(node.openingElement.name.name) && typeof importStatementsUtility[node.openingElement.name.name].source.value === 'string')) {
52
- return;
53
- }
54
- if (!errors.hasOwnProperty(node.openingElement.name.name)) {
55
- errors[node.openingElement.name.name] = [];
56
- }
57
- errors[node.openingElement.name.name].push({
58
- node,
59
- messageId: 'noUtilityIconsJSXElement',
60
- localName: node.openingElement.name.name,
61
- fixable: true,
62
- inNewButton: false
63
- });
64
- };
65
-
66
- // Cases: As Props, In Function Calls, In Arrays, In Maps, In Exports
67
- const checkIconReference = node => {
68
- //if this is an import statement then exit early
69
- if (node.parent && (isNodeOfType(node.parent, 'ImportSpecifier') || isNodeOfType(node.parent, 'ImportDefaultSpecifier'))) {
70
- return;
71
- }
72
-
73
- //check the reference to see if it's a utility icon, if not exit early
74
- if (!importStatementsUtility.hasOwnProperty(node.name)) {
75
- return;
76
- }
77
-
78
- // if it is in new Button then we can fix it
79
- if (node.parent && node.parent.parent && node.parent.parent.parent && isNodeOfType(node.parent, 'JSXExpressionContainer') && isNodeOfType(node.parent.parent, 'JSXAttribute') && isNodeOfType(node.parent.parent.name, 'JSXIdentifier') && iconPropsinNewButton.includes(node.parent.parent.name.name) && isNodeOfType(node.parent.parent.parent, 'JSXOpeningElement') && isNodeOfType(node.parent.parent.parent.name, 'JSXIdentifier') && newButtonImports.has(node.parent.parent.parent.name.name)) {
80
- // if it is in new Button then we can fix it
81
- if (!errors.hasOwnProperty(node.name)) {
82
- errors[node.name] = [];
83
- }
84
- errors[node.name].push({
85
- node,
86
- messageId: 'noUtilityIconsReference',
87
- localName: node.name,
88
- fixable: true,
89
- inNewButton: true
90
- });
91
- return;
92
- }
93
-
94
- // manually error
95
- if (!errors.hasOwnProperty(node.name)) {
96
- errors[node.name] = [];
97
- }
98
- errors[node.name].push({
99
- node,
100
- messageId: 'noUtilityIconsReference',
101
- localName: node.name,
102
- fixable: false,
103
- inNewButton: false
104
- });
105
- };
106
-
107
- /**
108
- * Throws the relevant errors in the correct order.
109
- */
110
- const throwErrors = () => {
111
- const shouldAutoFix = getConfigFlag('enableAutoFixer', false);
112
- for (const utilityIcon of Object.keys(errors)) {
113
- const allFixable = errors[utilityIcon].every(x => x.fixable); // Check if ALL errors for a giving import are fixable
114
- const originalImportNode = importStatementsUtility[utilityIcon];
115
- const oldImportName = importStatementsUtility[utilityIcon].source.value;
116
- const newImportName = specialCases.hasOwnProperty(oldImportName) ? specialCases[oldImportName] : oldImportName.replace('@atlaskit/icon/utility/', '@atlaskit/icon/core/');
117
- const existingImport = importStatementsCore.hasOwnProperty(newImportName) ? importStatementsCore[newImportName].localName : null;
118
- let replacementImportName = existingImport ? existingImport : allFixable ? utilityIcon : `${utilityIcon}Core`;
119
- let importFixAdded = false;
120
- for (const [index, error] of errors[utilityIcon].entries()) {
121
- if (error.fixable && shouldAutoFix) {
122
- context.report({
123
- node: error.node,
124
- messageId: error.messageId,
125
- fix: fixer => {
126
- const fixes = [];
127
-
128
- // Add a new import statement if it doesn't already exist
129
- if (!existingImport && !importFixAdded) {
130
- importFixAdded = true;
131
- fixes.push(fixer.insertTextBefore(originalImportNode, `import ${replacementImportName} from '${newImportName}';\n`));
132
- }
133
-
134
- // Handle JSX elements differently if they are in a "new Button"
135
- if (error.inNewButton) {
136
- // Replace the icon with a function that wraps it with iconProps and size="small"
137
- const wrappedIcon = `(iconProps) => <${replacementImportName} {...iconProps} size="small" />`;
138
- fixes.push(fixer.replaceText(error.node, wrappedIcon));
139
- } else if (isNodeOfType(error.node, 'JSXElement') && isNodeOfType(error.node.openingElement.name, 'JSXIdentifier')) {
140
- // Replace the JSX element's closing tag with size="small"
141
- const newOpeningElementText = context.sourceCode.getText(error.node.openingElement).replace(/\s*\/\s*>$/, ` size="small"\/>`).replace(new RegExp('<s*' + error.node.openingElement.name.name), `<${replacementImportName}`);
142
- fixes.push(fixer.replaceText(error.node.openingElement, newOpeningElementText));
143
- }
144
-
145
- // Handle the first fixable error for import removal if all fixable for this import
146
- if (index === 0 && allFixable) {
147
- fixes.push(fixer.remove(originalImportNode));
148
- }
149
- return fixes;
150
- }
151
- });
152
- } else {
153
- // Report non-fixable errors
154
- context.report({
155
- node: error.node,
156
- messageId: error.messageId
157
- });
158
- }
159
- }
160
- }
161
-
162
- // 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
163
- const otherUtilityImportsWithoutErrors = Object.keys(importStatementsUtility).filter(utilityIcon => !errors.hasOwnProperty(utilityIcon));
164
- for (const utilityIcon of otherUtilityImportsWithoutErrors) {
165
- context.report({
166
- node: importStatementsUtility[utilityIcon],
167
- messageId: 'noUtilityIconsImport'
168
- });
169
- }
170
- };
171
- return {
172
- checkImportDeclarations,
173
- checkJSXElement,
174
- checkIconReference,
175
- throwErrors
176
- };
177
- };
@@ -1,44 +0,0 @@
1
- import { createLintRule } from '../utils/create-rule';
2
- import { createChecks } from './checks';
3
- const rule = createLintRule({
4
- meta: {
5
- name: 'no-utility-icons',
6
- fixable: 'code',
7
- hasSuggestions: true,
8
- type: 'problem',
9
- schema: [{
10
- type: 'object',
11
- properties: {
12
- enableAutoFixer: {
13
- type: 'boolean'
14
- }
15
- },
16
- additionalProperties: false
17
- }],
18
- docs: {
19
- description: 'Disallow use of deprecated utility icons, in favor of core icons with `size="small"`.',
20
- recommended: true,
21
- severity: 'warn'
22
- },
23
- messages: {
24
- noUtilityIconsJSXElement: `Utility icons are deprecated. Please use core icons instead with the size prop set to small.`,
25
- noUtilityIconsImport: `Utility icons are deprecated. Please do not import them, use core icons instead.`,
26
- noUtilityIconsReference: `Utility icons are deprecated. To replace them, please use core icons with the size prop set to small instead.`
27
- }
28
- },
29
- create(context) {
30
- const {
31
- checkImportDeclarations,
32
- checkJSXElement,
33
- checkIconReference,
34
- throwErrors
35
- } = createChecks(context);
36
- return {
37
- ImportDeclaration: checkImportDeclarations,
38
- JSXElement: checkJSXElement,
39
- Identifier: checkIconReference,
40
- 'Program:exit': throwErrors
41
- };
42
- }
43
- });
44
- export default rule;