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