@atlaskit/eslint-plugin-design-system 13.23.4 → 13.24.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 (33) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +2 -1
  3. package/dist/cjs/presets/all-flat.codegen.js +2 -1
  4. package/dist/cjs/presets/all.codegen.js +2 -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/index.codegen.js +3 -1
  8. package/dist/cjs/rules/lozenge-appearance-and-isbold-migration/index.js +236 -0
  9. package/dist/es2019/presets/all-flat.codegen.js +2 -1
  10. package/dist/es2019/presets/all.codegen.js +2 -1
  11. package/dist/es2019/presets/recommended-flat.codegen.js +2 -1
  12. package/dist/es2019/presets/recommended.codegen.js +2 -1
  13. package/dist/es2019/rules/index.codegen.js +3 -1
  14. package/dist/es2019/rules/lozenge-appearance-and-isbold-migration/index.js +230 -0
  15. package/dist/esm/presets/all-flat.codegen.js +2 -1
  16. package/dist/esm/presets/all.codegen.js +2 -1
  17. package/dist/esm/presets/recommended-flat.codegen.js +2 -1
  18. package/dist/esm/presets/recommended.codegen.js +2 -1
  19. package/dist/esm/rules/index.codegen.js +3 -1
  20. package/dist/esm/rules/lozenge-appearance-and-isbold-migration/index.js +230 -0
  21. package/dist/types/presets/all-flat.codegen.d.ts +1 -1
  22. package/dist/types/presets/all.codegen.d.ts +1 -1
  23. package/dist/types/presets/recommended-flat.codegen.d.ts +1 -1
  24. package/dist/types/presets/recommended.codegen.d.ts +1 -1
  25. package/dist/types/rules/index.codegen.d.ts +1 -1
  26. package/dist/types/rules/lozenge-appearance-and-isbold-migration/index.d.ts +3 -0
  27. package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +1 -1
  28. package/dist/types-ts4.5/presets/all.codegen.d.ts +1 -1
  29. package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +1 -1
  30. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -1
  31. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -1
  32. package/dist/types-ts4.5/rules/lozenge-appearance-and-isbold-migration/index.d.ts +3 -0
  33. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 13.24.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`9e8597d0a762f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9e8597d0a762f) -
8
+ Update lozenge-appearance-and-isbold-migration rule to preserve appearance prop (no color prop
9
+ change)
10
+
11
+ ## 13.24.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`6346354ff2153`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6346354ff2153) -
16
+ Add a new rule `lozenge-appearance-and-isbold-migration` to help migrate deprecated Lozenge usages
17
+ to the new API or Tag component as part of the Labelling System Phase 1 migration
18
+
3
19
  ## 13.23.4
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -56,6 +56,7 @@ module.exports = {
56
56
  | <a href="./packages/design-system/eslint-plugin/src/rules/ensure-icon-color/README.md">ensure-icon-color</a> | Enforces that upcoming icon components have a color prop set, to enable a migration of the default value. | | | |
57
57
  | <a href="./packages/design-system/eslint-plugin/src/rules/ensure-proper-xcss-usage/README.md">ensure-proper-xcss-usage</a> | Enforces proper xcss usage: migrate from xcss() to cssMap() and use cssMap objects with specific keys. | | | |
58
58
  | <a href="./packages/design-system/eslint-plugin/src/rules/icon-label/README.md">icon-label</a> | Enforces accessible usage of icon labels when composed with Atlassian Design System components. | Yes | Yes | |
59
+ | <a href="./packages/design-system/eslint-plugin/src/rules/lozenge-appearance-and-isbold-migration/README.md">lozenge-appearance-and-isbold-migration</a> | Helps migrate deprecated Lozenge usages to the new API or Tag component as part of the Labelling System Phase 1 migration. | Yes | Yes | |
59
60
  | <a href="./packages/design-system/eslint-plugin/src/rules/no-banned-imports/README.md">no-banned-imports</a> | Disallow importing banned modules. | Yes | | |
60
61
  | <a href="./packages/design-system/eslint-plugin/src/rules/no-boolean-autofocus-on-modal-dialog/README.md">no-boolean-autofocus-on-modal-dialog</a> | Encourages makers to not use boolean values for `autoFocus` on Atlassian Design System's modal dialog component. | Yes | | |
61
62
  | <a href="./packages/design-system/eslint-plugin/src/rules/no-css-tagged-template-expression/README.md">no-css-tagged-template-expression</a> | Disallows any `css` tagged template expressions that originate from Emotion, Styled Components or Compiled | | Yes | |
@@ -111,7 +112,7 @@ module.exports = {
111
112
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-primitives/README.md">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
112
113
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-primitives-text/README.md">use-primitives-text</a> | Encourage the usage of text components. | | Yes | Yes |
113
114
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-should-render-to-parent/README.md">use-should-render-to-parent</a> | Encourages makers to use the `shouldRenderToParent` where possible in Atlassian Design System `Popup` and `DropdownMenu` components. | Yes | | Yes |
114
- | <a href="./packages/design-system/eslint-plugin/src/rules/use-spotlight-package/README.md">use-spotlight-package</a> | Discourage the use of deprecated imports from @atlaskit/onboarding in favor of @atlaskit/spotlight. | | Yes | Yes |
115
+ | <a href="./packages/design-system/eslint-plugin/src/rules/use-spotlight-package/README.md">use-spotlight-package</a> | Discourage the use of @atlaskit/onboarding in favor of @atlaskit/spotlight. | | Yes | Yes |
115
116
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-tag-group-label/README.md">use-tag-group-label</a> | Ensures tag groups are described to assistive technology by a direct label or by another element. | Yes | | Yes |
116
117
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-tokens-shape/README.md">use-tokens-shape</a> | Enforces usage of shape design tokens rather than hard-coded values. | | Yes | Yes |
117
118
  | <a href="./packages/design-system/eslint-plugin/src/rules/use-tokens-space/README.md">use-tokens-space</a> | Enforces usage of space design tokens rather than hard-coded values. | | Yes | Yes |
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::5aac2d8dc7c2832bcb8a96a143d60db5>>
9
+ * @codegen <<SignedSource::7fae089db9d7d7153fea58c673bd56af>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
 
@@ -21,6 +21,7 @@ var rules = {
21
21
  '@atlaskit/design-system/ensure-icon-color': 'error',
22
22
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
23
23
  '@atlaskit/design-system/icon-label': 'warn',
24
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
24
25
  '@atlaskit/design-system/no-banned-imports': 'error',
25
26
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
26
27
  '@atlaskit/design-system/no-css-tagged-template-expression': 'error',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::43ea4411c4e338a916772d4bfda146cc>>
9
+ * @codegen <<SignedSource::655d7f24171da0dff60003d0f235e48a>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
 
@@ -20,6 +20,7 @@ var rules = {
20
20
  '@atlaskit/design-system/ensure-icon-color': 'error',
21
21
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
22
22
  '@atlaskit/design-system/icon-label': 'warn',
23
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
23
24
  '@atlaskit/design-system/no-banned-imports': 'error',
24
25
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
25
26
  '@atlaskit/design-system/no-css-tagged-template-expression': 'error',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::3328b9c675a0d09876dcfbc5d29bc63f>>
9
+ * @codegen <<SignedSource::44a03b30a12e3b52d720c16785c9c649>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
 
@@ -17,6 +17,7 @@ var rules = {
17
17
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
18
18
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
19
19
  '@atlaskit/design-system/icon-label': 'warn',
20
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
20
21
  '@atlaskit/design-system/no-banned-imports': 'error',
21
22
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
22
23
  '@atlaskit/design-system/no-deprecated-apis': 'error',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::b28f895280627b7a35f059f90783644a>>
9
+ * @codegen <<SignedSource::0311febdad396820af1b01dd2825b63f>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
 
@@ -16,6 +16,7 @@ var rules = {
16
16
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
17
17
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
18
18
  '@atlaskit/design-system/icon-label': 'warn',
19
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
19
20
  '@atlaskit/design-system/no-banned-imports': 'error',
20
21
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
21
22
  '@atlaskit/design-system/no-deprecated-apis': 'error',
@@ -12,6 +12,7 @@ var _ensureDesignTokenUsagePreview = _interopRequireDefault(require("./ensure-de
12
12
  var _ensureIconColor = _interopRequireDefault(require("./ensure-icon-color"));
13
13
  var _ensureProperXcssUsage = _interopRequireDefault(require("./ensure-proper-xcss-usage"));
14
14
  var _iconLabel = _interopRequireDefault(require("./icon-label"));
15
+ var _lozengeAppearanceAndIsboldMigration = _interopRequireDefault(require("./lozenge-appearance-and-isbold-migration"));
15
16
  var _noBannedImports = _interopRequireDefault(require("./no-banned-imports"));
16
17
  var _noBooleanAutofocusOnModalDialog = _interopRequireDefault(require("./no-boolean-autofocus-on-modal-dialog"));
17
18
  var _noCssTaggedTemplateExpression = _interopRequireDefault(require("./no-css-tagged-template-expression"));
@@ -75,7 +76,7 @@ var _useTokensTypography = _interopRequireDefault(require("./use-tokens-typograp
75
76
  var _useVisuallyHidden = _interopRequireDefault(require("./use-visually-hidden"));
76
77
  /**
77
78
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
78
- * @codegen <<SignedSource::732bff0fc39d7ff05b6688694101698d>>
79
+ * @codegen <<SignedSource::75f94fc6b6fa998eed54b610e41bb9b1>>
79
80
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
80
81
  */
81
82
 
@@ -87,6 +88,7 @@ var rules = exports.rules = {
87
88
  'ensure-icon-color': _ensureIconColor.default,
88
89
  'ensure-proper-xcss-usage': _ensureProperXcssUsage.default,
89
90
  'icon-label': _iconLabel.default,
91
+ 'lozenge-appearance-and-isbold-migration': _lozengeAppearanceAndIsboldMigration.default,
90
92
  'no-banned-imports': _noBannedImports.default,
91
93
  'no-boolean-autofocus-on-modal-dialog': _noBooleanAutofocusOnModalDialog.default,
92
94
  'no-css-tagged-template-expression': _noCssTaggedTemplateExpression.default,
@@ -0,0 +1,236 @@
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-appearance-and-isbold-migration',
12
+ fixable: 'code',
13
+ type: 'suggestion',
14
+ docs: {
15
+ description: 'Helps migrate deprecated Lozenge usages to the new API or Tag component as part of the Labelling System Phase 1 migration.',
16
+ recommended: true,
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
+ }
24
+ },
25
+ create: function create(context) {
26
+ /**
27
+ * Contains a map of imported Lozenge components.
28
+ */
29
+ var lozengeImports = {}; // local name -> import source
30
+
31
+ /**
32
+ * Check if a JSX attribute value is a literal false
33
+ */
34
+ function isLiteralFalse(node) {
35
+ return node && node.type === 'JSXExpressionContainer' && node.expression && node.expression.type === 'Literal' && node.expression.value === false;
36
+ }
37
+
38
+ /**
39
+ * Check if a JSX attribute value is dynamic (not a literal boolean)
40
+ */
41
+ function isDynamicExpression(node) {
42
+ if (!node || node.type !== 'JSXExpressionContainer') {
43
+ return false;
44
+ }
45
+ var expr = node.expression;
46
+ return expr && !(expr.type === 'Literal' && typeof expr.value === 'boolean');
47
+ }
48
+
49
+ /**
50
+ * Get all attributes as an object for easier manipulation
51
+ */
52
+ function getAttributesMap(attributes) {
53
+ var map = {};
54
+ attributes.forEach(function (attr) {
55
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
56
+ map[attr.name.name] = attr;
57
+ }
58
+ });
59
+ return map;
60
+ }
61
+
62
+ /**
63
+ * Map old appearance values to new semantic appearance values
64
+ * Both Lozenge and Tag now use the same appearance prop with new semantic values
65
+ */
66
+ function mapToNewAppearanceValue(oldValue) {
67
+ var mapping = {
68
+ success: 'success',
69
+ default: 'default',
70
+ removed: 'removed',
71
+ inprogress: 'inprogress',
72
+ new: 'new',
73
+ moved: 'moved'
74
+ };
75
+ // TODO: Update this mapping based on actual new semantic values when provided
76
+ return mapping[oldValue] || oldValue;
77
+ }
78
+
79
+ /**
80
+ * Extract the string value from a JSX attribute value
81
+ */
82
+ function extractStringValue(attrValue) {
83
+ if (!attrValue) {
84
+ return null;
85
+ }
86
+ if (attrValue.type === 'Literal') {
87
+ return attrValue.value;
88
+ }
89
+ if (attrValue.type === 'JSXExpressionContainer' && attrValue.expression && attrValue.expression.type === 'Literal') {
90
+ return attrValue.expression.value;
91
+ }
92
+ return null;
93
+ }
94
+
95
+ /**
96
+ * Generate the replacement JSX element text
97
+ */
98
+ function generateTagReplacement(node) {
99
+ var sourceCode = context.getSourceCode();
100
+ var attributes = node.openingElement.attributes;
101
+
102
+ // Build new attributes array, excluding isBold and mapping appearance values to new semantics
103
+ var newAttributes = [];
104
+ attributes.forEach(function (attr) {
105
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
106
+ var attrName = attr.name.name;
107
+ if (attrName === 'isBold') {
108
+ // Skip isBold attribute
109
+ return;
110
+ }
111
+ if (attrName === 'appearance') {
112
+ // Map appearance value to new semantic value but keep the prop name as appearance
113
+ var stringValue = extractStringValue(attr.value);
114
+ if (stringValue && typeof stringValue === 'string') {
115
+ var mappedAppearance = mapToNewAppearanceValue(stringValue);
116
+ newAttributes.push("appearance=\"".concat(mappedAppearance, "\""));
117
+ } else {
118
+ // If we can't extract the string value, keep as-is with appearance prop
119
+ var value = attr.value ? sourceCode.getText(attr.value) : '';
120
+ newAttributes.push("appearance".concat(value ? "=".concat(value) : ''));
121
+ }
122
+ return;
123
+ }
124
+
125
+ // Keep all other attributes
126
+ newAttributes.push(sourceCode.getText(attr));
127
+ } else if (attr.type === 'JSXSpreadAttribute') {
128
+ // Keep spread attributes
129
+ newAttributes.push(sourceCode.getText(attr));
130
+ }
131
+ });
132
+ var attributesText = newAttributes.length > 0 ? " ".concat(newAttributes.join(' ')) : '';
133
+ var children = node.children.length > 0 ? sourceCode.getText().slice(node.openingElement.range[1], node.closingElement ? node.closingElement.range[0] : node.range[1]) : '';
134
+ if (node.closingElement) {
135
+ return "<Tag".concat(attributesText, ">").concat(children, "</Tag>");
136
+ } else {
137
+ return "<Tag".concat(attributesText, " />");
138
+ }
139
+ }
140
+ return {
141
+ ImportDeclaration: function ImportDeclaration(node) {
142
+ var moduleSource = node.source.value;
143
+ if (typeof moduleSource === 'string') {
144
+ // Track Lozenge imports
145
+ if (moduleSource === '@atlaskit/lozenge' || moduleSource.startsWith('@atlaskit/lozenge')) {
146
+ node.specifiers.forEach(function (spec) {
147
+ if (spec.type === 'ImportDefaultSpecifier') {
148
+ lozengeImports[spec.local.name] = moduleSource;
149
+ } else if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
150
+ if (spec.imported.name === 'Lozenge') {
151
+ lozengeImports[spec.local.name] = moduleSource;
152
+ }
153
+ }
154
+ });
155
+ }
156
+ }
157
+ },
158
+ JSXElement: function JSXElement(node) {
159
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
160
+ return;
161
+ }
162
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
163
+ return;
164
+ }
165
+ var elementName = node.openingElement.name.name;
166
+
167
+ // Only process if this is a Lozenge component we've imported
168
+ if (!lozengeImports[elementName]) {
169
+ return;
170
+ }
171
+ var attributesMap = getAttributesMap(node.openingElement.attributes);
172
+ var appearanceProp = attributesMap.appearance;
173
+ var isBoldProp = attributesMap.isBold;
174
+
175
+ // Handle appearance prop value migration
176
+ if (appearanceProp) {
177
+ var shouldMigrateToTag = !isBoldProp || isLiteralFalse(isBoldProp.value);
178
+ if (!shouldMigrateToTag) {
179
+ // Only update appearance values for Lozenge components that stay as Lozenge
180
+ var stringValue = extractStringValue(appearanceProp.value);
181
+ if (stringValue && typeof stringValue === 'string') {
182
+ var mappedValue = mapToNewAppearanceValue(stringValue);
183
+ if (mappedValue !== stringValue) {
184
+ context.report({
185
+ node: appearanceProp,
186
+ messageId: 'updateAppearance',
187
+ fix: function fix(fixer) {
188
+ if (appearanceProp.value.type === 'Literal') {
189
+ return fixer.replaceText(appearanceProp.value, "\"".concat(mappedValue, "\""));
190
+ } else if (appearanceProp.value.type === 'JSXExpressionContainer' && appearanceProp.value.expression && appearanceProp.value.expression.type === 'Literal') {
191
+ return fixer.replaceText(appearanceProp.value.expression, "\"".concat(mappedValue, "\""));
192
+ }
193
+ return null;
194
+ }
195
+ });
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ // Handle isBold prop and Tag migration
202
+ if (isBoldProp) {
203
+ if (isLiteralFalse(isBoldProp.value)) {
204
+ // isBold={false} should migrate to Tag
205
+ context.report({
206
+ node: node,
207
+ messageId: 'migrateTag',
208
+ fix: function fix(fixer) {
209
+ var replacement = generateTagReplacement(node);
210
+ return fixer.replaceText(node, replacement);
211
+ }
212
+ });
213
+ } else if (isDynamicExpression(isBoldProp.value)) {
214
+ // Dynamic isBold requires manual review
215
+ context.report({
216
+ node: isBoldProp,
217
+ messageId: 'manualReview'
218
+ });
219
+ }
220
+ // isBold={true} or isBold (implicit true) - no action needed
221
+ } else {
222
+ // No isBold prop means implicit false, should migrate to Tag
223
+ context.report({
224
+ node: node,
225
+ messageId: 'migrateTag',
226
+ fix: function fix(fixer) {
227
+ var replacement = generateTagReplacement(node);
228
+ return fixer.replaceText(node, replacement);
229
+ }
230
+ });
231
+ }
232
+ }
233
+ };
234
+ }
235
+ });
236
+ 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::5aac2d8dc7c2832bcb8a96a143d60db5>>
3
+ * @codegen <<SignedSource::7fae089db9d7d7153fea58c673bd56af>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -15,6 +15,7 @@ const rules = {
15
15
  '@atlaskit/design-system/ensure-icon-color': 'error',
16
16
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
17
17
  '@atlaskit/design-system/icon-label': 'warn',
18
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
18
19
  '@atlaskit/design-system/no-banned-imports': 'error',
19
20
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
20
21
  '@atlaskit/design-system/no-css-tagged-template-expression': '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::43ea4411c4e338a916772d4bfda146cc>>
3
+ * @codegen <<SignedSource::655d7f24171da0dff60003d0f235e48a>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -14,6 +14,7 @@ const rules = {
14
14
  '@atlaskit/design-system/ensure-icon-color': 'error',
15
15
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
16
16
  '@atlaskit/design-system/icon-label': 'warn',
17
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
17
18
  '@atlaskit/design-system/no-banned-imports': 'error',
18
19
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
19
20
  '@atlaskit/design-system/no-css-tagged-template-expression': '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::3328b9c675a0d09876dcfbc5d29bc63f>>
3
+ * @codegen <<SignedSource::44a03b30a12e3b52d720c16785c9c649>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ const rules = {
11
11
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
12
12
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
13
13
  '@atlaskit/design-system/icon-label': 'warn',
14
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
14
15
  '@atlaskit/design-system/no-banned-imports': 'error',
15
16
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
16
17
  '@atlaskit/design-system/no-deprecated-apis': '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::b28f895280627b7a35f059f90783644a>>
3
+ * @codegen <<SignedSource::0311febdad396820af1b01dd2825b63f>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -10,6 +10,7 @@ const rules = {
10
10
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
11
11
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
12
12
  '@atlaskit/design-system/icon-label': 'warn',
13
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
13
14
  '@atlaskit/design-system/no-banned-imports': 'error',
14
15
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
15
16
  '@atlaskit/design-system/no-deprecated-apis': '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::732bff0fc39d7ff05b6688694101698d>>
3
+ * @codegen <<SignedSource::75f94fc6b6fa998eed54b610e41bb9b1>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
11
11
  import ensureIconColor from './ensure-icon-color';
12
12
  import ensureProperXcssUsage from './ensure-proper-xcss-usage';
13
13
  import iconLabel from './icon-label';
14
+ import lozengeAppearanceAndIsboldMigration from './lozenge-appearance-and-isbold-migration';
14
15
  import noBannedImports from './no-banned-imports';
15
16
  import noBooleanAutofocusOnModalDialog from './no-boolean-autofocus-on-modal-dialog';
16
17
  import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
@@ -80,6 +81,7 @@ export const rules = {
80
81
  'ensure-icon-color': ensureIconColor,
81
82
  'ensure-proper-xcss-usage': ensureProperXcssUsage,
82
83
  'icon-label': iconLabel,
84
+ 'lozenge-appearance-and-isbold-migration': lozengeAppearanceAndIsboldMigration,
83
85
  'no-banned-imports': noBannedImports,
84
86
  'no-boolean-autofocus-on-modal-dialog': noBooleanAutofocusOnModalDialog,
85
87
  'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
@@ -0,0 +1,230 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import { createLintRule } from '../utils/create-rule';
3
+ const rule = createLintRule({
4
+ meta: {
5
+ name: 'lozenge-appearance-and-isbold-migration',
6
+ fixable: 'code',
7
+ type: 'suggestion',
8
+ docs: {
9
+ description: 'Helps migrate deprecated Lozenge usages to the new API or Tag component as part of the Labelling System Phase 1 migration.',
10
+ recommended: true,
11
+ severity: 'warn'
12
+ },
13
+ messages: {
14
+ updateAppearance: 'Update appearance value to new semantic value.',
15
+ migrateTag: 'Non-bold <Lozenge> variants should migrate to <Tag> component.',
16
+ manualReview: "Dynamic 'isBold' props require manual review before migration."
17
+ }
18
+ },
19
+ create(context) {
20
+ /**
21
+ * Contains a map of imported Lozenge components.
22
+ */
23
+ const lozengeImports = {}; // local name -> import source
24
+
25
+ /**
26
+ * Check if a JSX attribute value is a literal false
27
+ */
28
+ function isLiteralFalse(node) {
29
+ return node && node.type === 'JSXExpressionContainer' && node.expression && node.expression.type === 'Literal' && node.expression.value === false;
30
+ }
31
+
32
+ /**
33
+ * Check if a JSX attribute value is dynamic (not a literal boolean)
34
+ */
35
+ function isDynamicExpression(node) {
36
+ if (!node || node.type !== 'JSXExpressionContainer') {
37
+ return false;
38
+ }
39
+ const expr = node.expression;
40
+ return expr && !(expr.type === 'Literal' && typeof expr.value === 'boolean');
41
+ }
42
+
43
+ /**
44
+ * Get all attributes as an object for easier manipulation
45
+ */
46
+ function getAttributesMap(attributes) {
47
+ const map = {};
48
+ attributes.forEach(attr => {
49
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
50
+ map[attr.name.name] = attr;
51
+ }
52
+ });
53
+ return map;
54
+ }
55
+
56
+ /**
57
+ * Map old appearance values to new semantic appearance values
58
+ * Both Lozenge and Tag now use the same appearance prop with new semantic values
59
+ */
60
+ function mapToNewAppearanceValue(oldValue) {
61
+ const mapping = {
62
+ success: 'success',
63
+ default: 'default',
64
+ removed: 'removed',
65
+ inprogress: 'inprogress',
66
+ new: 'new',
67
+ moved: 'moved'
68
+ };
69
+ // TODO: Update this mapping based on actual new semantic values when provided
70
+ return mapping[oldValue] || oldValue;
71
+ }
72
+
73
+ /**
74
+ * Extract the string value from a JSX attribute value
75
+ */
76
+ function extractStringValue(attrValue) {
77
+ if (!attrValue) {
78
+ return null;
79
+ }
80
+ if (attrValue.type === 'Literal') {
81
+ return attrValue.value;
82
+ }
83
+ if (attrValue.type === 'JSXExpressionContainer' && attrValue.expression && attrValue.expression.type === 'Literal') {
84
+ return attrValue.expression.value;
85
+ }
86
+ return null;
87
+ }
88
+
89
+ /**
90
+ * Generate the replacement JSX element text
91
+ */
92
+ function generateTagReplacement(node) {
93
+ const sourceCode = context.getSourceCode();
94
+ const attributes = node.openingElement.attributes;
95
+
96
+ // Build new attributes array, excluding isBold and mapping appearance values to new semantics
97
+ const newAttributes = [];
98
+ attributes.forEach(attr => {
99
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
100
+ const attrName = attr.name.name;
101
+ if (attrName === 'isBold') {
102
+ // Skip isBold attribute
103
+ return;
104
+ }
105
+ if (attrName === 'appearance') {
106
+ // Map appearance value to new semantic value but keep the prop name as appearance
107
+ const stringValue = extractStringValue(attr.value);
108
+ if (stringValue && typeof stringValue === 'string') {
109
+ const mappedAppearance = mapToNewAppearanceValue(stringValue);
110
+ newAttributes.push(`appearance="${mappedAppearance}"`);
111
+ } else {
112
+ // If we can't extract the string value, keep as-is with appearance prop
113
+ const value = attr.value ? sourceCode.getText(attr.value) : '';
114
+ newAttributes.push(`appearance${value ? `=${value}` : ''}`);
115
+ }
116
+ return;
117
+ }
118
+
119
+ // Keep all other attributes
120
+ newAttributes.push(sourceCode.getText(attr));
121
+ } else if (attr.type === 'JSXSpreadAttribute') {
122
+ // Keep spread attributes
123
+ newAttributes.push(sourceCode.getText(attr));
124
+ }
125
+ });
126
+ const attributesText = newAttributes.length > 0 ? ` ${newAttributes.join(' ')}` : '';
127
+ const children = node.children.length > 0 ? sourceCode.getText().slice(node.openingElement.range[1], node.closingElement ? node.closingElement.range[0] : node.range[1]) : '';
128
+ if (node.closingElement) {
129
+ return `<Tag${attributesText}>${children}</Tag>`;
130
+ } else {
131
+ return `<Tag${attributesText} />`;
132
+ }
133
+ }
134
+ return {
135
+ ImportDeclaration(node) {
136
+ const moduleSource = node.source.value;
137
+ if (typeof moduleSource === 'string') {
138
+ // Track Lozenge imports
139
+ if (moduleSource === '@atlaskit/lozenge' || moduleSource.startsWith('@atlaskit/lozenge')) {
140
+ node.specifiers.forEach(spec => {
141
+ if (spec.type === 'ImportDefaultSpecifier') {
142
+ lozengeImports[spec.local.name] = moduleSource;
143
+ } else if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
144
+ if (spec.imported.name === 'Lozenge') {
145
+ lozengeImports[spec.local.name] = moduleSource;
146
+ }
147
+ }
148
+ });
149
+ }
150
+ }
151
+ },
152
+ JSXElement(node) {
153
+ if (!isNodeOfType(node, 'JSXElement')) {
154
+ return;
155
+ }
156
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
157
+ return;
158
+ }
159
+ const elementName = node.openingElement.name.name;
160
+
161
+ // Only process if this is a Lozenge component we've imported
162
+ if (!lozengeImports[elementName]) {
163
+ return;
164
+ }
165
+ const attributesMap = getAttributesMap(node.openingElement.attributes);
166
+ const appearanceProp = attributesMap.appearance;
167
+ const isBoldProp = attributesMap.isBold;
168
+
169
+ // Handle appearance prop value migration
170
+ if (appearanceProp) {
171
+ const shouldMigrateToTag = !isBoldProp || isLiteralFalse(isBoldProp.value);
172
+ if (!shouldMigrateToTag) {
173
+ // Only update appearance values for Lozenge components that stay as Lozenge
174
+ const stringValue = extractStringValue(appearanceProp.value);
175
+ if (stringValue && typeof stringValue === 'string') {
176
+ const mappedValue = mapToNewAppearanceValue(stringValue);
177
+ if (mappedValue !== stringValue) {
178
+ context.report({
179
+ node: appearanceProp,
180
+ messageId: 'updateAppearance',
181
+ fix: fixer => {
182
+ if (appearanceProp.value.type === 'Literal') {
183
+ return fixer.replaceText(appearanceProp.value, `"${mappedValue}"`);
184
+ } else if (appearanceProp.value.type === 'JSXExpressionContainer' && appearanceProp.value.expression && appearanceProp.value.expression.type === 'Literal') {
185
+ return fixer.replaceText(appearanceProp.value.expression, `"${mappedValue}"`);
186
+ }
187
+ return null;
188
+ }
189
+ });
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Handle isBold prop and Tag migration
196
+ if (isBoldProp) {
197
+ if (isLiteralFalse(isBoldProp.value)) {
198
+ // isBold={false} should migrate to Tag
199
+ context.report({
200
+ node: node,
201
+ messageId: 'migrateTag',
202
+ fix: fixer => {
203
+ const replacement = generateTagReplacement(node);
204
+ return fixer.replaceText(node, replacement);
205
+ }
206
+ });
207
+ } else if (isDynamicExpression(isBoldProp.value)) {
208
+ // Dynamic isBold requires manual review
209
+ context.report({
210
+ node: isBoldProp,
211
+ messageId: 'manualReview'
212
+ });
213
+ }
214
+ // isBold={true} or isBold (implicit true) - no action needed
215
+ } else {
216
+ // No isBold prop means implicit false, should migrate to Tag
217
+ context.report({
218
+ node: node,
219
+ messageId: 'migrateTag',
220
+ fix: fixer => {
221
+ const replacement = generateTagReplacement(node);
222
+ return fixer.replaceText(node, replacement);
223
+ }
224
+ });
225
+ }
226
+ }
227
+ };
228
+ }
229
+ });
230
+ 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::5aac2d8dc7c2832bcb8a96a143d60db5>>
3
+ * @codegen <<SignedSource::7fae089db9d7d7153fea58c673bd56af>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -15,6 +15,7 @@ var rules = {
15
15
  '@atlaskit/design-system/ensure-icon-color': 'error',
16
16
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
17
17
  '@atlaskit/design-system/icon-label': 'warn',
18
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
18
19
  '@atlaskit/design-system/no-banned-imports': 'error',
19
20
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
20
21
  '@atlaskit/design-system/no-css-tagged-template-expression': '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::43ea4411c4e338a916772d4bfda146cc>>
3
+ * @codegen <<SignedSource::655d7f24171da0dff60003d0f235e48a>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -14,6 +14,7 @@ var rules = {
14
14
  '@atlaskit/design-system/ensure-icon-color': 'error',
15
15
  '@atlaskit/design-system/ensure-proper-xcss-usage': 'error',
16
16
  '@atlaskit/design-system/icon-label': 'warn',
17
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
17
18
  '@atlaskit/design-system/no-banned-imports': 'error',
18
19
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
19
20
  '@atlaskit/design-system/no-css-tagged-template-expression': '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::3328b9c675a0d09876dcfbc5d29bc63f>>
3
+ * @codegen <<SignedSource::44a03b30a12e3b52d720c16785c9c649>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ var rules = {
11
11
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
12
12
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
13
13
  '@atlaskit/design-system/icon-label': 'warn',
14
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
14
15
  '@atlaskit/design-system/no-banned-imports': 'error',
15
16
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
16
17
  '@atlaskit/design-system/no-deprecated-apis': '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::b28f895280627b7a35f059f90783644a>>
3
+ * @codegen <<SignedSource::0311febdad396820af1b01dd2825b63f>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -10,6 +10,7 @@ var rules = {
10
10
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
11
11
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
12
12
  '@atlaskit/design-system/icon-label': 'warn',
13
+ '@atlaskit/design-system/lozenge-appearance-and-isbold-migration': 'warn',
13
14
  '@atlaskit/design-system/no-banned-imports': 'error',
14
15
  '@atlaskit/design-system/no-boolean-autofocus-on-modal-dialog': 'warn',
15
16
  '@atlaskit/design-system/no-deprecated-apis': '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::732bff0fc39d7ff05b6688694101698d>>
3
+ * @codegen <<SignedSource::75f94fc6b6fa998eed54b610e41bb9b1>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
 
@@ -11,6 +11,7 @@ import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
11
11
  import ensureIconColor from './ensure-icon-color';
12
12
  import ensureProperXcssUsage from './ensure-proper-xcss-usage';
13
13
  import iconLabel from './icon-label';
14
+ import lozengeAppearanceAndIsboldMigration from './lozenge-appearance-and-isbold-migration';
14
15
  import noBannedImports from './no-banned-imports';
15
16
  import noBooleanAutofocusOnModalDialog from './no-boolean-autofocus-on-modal-dialog';
16
17
  import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
@@ -80,6 +81,7 @@ export var rules = {
80
81
  'ensure-icon-color': ensureIconColor,
81
82
  'ensure-proper-xcss-usage': ensureProperXcssUsage,
82
83
  'icon-label': iconLabel,
84
+ 'lozenge-appearance-and-isbold-migration': lozengeAppearanceAndIsboldMigration,
83
85
  'no-banned-imports': noBannedImports,
84
86
  'no-boolean-autofocus-on-modal-dialog': noBooleanAutofocusOnModalDialog,
85
87
  'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
@@ -0,0 +1,230 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import { createLintRule } from '../utils/create-rule';
3
+ var rule = createLintRule({
4
+ meta: {
5
+ name: 'lozenge-appearance-and-isbold-migration',
6
+ fixable: 'code',
7
+ type: 'suggestion',
8
+ docs: {
9
+ description: 'Helps migrate deprecated Lozenge usages to the new API or Tag component as part of the Labelling System Phase 1 migration.',
10
+ recommended: true,
11
+ severity: 'warn'
12
+ },
13
+ messages: {
14
+ updateAppearance: 'Update appearance value to new semantic value.',
15
+ migrateTag: 'Non-bold <Lozenge> variants should migrate to <Tag> component.',
16
+ manualReview: "Dynamic 'isBold' props require manual review before migration."
17
+ }
18
+ },
19
+ create: function create(context) {
20
+ /**
21
+ * Contains a map of imported Lozenge components.
22
+ */
23
+ var lozengeImports = {}; // local name -> import source
24
+
25
+ /**
26
+ * Check if a JSX attribute value is a literal false
27
+ */
28
+ function isLiteralFalse(node) {
29
+ return node && node.type === 'JSXExpressionContainer' && node.expression && node.expression.type === 'Literal' && node.expression.value === false;
30
+ }
31
+
32
+ /**
33
+ * Check if a JSX attribute value is dynamic (not a literal boolean)
34
+ */
35
+ function isDynamicExpression(node) {
36
+ if (!node || node.type !== 'JSXExpressionContainer') {
37
+ return false;
38
+ }
39
+ var expr = node.expression;
40
+ return expr && !(expr.type === 'Literal' && typeof expr.value === 'boolean');
41
+ }
42
+
43
+ /**
44
+ * Get all attributes as an object for easier manipulation
45
+ */
46
+ function getAttributesMap(attributes) {
47
+ var map = {};
48
+ attributes.forEach(function (attr) {
49
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
50
+ map[attr.name.name] = attr;
51
+ }
52
+ });
53
+ return map;
54
+ }
55
+
56
+ /**
57
+ * Map old appearance values to new semantic appearance values
58
+ * Both Lozenge and Tag now use the same appearance prop with new semantic values
59
+ */
60
+ function mapToNewAppearanceValue(oldValue) {
61
+ var mapping = {
62
+ success: 'success',
63
+ default: 'default',
64
+ removed: 'removed',
65
+ inprogress: 'inprogress',
66
+ new: 'new',
67
+ moved: 'moved'
68
+ };
69
+ // TODO: Update this mapping based on actual new semantic values when provided
70
+ return mapping[oldValue] || oldValue;
71
+ }
72
+
73
+ /**
74
+ * Extract the string value from a JSX attribute value
75
+ */
76
+ function extractStringValue(attrValue) {
77
+ if (!attrValue) {
78
+ return null;
79
+ }
80
+ if (attrValue.type === 'Literal') {
81
+ return attrValue.value;
82
+ }
83
+ if (attrValue.type === 'JSXExpressionContainer' && attrValue.expression && attrValue.expression.type === 'Literal') {
84
+ return attrValue.expression.value;
85
+ }
86
+ return null;
87
+ }
88
+
89
+ /**
90
+ * Generate the replacement JSX element text
91
+ */
92
+ function generateTagReplacement(node) {
93
+ var sourceCode = context.getSourceCode();
94
+ var attributes = node.openingElement.attributes;
95
+
96
+ // Build new attributes array, excluding isBold and mapping appearance values to new semantics
97
+ var newAttributes = [];
98
+ attributes.forEach(function (attr) {
99
+ if (attr.type === 'JSXAttribute' && attr.name.type === 'JSXIdentifier') {
100
+ var attrName = attr.name.name;
101
+ if (attrName === 'isBold') {
102
+ // Skip isBold attribute
103
+ return;
104
+ }
105
+ if (attrName === 'appearance') {
106
+ // Map appearance value to new semantic value but keep the prop name as appearance
107
+ var stringValue = extractStringValue(attr.value);
108
+ if (stringValue && typeof stringValue === 'string') {
109
+ var mappedAppearance = mapToNewAppearanceValue(stringValue);
110
+ newAttributes.push("appearance=\"".concat(mappedAppearance, "\""));
111
+ } else {
112
+ // If we can't extract the string value, keep as-is with appearance prop
113
+ var value = attr.value ? sourceCode.getText(attr.value) : '';
114
+ newAttributes.push("appearance".concat(value ? "=".concat(value) : ''));
115
+ }
116
+ return;
117
+ }
118
+
119
+ // Keep all other attributes
120
+ newAttributes.push(sourceCode.getText(attr));
121
+ } else if (attr.type === 'JSXSpreadAttribute') {
122
+ // Keep spread attributes
123
+ newAttributes.push(sourceCode.getText(attr));
124
+ }
125
+ });
126
+ var attributesText = newAttributes.length > 0 ? " ".concat(newAttributes.join(' ')) : '';
127
+ var children = node.children.length > 0 ? sourceCode.getText().slice(node.openingElement.range[1], node.closingElement ? node.closingElement.range[0] : node.range[1]) : '';
128
+ if (node.closingElement) {
129
+ return "<Tag".concat(attributesText, ">").concat(children, "</Tag>");
130
+ } else {
131
+ return "<Tag".concat(attributesText, " />");
132
+ }
133
+ }
134
+ return {
135
+ ImportDeclaration: function ImportDeclaration(node) {
136
+ var moduleSource = node.source.value;
137
+ if (typeof moduleSource === 'string') {
138
+ // Track Lozenge imports
139
+ if (moduleSource === '@atlaskit/lozenge' || moduleSource.startsWith('@atlaskit/lozenge')) {
140
+ node.specifiers.forEach(function (spec) {
141
+ if (spec.type === 'ImportDefaultSpecifier') {
142
+ lozengeImports[spec.local.name] = moduleSource;
143
+ } else if (spec.type === 'ImportSpecifier' && spec.imported.type === 'Identifier') {
144
+ if (spec.imported.name === 'Lozenge') {
145
+ lozengeImports[spec.local.name] = moduleSource;
146
+ }
147
+ }
148
+ });
149
+ }
150
+ }
151
+ },
152
+ JSXElement: function JSXElement(node) {
153
+ if (!isNodeOfType(node, 'JSXElement')) {
154
+ return;
155
+ }
156
+ if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
157
+ return;
158
+ }
159
+ var elementName = node.openingElement.name.name;
160
+
161
+ // Only process if this is a Lozenge component we've imported
162
+ if (!lozengeImports[elementName]) {
163
+ return;
164
+ }
165
+ var attributesMap = getAttributesMap(node.openingElement.attributes);
166
+ var appearanceProp = attributesMap.appearance;
167
+ var isBoldProp = attributesMap.isBold;
168
+
169
+ // Handle appearance prop value migration
170
+ if (appearanceProp) {
171
+ var shouldMigrateToTag = !isBoldProp || isLiteralFalse(isBoldProp.value);
172
+ if (!shouldMigrateToTag) {
173
+ // Only update appearance values for Lozenge components that stay as Lozenge
174
+ var stringValue = extractStringValue(appearanceProp.value);
175
+ if (stringValue && typeof stringValue === 'string') {
176
+ var mappedValue = mapToNewAppearanceValue(stringValue);
177
+ if (mappedValue !== stringValue) {
178
+ context.report({
179
+ node: appearanceProp,
180
+ messageId: 'updateAppearance',
181
+ fix: function fix(fixer) {
182
+ if (appearanceProp.value.type === 'Literal') {
183
+ return fixer.replaceText(appearanceProp.value, "\"".concat(mappedValue, "\""));
184
+ } else if (appearanceProp.value.type === 'JSXExpressionContainer' && appearanceProp.value.expression && appearanceProp.value.expression.type === 'Literal') {
185
+ return fixer.replaceText(appearanceProp.value.expression, "\"".concat(mappedValue, "\""));
186
+ }
187
+ return null;
188
+ }
189
+ });
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Handle isBold prop and Tag migration
196
+ if (isBoldProp) {
197
+ if (isLiteralFalse(isBoldProp.value)) {
198
+ // isBold={false} should migrate to Tag
199
+ context.report({
200
+ node: node,
201
+ messageId: 'migrateTag',
202
+ fix: function fix(fixer) {
203
+ var replacement = generateTagReplacement(node);
204
+ return fixer.replaceText(node, replacement);
205
+ }
206
+ });
207
+ } else if (isDynamicExpression(isBoldProp.value)) {
208
+ // Dynamic isBold requires manual review
209
+ context.report({
210
+ node: isBoldProp,
211
+ messageId: 'manualReview'
212
+ });
213
+ }
214
+ // isBold={true} or isBold (implicit true) - no action needed
215
+ } else {
216
+ // No isBold prop means implicit false, should migrate to Tag
217
+ context.report({
218
+ node: node,
219
+ messageId: 'migrateTag',
220
+ fix: function fix(fixer) {
221
+ var replacement = generateTagReplacement(node);
222
+ return fixer.replaceText(node, replacement);
223
+ }
224
+ });
225
+ }
226
+ }
227
+ };
228
+ }
229
+ });
230
+ 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::5aac2d8dc7c2832bcb8a96a143d60db5>>
3
+ * @codegen <<SignedSource::7fae089db9d7d7153fea58c673bd56af>>
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::43ea4411c4e338a916772d4bfda146cc>>
3
+ * @codegen <<SignedSource::655d7f24171da0dff60003d0f235e48a>>
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::3328b9c675a0d09876dcfbc5d29bc63f>>
3
+ * @codegen <<SignedSource::44a03b30a12e3b52d720c16785c9c649>>
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::b28f895280627b7a35f059f90783644a>>
3
+ * @codegen <<SignedSource::0311febdad396820af1b01dd2825b63f>>
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::732bff0fc39d7ff05b6688694101698d>>
3
+ * @codegen <<SignedSource::75f94fc6b6fa998eed54b610e41bb9b1>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { Rule } from 'eslint';
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ 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::5aac2d8dc7c2832bcb8a96a143d60db5>>
3
+ * @codegen <<SignedSource::7fae089db9d7d7153fea58c673bd56af>>
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::43ea4411c4e338a916772d4bfda146cc>>
3
+ * @codegen <<SignedSource::655d7f24171da0dff60003d0f235e48a>>
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::3328b9c675a0d09876dcfbc5d29bc63f>>
3
+ * @codegen <<SignedSource::44a03b30a12e3b52d720c16785c9c649>>
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::b28f895280627b7a35f059f90783644a>>
3
+ * @codegen <<SignedSource::0311febdad396820af1b01dd2825b63f>>
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::732bff0fc39d7ff05b6688694101698d>>
3
+ * @codegen <<SignedSource::75f94fc6b6fa998eed54b610e41bb9b1>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import type { Rule } from 'eslint';
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ 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.23.4",
4
+ "version": "13.24.1",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {