@atlaskit/eslint-plugin-design-system 13.30.1 → 13.32.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 (51) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +75 -75
  3. package/dist/cjs/presets/all-flat.codegen.js +3 -3
  4. package/dist/cjs/presets/all.codegen.js +3 -3
  5. package/dist/cjs/presets/recommended-flat.codegen.js +2 -2
  6. package/dist/cjs/presets/recommended.codegen.js +2 -2
  7. package/dist/cjs/rules/index.codegen.js +5 -5
  8. package/dist/cjs/rules/lozenge-badge-tag-labelling-system-migration/index.js +712 -0
  9. package/dist/cjs/rules/no-placeholder/index.js +162 -0
  10. package/dist/es2019/presets/all-flat.codegen.js +3 -3
  11. package/dist/es2019/presets/all.codegen.js +3 -3
  12. package/dist/es2019/presets/recommended-flat.codegen.js +2 -2
  13. package/dist/es2019/presets/recommended.codegen.js +2 -2
  14. package/dist/es2019/rules/index.codegen.js +5 -5
  15. package/dist/es2019/rules/lozenge-badge-tag-labelling-system-migration/index.js +702 -0
  16. package/dist/es2019/rules/no-placeholder/index.js +142 -0
  17. package/dist/esm/presets/all-flat.codegen.js +3 -3
  18. package/dist/esm/presets/all.codegen.js +3 -3
  19. package/dist/esm/presets/recommended-flat.codegen.js +2 -2
  20. package/dist/esm/presets/recommended.codegen.js +2 -2
  21. package/dist/esm/rules/index.codegen.js +5 -5
  22. package/dist/esm/rules/lozenge-badge-tag-labelling-system-migration/index.js +705 -0
  23. package/dist/esm/rules/no-placeholder/index.js +154 -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-ts4.5/presets/all-flat.codegen.d.ts +1 -1
  31. package/dist/types-ts4.5/presets/all.codegen.d.ts +1 -1
  32. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -1
  33. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -1
  34. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -1
  35. package/dist/types-ts4.5/rules/no-placeholder/index.d.ts +6 -0
  36. package/package.json +2 -2
  37. package/dist/cjs/rules/lozenge-isBold-and-lozenge-badge-appearance-migration/index.js +0 -332
  38. package/dist/cjs/rules/no-utility-icons/checks.js +0 -246
  39. package/dist/cjs/rules/no-utility-icons/index.js +0 -49
  40. package/dist/es2019/rules/lozenge-isBold-and-lozenge-badge-appearance-migration/index.js +0 -324
  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/lozenge-isBold-and-lozenge-badge-appearance-migration/index.js +0 -326
  44. package/dist/esm/rules/no-utility-icons/checks.js +0 -239
  45. package/dist/esm/rules/no-utility-icons/index.js +0 -43
  46. package/dist/types/rules/lozenge-isBold-and-lozenge-badge-appearance-migration/index.d.ts +0 -3
  47. package/dist/types/rules/no-utility-icons/checks.d.ts +0 -10
  48. package/dist/types/rules/no-utility-icons/index.d.ts +0 -3
  49. package/dist/types-ts4.5/rules/no-utility-icons/checks.d.ts +0 -10
  50. /package/dist/{types-ts4.5/rules/no-utility-icons → types/rules/lozenge-badge-tag-labelling-system-migration}/index.d.ts +0 -0
  51. /package/dist/types-ts4.5/rules/{lozenge-isBold-and-lozenge-badge-appearance-migration → lozenge-badge-tag-labelling-system-migration}/index.d.ts +0 -0
@@ -0,0 +1,154 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import * as ast from '../../ast-nodes';
3
+ import { createLintRule } from '../utils/create-rule';
4
+ export var AFFECTED_HTML_ELEMENTS = ['input', 'textarea'];
5
+ export var AFFECTED_ATLASKIT_PACKAGES = {
6
+ '@atlaskit/datetime-picker': ['DatePicker', 'TimePicker', 'DateTimePicker'],
7
+ '@atlaskit/select': ['default', 'AsyncCreatableSelect', 'CheckboxSelect', 'CountrySelect', 'CreatableSelect', 'PopupSelect', 'RadioSelect'],
8
+ '@atlaskit/textarea': ['default'],
9
+ '@atlaskit/textfield': ['default']
10
+ };
11
+ export var ATLASKIT_FORM_PACKAGE = '@atlaskit/form';
12
+ export var ATLASKIT_FIELD_IMPORT = 'Field';
13
+ var rule = createLintRule({
14
+ meta: {
15
+ name: 'no-placeholder',
16
+ type: 'problem',
17
+ docs: {
18
+ description: 'Placeholders should not be used. If information should be given to the user about the proper type or formatting of a value, this should be included using a helper message that is associated to the input instead.',
19
+ recommended: true,
20
+ severity: 'warn'
21
+ },
22
+ messages: {
23
+ noPlaceholder: 'Placeholders should not be used. Use separate information to help users associated using `aria-describedby` instead.',
24
+ noPlaceholderOnSimpleField: 'Placeholders should not be used. Use the `helperMessage` prop instead.',
25
+ noPlaceholderOnComplexField: 'Placeholders should not be used. Use the `HelperMessage` component instead.'
26
+ }
27
+ },
28
+ create: function create(context) {
29
+ var hasFieldImport = false;
30
+ var fieldLocalName = null;
31
+ var localComponentNames = [];
32
+ return {
33
+ ImportDeclaration: function ImportDeclaration(node) {
34
+ var source = node.source.value;
35
+ if (typeof source !== 'string') {
36
+ return;
37
+ }
38
+
39
+ // Ignore non-atlaskit input/form packages
40
+ if (!Object.keys(AFFECTED_ATLASKIT_PACKAGES).includes(source) && ATLASKIT_FORM_PACKAGE !== source) {
41
+ return;
42
+ }
43
+ if (!node.specifiers.length) {
44
+ return;
45
+ }
46
+ var defaultImport = node.specifiers.filter(function (spec) {
47
+ return spec.type === 'ImportDefaultSpecifier';
48
+ });
49
+ var namedImport = node.specifiers.filter(function (spec) {
50
+ return spec.type === 'ImportSpecifier';
51
+ });
52
+ if (source === ATLASKIT_FORM_PACKAGE) {
53
+ if (namedImport.length && namedImport[0].type === 'ImportSpecifier' && 'name' in namedImport[0].imported && namedImport[0].imported.name === ATLASKIT_FIELD_IMPORT) {
54
+ hasFieldImport = true;
55
+ fieldLocalName = namedImport[0].local.name;
56
+ }
57
+ } else {
58
+ var importNames = AFFECTED_ATLASKIT_PACKAGES[source];
59
+ var usesDefaultImport = importNames.includes('default');
60
+ var possibleNamedImports = importNames.filter(function (importName) {
61
+ return importName !== 'default';
62
+ });
63
+ if (usesDefaultImport && defaultImport.length && defaultImport[0].local) {
64
+ localComponentNames.push(defaultImport[0].local.name);
65
+ // or if popup and using a named import
66
+ } else if (possibleNamedImports.length >= 1 && namedImport.length) {
67
+ namedImport.forEach(function (imp) {
68
+ if (imp.type === 'ImportSpecifier' && 'name' in imp.imported && possibleNamedImports.includes(imp.imported.name)) {
69
+ localComponentNames.push(imp.local.name);
70
+ }
71
+ });
72
+ }
73
+ }
74
+ },
75
+ JSXElement: function JSXElement(node) {
76
+ if (!isNodeOfType(node, 'JSXElement')) {
77
+ return false;
78
+ }
79
+ var elName = ast.JSXElement.getName(node);
80
+ if (!elName) {
81
+ return false;
82
+ }
83
+
84
+ // If it is one of the affected native HTML elements
85
+ if (AFFECTED_HTML_ELEMENTS.includes(elName)) {
86
+ // if has a placeholder attribute
87
+ var hasPlaceholderAttribute = node.openingElement.attributes.find(function (attr) {
88
+ return isNodeOfType(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
89
+ });
90
+ if (hasPlaceholderAttribute) {
91
+ return context.report({
92
+ node: node.openingElement,
93
+ messageId: 'noPlaceholder'
94
+ });
95
+ }
96
+ // Else, it is a React component
97
+ } else {
98
+ // if none of the affected packages is imported, return
99
+ if (localComponentNames.length === 0) {
100
+ return;
101
+ }
102
+ // if component name is not in the list, exit
103
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier') || !localComponentNames.includes(node.openingElement.name.name)) {
104
+ return;
105
+ }
106
+ if (hasFieldImport && fieldLocalName) {
107
+ var _node = node;
108
+ var hasParentField = false;
109
+ var fieldType = 'Complex';
110
+ // If node is a Field element or if
111
+ while (isNodeOfType(_node, 'JSXElement') && isNodeOfType(_node.openingElement.name, 'JSXIdentifier') && !hasParentField) {
112
+ var name = _node.openingElement.name.name;
113
+ hasParentField = hasParentField || name === fieldLocalName;
114
+ _node = _node.parent;
115
+ // Skip up until a JSXElement or JSXAttribute is reached
116
+ if (isNodeOfType(_node, 'JSXFragment') || isNodeOfType(_node, 'ArrowFunctionExpression') || isNodeOfType(_node, 'JSXExpressionContainer') || isNodeOfType(_node, 'JSXAttribute')) {
117
+ while (_node && !isNodeOfType(_node, 'JSXElement') && !isNodeOfType(_node, 'Program')) {
118
+ if (isNodeOfType(_node, 'JSXAttribute')) {
119
+ fieldType = 'Simple';
120
+ }
121
+ _node = _node.parent;
122
+ }
123
+ }
124
+ }
125
+ if (hasParentField) {
126
+ // if has a placeholder attribute
127
+ var _hasPlaceholderAttribute = node.openingElement.attributes.find(function (attr) {
128
+ return isNodeOfType(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
129
+ });
130
+ if (_hasPlaceholderAttribute) {
131
+ return context.report({
132
+ node: node.openingElement,
133
+ messageId: "noPlaceholderOn".concat(fieldType, "Field")
134
+ });
135
+ }
136
+ }
137
+ } else {
138
+ // if has a placeholder attribute
139
+ var _hasPlaceholderAttribute2 = node.openingElement.attributes.find(function (attr) {
140
+ return isNodeOfType(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
141
+ });
142
+ if (_hasPlaceholderAttribute2) {
143
+ return context.report({
144
+ node: node.openingElement,
145
+ messageId: 'noPlaceholder'
146
+ });
147
+ }
148
+ }
149
+ }
150
+ }
151
+ };
152
+ }
153
+ });
154
+ export 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::131350ebc877f42247042c6e7327fe18>>
3
+ * @codegen <<SignedSource::4fa72535ce2bc0a19a6fb01c951150db>>
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::b3ddf9ee0a27aaf8a318a6579d48ce99>>
3
+ * @codegen <<SignedSource::dcf6bf4496c97fd6ad4c1d8d65337a6b>>
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::27c9a3631c47b134bfb9da3e921e0601>>
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::52a31bc6cdeb7a9818a0e225d21c88f2>>
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::02be73e0813b6f22038f0f3f2ad6865d>>
3
+ * @codegen <<SignedSource::ca89575f70ae79af2f43113bdc77c0c5>>
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,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::131350ebc877f42247042c6e7327fe18>>
3
+ * @codegen <<SignedSource::4fa72535ce2bc0a19a6fb01c951150db>>
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::b3ddf9ee0a27aaf8a318a6579d48ce99>>
3
+ * @codegen <<SignedSource::dcf6bf4496c97fd6ad4c1d8d65337a6b>>
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::27c9a3631c47b134bfb9da3e921e0601>>
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::52a31bc6cdeb7a9818a0e225d21c88f2>>
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::02be73e0813b6f22038f0f3f2ad6865d>>
3
+ * @codegen <<SignedSource::ca89575f70ae79af2f43113bdc77c0c5>>
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;
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.30.1",
4
+ "version": "13.32.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,332 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _eslintCodemodUtils = require("eslint-codemod-utils");
8
- var _createRule = require("../utils/create-rule");
9
- var rule = (0, _createRule.createLintRule)({
10
- meta: {
11
- name: 'lozenge-isBold-and-lozenge-badge-appearance-migration',
12
- fixable: 'code',
13
- type: 'suggestion',
14
- docs: {
15
- description: 'Helps migrate Lozenge isBold prop and appearance values (for both Lozenge and Badge components) as part of the Labelling System Phase 1 migration.',
16
- recommended: false,
17
- severity: 'warn'
18
- },
19
- messages: {
20
- updateAppearance: 'Update appearance value to new semantic value.',
21
- migrateTag: 'Non-bold <Lozenge> variants should migrate to <Tag> component.',
22
- manualReview: "Dynamic 'isBold' props require manual review before migration.",
23
- updateBadgeAppearance: 'Update Badge appearance value "{{oldValue}}" to new semantic value "{{newValue}}".',
24
- dynamicBadgeAppearance: 'Dynamic appearance prop values require manual review to ensure they use the new semantic values: neutral, information, inverse, danger, success.'
25
- }
26
- },
27
- create: function create(context) {
28
- /**
29
- * Contains a map of imported Lozenge components.
30
- */
31
- var lozengeImports = {}; // local name -> import source
32
-
33
- /**
34
- * Contains a map of imported Badge components.
35
- */
36
- var badgeImports = {}; // local name -> import source
37
-
38
- /**
39
- * Check if a JSX attribute value is a literal false
40
- */
41
- function isLiteralFalse(node) {
42
- return node && node.type === 'JSXExpressionContainer' && node.expression && node.expression.type === 'Literal' && node.expression.value === false;
43
- }
44
-
45
- /**
46
- * Check if a JSX attribute value is dynamic (not a static literal value)
47
- * Can be used for any prop type (boolean, string, etc.)
48
- */
49
- function isDynamicExpression(node) {
50
- if (!node) {
51
- return false;
52
- }
53
-
54
- // If it's a plain literal (e.g., appearance="value"), it's not dynamic
55
- if (node.type === 'Literal') {
56
- return false;
57
- }
58
-
59
- // If it's an expression container with a non-literal expression, it's dynamic
60
- if (node.type === 'JSXExpressionContainer') {
61
- var expr = node.expression;
62
- return expr && expr.type !== 'Literal';
63
- }
64
- return false;
65
- }
66
-
67
- /**
68
- * Get all attributes as an object for easier manipulation
69
- */
70
- function getAttributesMap(attributes) {
71
- var map = {};
72
- attributes.forEach(function (attr) {
73
- if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
74
- map[attr.name.name] = attr;
75
- }
76
- });
77
- return map;
78
- }
79
-
80
- /**
81
- * Map old appearance values to new semantic appearance values
82
- * Both Lozenge and Tag now use the same appearance prop with new semantic values
83
- */
84
- function mapToNewAppearanceValue(oldValue) {
85
- var mapping = {
86
- success: 'success',
87
- default: 'default',
88
- removed: 'removed',
89
- inprogress: 'inprogress',
90
- new: 'new',
91
- moved: 'moved'
92
- };
93
- // TODO: Update this mapping based on actual new semantic values when provided
94
- return mapping[oldValue] || oldValue;
95
- }
96
-
97
- /**
98
- * Map Badge old appearance values to new semantic appearance values
99
- */
100
- function mapBadgeToNewAppearanceValue(oldValue) {
101
- var mapping = {
102
- added: 'success',
103
- removed: 'danger',
104
- default: 'neutral',
105
- primary: 'information',
106
- primaryInverted: 'inverse',
107
- important: 'danger'
108
- };
109
- return mapping[oldValue] || oldValue;
110
- }
111
-
112
- /**
113
- * Extract the string value from a JSX attribute value
114
- */
115
- function extractStringValue(attrValue) {
116
- if (!attrValue) {
117
- return null;
118
- }
119
- if (attrValue.type === 'Literal') {
120
- return attrValue.value;
121
- }
122
- if (attrValue.type === 'JSXExpressionContainer' && attrValue.expression && attrValue.expression.type === 'Literal') {
123
- return attrValue.expression.value;
124
- }
125
- return null;
126
- }
127
-
128
- /**
129
- * Create a fixer function to replace an appearance prop value
130
- * Handles both Literal and JSXExpressionContainer with Literal
131
- */
132
- function createAppearanceFixer(attrValue, newValue) {
133
- return function (fixer) {
134
- if (!attrValue) {
135
- return null;
136
- }
137
- if (attrValue.type === 'Literal') {
138
- return fixer.replaceText(attrValue, "\"".concat(newValue, "\""));
139
- }
140
- if (attrValue.type === 'JSXExpressionContainer' && 'expression' in attrValue && attrValue.expression && attrValue.expression.type === 'Literal') {
141
- return fixer.replaceText(attrValue.expression, "\"".concat(newValue, "\""));
142
- }
143
- return null;
144
- };
145
- }
146
-
147
- /**
148
- * Generate the replacement JSX element text
149
- */
150
- function generateTagReplacement(node) {
151
- var sourceCode = context.getSourceCode();
152
- var attributes = node.openingElement.attributes;
153
-
154
- // Build new attributes array, excluding isBold and mapping appearance values to new semantics
155
- var newAttributes = [];
156
- attributes.forEach(function (attr) {
157
- if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
158
- var attrName = attr.name.name;
159
- if (attrName === 'isBold') {
160
- // Skip isBold attribute
161
- return;
162
- }
163
- if (attrName === 'appearance') {
164
- // Map appearance value to new semantic value but keep the prop name as appearance
165
- var stringValue = extractStringValue(attr.value);
166
- if (stringValue && typeof stringValue === 'string') {
167
- var mappedAppearance = mapToNewAppearanceValue(stringValue);
168
- newAttributes.push("appearance=\"".concat(mappedAppearance, "\""));
169
- } else {
170
- // If we can't extract the string value, keep as-is with appearance prop
171
- var value = attr.value ? sourceCode.getText(attr.value) : '';
172
- newAttributes.push("appearance".concat(value ? "=".concat(value) : ''));
173
- }
174
- return;
175
- }
176
-
177
- // Keep all other attributes
178
- newAttributes.push(sourceCode.getText(attr));
179
- } else if (attr.type === 'JSXSpreadAttribute') {
180
- // Keep spread attributes
181
- newAttributes.push(sourceCode.getText(attr));
182
- }
183
- });
184
- var attributesText = newAttributes.length > 0 ? " ".concat(newAttributes.join(' ')) : '';
185
- var children = node.children.length > 0 ? sourceCode.getText().slice(node.openingElement.range[1], node.closingElement ? node.closingElement.range[0] : node.range[1]) : '';
186
- if (node.closingElement) {
187
- return "<Tag".concat(attributesText, ">").concat(children, "</Tag>");
188
- } else {
189
- return "<Tag".concat(attributesText, " />");
190
- }
191
- }
192
- return {
193
- ImportDeclaration: function ImportDeclaration(node) {
194
- var moduleSource = node.source.value;
195
- if (typeof moduleSource === 'string') {
196
- // Track Lozenge imports
197
- if (moduleSource === '@atlaskit/lozenge' || moduleSource.startsWith('@atlaskit/lozenge')) {
198
- node.specifiers.forEach(function (spec) {
199
- if (spec.type === 'ImportDefaultSpecifier') {
200
- lozengeImports[spec.local.name] = moduleSource;
201
- } else if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
202
- if (spec.imported.name === 'Lozenge') {
203
- lozengeImports[spec.local.name] = moduleSource;
204
- }
205
- }
206
- });
207
- }
208
- // Track Badge imports
209
- if (moduleSource === '@atlaskit/badge' || moduleSource.startsWith('@atlaskit/badge')) {
210
- node.specifiers.forEach(function (spec) {
211
- if (spec.type === 'ImportDefaultSpecifier') {
212
- badgeImports[spec.local.name] = moduleSource;
213
- } else if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
214
- if (spec.imported.name === 'Badge' || spec.imported.name === 'default') {
215
- badgeImports[spec.local.name] = moduleSource;
216
- }
217
- }
218
- });
219
- }
220
- }
221
- },
222
- JSXElement: function JSXElement(node) {
223
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
224
- return;
225
- }
226
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
227
- return;
228
- }
229
- var elementName = node.openingElement.name.name;
230
-
231
- // Handle Badge components
232
- if (badgeImports[elementName]) {
233
- // Find the appearance prop
234
- var _appearanceProp = node.openingElement.attributes.find(function (attr) {
235
- return attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier' && attr.name.name === 'appearance';
236
- });
237
- if (!_appearanceProp || _appearanceProp.type !== 'JSXAttribute') {
238
- // No appearance prop or it's a spread attribute, nothing to migrate
239
- return;
240
- }
241
-
242
- // Check if it's a dynamic expression
243
- if (isDynamicExpression(_appearanceProp.value)) {
244
- context.report({
245
- node: _appearanceProp,
246
- messageId: 'dynamicBadgeAppearance'
247
- });
248
- return;
249
- }
250
-
251
- // Extract the string value
252
- var stringValue = extractStringValue(_appearanceProp.value);
253
- if (stringValue && typeof stringValue === 'string') {
254
- var mappedValue = mapBadgeToNewAppearanceValue(stringValue);
255
- if (mappedValue !== stringValue) {
256
- context.report({
257
- node: _appearanceProp,
258
- messageId: 'updateBadgeAppearance',
259
- data: {
260
- oldValue: stringValue,
261
- newValue: mappedValue
262
- },
263
- fix: createAppearanceFixer(_appearanceProp.value, mappedValue)
264
- });
265
- }
266
- }
267
- return;
268
- }
269
-
270
- // Only process if this is a Lozenge component we've imported
271
- if (!lozengeImports[elementName]) {
272
- return;
273
- }
274
- var attributesMap = getAttributesMap(node.openingElement.attributes);
275
- var appearanceProp = attributesMap.appearance;
276
- var isBoldProp = attributesMap.isBold;
277
-
278
- // Handle appearance prop value migration
279
- if (appearanceProp) {
280
- var shouldMigrateToTag = !isBoldProp || isLiteralFalse(isBoldProp.value);
281
- if (!shouldMigrateToTag) {
282
- // Only update appearance values for Lozenge components that stay as Lozenge
283
- var _stringValue = extractStringValue(appearanceProp.value);
284
- if (_stringValue && typeof _stringValue === 'string') {
285
- var _mappedValue = mapToNewAppearanceValue(_stringValue);
286
- if (_mappedValue !== _stringValue) {
287
- context.report({
288
- node: appearanceProp,
289
- messageId: 'updateAppearance',
290
- fix: createAppearanceFixer(appearanceProp.value, _mappedValue)
291
- });
292
- }
293
- }
294
- }
295
- }
296
-
297
- // Handle isBold prop and Tag migration
298
- if (isBoldProp) {
299
- if (isLiteralFalse(isBoldProp.value)) {
300
- // isBold={false} should migrate to Tag
301
- context.report({
302
- node: node,
303
- messageId: 'migrateTag',
304
- fix: function fix(fixer) {
305
- var replacement = generateTagReplacement(node);
306
- return fixer.replaceText(node, replacement);
307
- }
308
- });
309
- } else if (isDynamicExpression(isBoldProp.value)) {
310
- // Dynamic isBold requires manual review
311
- context.report({
312
- node: isBoldProp,
313
- messageId: 'manualReview'
314
- });
315
- }
316
- // isBold={true} or isBold (implicit true) - no action needed
317
- } else {
318
- // No isBold prop means implicit false, should migrate to Tag
319
- context.report({
320
- node: node,
321
- messageId: 'migrateTag',
322
- fix: function fix(fixer) {
323
- var replacement = generateTagReplacement(node);
324
- return fixer.replaceText(node, replacement);
325
- }
326
- });
327
- }
328
- }
329
- };
330
- }
331
- });
332
- var _default = exports.default = rule;