@entur/typography 1.10.0-beta.1 โ 1.10.0-beta.10
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.
- package/README.md +12 -11
- package/dist/beta/utils.d.ts +2 -1
- package/dist/typography.cjs.development.js +22 -2
- package/dist/typography.cjs.development.js.map +1 -1
- package/dist/typography.cjs.production.min.js +1 -1
- package/dist/typography.cjs.production.min.js.map +1 -1
- package/dist/typography.esm.js +22 -2
- package/dist/typography.esm.js.map +1 -1
- package/package.json +6 -2
- package/scripts/migrate-typography.js +543 -142
|
@@ -18,21 +18,16 @@
|
|
|
18
18
|
* * Styling classes may change
|
|
19
19
|
* * Test thoroughly after migration!
|
|
20
20
|
*
|
|
21
|
-
|
|
22
|
-
* - Only updates import paths from '@entur/typography' to '@entur/typography'
|
|
23
|
-
* - Keeps your existing component usage unchanged
|
|
24
|
-
* - Minimal risk, allows gradual migration
|
|
25
|
-
* - You can manually update components later
|
|
21
|
+
|
|
26
22
|
*
|
|
27
23
|
* Usage:
|
|
28
24
|
* 1. Run this script in your project root
|
|
29
|
-
* 2. Choose your migration mode (complete
|
|
25
|
+
* 2. Choose your migration mode (complete)
|
|
30
26
|
* 3. Update your styles as needed
|
|
31
27
|
* 4. Test your application thoroughly
|
|
32
28
|
*
|
|
33
29
|
* Options:
|
|
34
30
|
* --dry-run Show what would be changed without modifying files
|
|
35
|
-
* --import-only Import-only migration: update import paths only
|
|
36
31
|
*
|
|
37
32
|
* Environment Variables:
|
|
38
33
|
* TYPOGRAPHY_MIGRATION_DIRS Comma-separated list of directories to scan
|
|
@@ -72,6 +67,31 @@ try {
|
|
|
72
67
|
const OLD_IMPORT = '@entur/typography';
|
|
73
68
|
const BETA_IMPORT = '@entur/typography';
|
|
74
69
|
|
|
70
|
+
// Enhanced warning detection patterns - only truly problematic patterns
|
|
71
|
+
const PROBLEMATIC_PATTERNS = {
|
|
72
|
+
// Style conflicts that will cause issues
|
|
73
|
+
styleMarginConflict: /style=.*margin=/g,
|
|
74
|
+
styleSpacingConflict: /style=.*spacing=/g,
|
|
75
|
+
|
|
76
|
+
// Invalid HTML structure
|
|
77
|
+
nestedTypography: /<Text[^>]*>.*<Text[^>]*>/g,
|
|
78
|
+
|
|
79
|
+
// Accessibility issues
|
|
80
|
+
missingAsProps: /<Heading[^>]*>(?!.*\bas=)/g,
|
|
81
|
+
|
|
82
|
+
// Semantic HTML mismatches
|
|
83
|
+
semanticMismatch: /<Heading[^>]*as="([^"]*)"[^>]*variant="([^"]*)"/g,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Warning severity levels
|
|
87
|
+
const WARNING_CATEGORIES = {
|
|
88
|
+
CRITICAL: 'critical', // Will break functionality
|
|
89
|
+
HIGH: 'high', // Likely to cause issues
|
|
90
|
+
MEDIUM: 'medium', // May cause styling issues
|
|
91
|
+
LOW: 'low', // Best practice suggestions
|
|
92
|
+
INFO: 'info', // Informational only
|
|
93
|
+
};
|
|
94
|
+
|
|
75
95
|
// =============================================================================
|
|
76
96
|
// ๐ฏ MIGRATION FOLDERS CONFIGURATION
|
|
77
97
|
// =============================================================================
|
|
@@ -114,6 +134,153 @@ function validateDirectoryPath(dir) {
|
|
|
114
134
|
return !path.isAbsolute(dir) && !dir.includes('..') && !dir.includes('~');
|
|
115
135
|
}
|
|
116
136
|
|
|
137
|
+
// Enhanced file analysis for better warning detection - only truly problematic patterns
|
|
138
|
+
function analyzeFile(filePath, content) {
|
|
139
|
+
const analysis = {
|
|
140
|
+
hasStyleConflicts: false,
|
|
141
|
+
hasNestedTypography: false,
|
|
142
|
+
hasAccessibilityIssues: false,
|
|
143
|
+
hasSemanticMismatches: false,
|
|
144
|
+
lineNumbers: {},
|
|
145
|
+
suggestions: [],
|
|
146
|
+
warnings: [],
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Line-by-line analysis for better context
|
|
150
|
+
content.split('\n').forEach((line, index) => {
|
|
151
|
+
const lineNum = index + 1;
|
|
152
|
+
|
|
153
|
+
// Check for style conflicts (style + margin/spacing)
|
|
154
|
+
if (
|
|
155
|
+
line.match(PROBLEMATIC_PATTERNS.styleMarginConflict) ||
|
|
156
|
+
line.match(PROBLEMATIC_PATTERNS.styleSpacingConflict)
|
|
157
|
+
) {
|
|
158
|
+
analysis.hasStyleConflicts = true;
|
|
159
|
+
analysis.lineNumbers.styleConflicts = (
|
|
160
|
+
analysis.lineNumbers.styleConflicts || []
|
|
161
|
+
).concat(lineNum);
|
|
162
|
+
|
|
163
|
+
// Generate warning message
|
|
164
|
+
analysis.warnings.push(
|
|
165
|
+
`Line ${lineNum}: Style conflicts detected - component has both style and margin/spacing props`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Check for nested typography components (invalid HTML)
|
|
170
|
+
if (line.match(PROBLEMATIC_PATTERNS.nestedTypography)) {
|
|
171
|
+
analysis.hasNestedTypography = true;
|
|
172
|
+
analysis.lineNumbers.nestedTypography = (
|
|
173
|
+
analysis.lineNumbers.nestedTypography || []
|
|
174
|
+
).concat(lineNum);
|
|
175
|
+
|
|
176
|
+
// Generate warning message
|
|
177
|
+
analysis.warnings.push(
|
|
178
|
+
`Line ${lineNum}: Nested typography components detected - invalid HTML structure`,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check for missing as props (accessibility issue)
|
|
183
|
+
if (line.match(PROBLEMATIC_PATTERNS.missingAsProps)) {
|
|
184
|
+
analysis.hasAccessibilityIssues = true;
|
|
185
|
+
analysis.lineNumbers.missingAsProps = (
|
|
186
|
+
analysis.lineNumbers.missingAsProps || []
|
|
187
|
+
).concat(lineNum);
|
|
188
|
+
|
|
189
|
+
// Generate warning message
|
|
190
|
+
analysis.warnings.push(
|
|
191
|
+
`Line ${lineNum}: Missing 'as' prop - accessibility issue for Heading component`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Check for semantic mismatches (e.g., h1 with subtitle variant)
|
|
196
|
+
if (line.match(PROBLEMATIC_PATTERNS.semanticMismatch)) {
|
|
197
|
+
analysis.hasSemanticMismatches = true;
|
|
198
|
+
analysis.lineNumbers.semanticMismatches = (
|
|
199
|
+
analysis.lineNumbers.semanticMismatches || []
|
|
200
|
+
).concat(lineNum);
|
|
201
|
+
|
|
202
|
+
// Generate warning message
|
|
203
|
+
analysis.warnings.push(
|
|
204
|
+
`Line ${lineNum}: Semantic mismatch detected - heading level and variant combination may be incorrect`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return analysis;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Generate enhanced warnings with context and solutions
|
|
213
|
+
function generateWarningWithSolution(warning, context, filePath, lineNumber) {
|
|
214
|
+
const severity = determineSeverity(warning);
|
|
215
|
+
const suggestion = generateSuggestion(warning, context);
|
|
216
|
+
const codeExample = generateCodeExample(warning);
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
message: warning,
|
|
220
|
+
severity,
|
|
221
|
+
suggestion,
|
|
222
|
+
codeExample,
|
|
223
|
+
file: filePath,
|
|
224
|
+
line: lineNumber,
|
|
225
|
+
documentation: getRelevantDocs(warning),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Determine warning severity based on content
|
|
230
|
+
function determineSeverity(warning) {
|
|
231
|
+
if (warning.includes('will break') || warning.includes('fatal'))
|
|
232
|
+
return WARNING_CATEGORIES.CRITICAL;
|
|
233
|
+
if (warning.includes('conflict') || warning.includes('override'))
|
|
234
|
+
return WARNING_CATEGORIES.HIGH;
|
|
235
|
+
if (warning.includes('may cause') || warning.includes('styling'))
|
|
236
|
+
return WARNING_CATEGORIES.MEDIUM;
|
|
237
|
+
if (warning.includes('best practice') || warning.includes('consider'))
|
|
238
|
+
return WARNING_CATEGORIES.LOW;
|
|
239
|
+
return WARNING_CATEGORIES.INFO;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Generate actionable suggestions
|
|
243
|
+
function generateSuggestion(warning, context) {
|
|
244
|
+
if (warning.includes('style and margin')) {
|
|
245
|
+
return 'Remove the margin prop as it will be overridden by inline styles. Use spacing prop instead.';
|
|
246
|
+
}
|
|
247
|
+
if (warning.includes('missing variant')) {
|
|
248
|
+
return 'Add a variant prop to ensure consistent styling. Example: variant="title-1"';
|
|
249
|
+
}
|
|
250
|
+
if (warning.includes('nested typography')) {
|
|
251
|
+
return 'Avoid nesting Text components. Use spans or other inline elements for emphasis.';
|
|
252
|
+
}
|
|
253
|
+
if (warning.includes('deprecated margin')) {
|
|
254
|
+
return 'Replace margin prop with spacing prop for better consistency.';
|
|
255
|
+
}
|
|
256
|
+
return 'Review the component for potential styling conflicts.';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Generate code examples for fixes
|
|
260
|
+
function generateCodeExample(warning) {
|
|
261
|
+
if (warning.includes('style and margin')) {
|
|
262
|
+
return '// Before: <Text style={{color: "red"}} margin="bottom">\n// After: <Text style={{color: "red"}} spacing="bottom">';
|
|
263
|
+
}
|
|
264
|
+
if (warning.includes('missing variant')) {
|
|
265
|
+
return '// Before: <Heading as="h1">Title</Heading>\n// After: <Heading as="h1" variant="title-1">Title</Heading>';
|
|
266
|
+
}
|
|
267
|
+
if (warning.includes('nested typography')) {
|
|
268
|
+
return '// Before: <Text>Hello <Text>World</Text></Text>\n// After: <Text>Hello <span>World</span></Text>';
|
|
269
|
+
}
|
|
270
|
+
return '';
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Get relevant documentation links
|
|
274
|
+
function getRelevantDocs(warning) {
|
|
275
|
+
if (warning.includes('variant'))
|
|
276
|
+
return 'https://linje.entur.no/komponenter/ressurser/typography-beta#heading-variants';
|
|
277
|
+
if (warning.includes('spacing'))
|
|
278
|
+
return 'https://linje.entur.no/komponenter/ressurser/typography-beta#spacing';
|
|
279
|
+
if (warning.includes('semantic'))
|
|
280
|
+
return 'https://linje.entur.no/komponenter/ressurser/typography-beta#semantic-html';
|
|
281
|
+
return 'https://linje.entur.no/komponenter/ressurser/typography-beta';
|
|
282
|
+
}
|
|
283
|
+
|
|
117
284
|
let ALLOWED_DIRECTORIES = process.env.TYPOGRAPHY_MIGRATION_DIRS
|
|
118
285
|
? process.env.TYPOGRAPHY_MIGRATION_DIRS.split(',')
|
|
119
286
|
: MIGRATION_FOLDERS;
|
|
@@ -170,15 +337,14 @@ const COMPONENT_MAPPING = {
|
|
|
170
337
|
Heading6: { component: 'Heading', as: 'h6', variant: 'section-2' },
|
|
171
338
|
Paragraph: { component: 'Text', variant: 'paragraph' },
|
|
172
339
|
LeadParagraph: { component: 'Text', variant: 'leading' },
|
|
173
|
-
SmallText: { component: 'Text', variant: 'subparagraph'
|
|
174
|
-
StrongText: { component: 'Text',
|
|
175
|
-
SubLabel: { component: 'Text', variant: 'sublabel'
|
|
340
|
+
SmallText: { component: 'Text', variant: 'subparagraph' },
|
|
341
|
+
StrongText: { component: 'Text', as: 'strong', weight: 'bold' },
|
|
342
|
+
SubLabel: { component: 'Text', variant: 'sublabel' },
|
|
176
343
|
SubParagraph: { component: 'Text', variant: 'subparagraph' },
|
|
177
344
|
Label: { component: 'Text', variant: 'label' },
|
|
178
345
|
EmphasizedText: { component: 'Text', variant: 'emphasized' },
|
|
179
346
|
CodeText: { component: 'Text', variant: 'code-text' },
|
|
180
|
-
Link: { component: 'LinkBeta' },
|
|
181
|
-
Blockquote: { component: 'BlockquoteBeta' },
|
|
347
|
+
Link: { component: 'LinkBeta' }, // Convert Link to LinkBeta
|
|
182
348
|
};
|
|
183
349
|
|
|
184
350
|
// Props mapping for migration
|
|
@@ -187,17 +353,43 @@ const PROPS_MAPPING = {
|
|
|
187
353
|
};
|
|
188
354
|
|
|
189
355
|
// Spacing value mapping from old margin to new spacing
|
|
356
|
+
// Based on the actual CSS classes in src/beta/styles.scss
|
|
357
|
+
// and the old margin prop values: "top" | "bottom" | "both" | "none"
|
|
190
358
|
const SPACING_MAPPING = {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
359
|
+
// Old margin values mapped to new spacing values
|
|
360
|
+
none: 'none', // No spacing
|
|
361
|
+
top: 'md-top', // Top margin only (medium size)
|
|
362
|
+
bottom: 'md-bottom', // Bottom margin only (medium size)
|
|
363
|
+
both: 'md', // Both top and bottom margins (medium size)
|
|
364
|
+
|
|
365
|
+
// Additional spacing values for more granular control
|
|
366
|
+
// These weren't in the old margin prop but are available in new spacing
|
|
367
|
+
left: 'md-left', // Left margin (medium size)
|
|
368
|
+
right: 'md-right', // Right margin (medium size)
|
|
369
|
+
|
|
370
|
+
// Size-based spacing (applies to both top and bottom)
|
|
196
371
|
xs: 'xs',
|
|
197
372
|
sm: 'sm',
|
|
198
373
|
md: 'md',
|
|
199
374
|
lg: 'lg',
|
|
200
375
|
xl: 'xl',
|
|
376
|
+
|
|
377
|
+
// Specific directional spacing with sizes
|
|
378
|
+
'xs-top': 'xs-top',
|
|
379
|
+
'xs-bottom': 'xs-bottom',
|
|
380
|
+
'sm-top': 'sm-top',
|
|
381
|
+
'sm-bottom': 'sm-bottom',
|
|
382
|
+
'md-top': 'md-top',
|
|
383
|
+
'md-bottom': 'md-bottom',
|
|
384
|
+
'lg-top': 'lg-top',
|
|
385
|
+
'lg-bottom': 'lg-bottom',
|
|
386
|
+
'xl-top': 'xl-top',
|
|
387
|
+
'xl-bottom': 'xl-bottom',
|
|
388
|
+
|
|
389
|
+
// Extra small variants
|
|
390
|
+
xs2: 'xs2',
|
|
391
|
+
'xs2-top': 'xs2-top',
|
|
392
|
+
'xs2-bottom': 'xs2-bottom',
|
|
201
393
|
};
|
|
202
394
|
|
|
203
395
|
// Import patterns to handle
|
|
@@ -211,30 +403,33 @@ const IMPORT_PATTERNS = [
|
|
|
211
403
|
// Parse JSX props more robustly
|
|
212
404
|
function parseJSXProps(propsString) {
|
|
213
405
|
if (!propsString || !propsString.trim()) {
|
|
214
|
-
return { props: {}, warnings: [] };
|
|
406
|
+
return { props: {}, warnings: [], spreadProps: [] };
|
|
215
407
|
}
|
|
216
408
|
|
|
217
409
|
const props = {};
|
|
218
410
|
const warnings = [];
|
|
219
|
-
const
|
|
220
|
-
let iterationCount = 0;
|
|
411
|
+
const spreadProps = []; // Track spread props separately
|
|
221
412
|
|
|
222
413
|
try {
|
|
223
414
|
// Parse props manually to handle complex cases
|
|
224
415
|
let remaining = propsString.trim();
|
|
225
|
-
let lastRemainingLength = remaining.length;
|
|
226
416
|
|
|
227
|
-
|
|
228
|
-
|
|
417
|
+
// First, extract all spread props
|
|
418
|
+
const spreadRegex = /\.\.\.\{?(\w+)\}?/g;
|
|
419
|
+
let spreadMatch;
|
|
420
|
+
while ((spreadMatch = spreadRegex.exec(remaining)) !== null) {
|
|
421
|
+
spreadProps.push(spreadMatch[1]);
|
|
422
|
+
}
|
|
229
423
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
424
|
+
// Remove spread props from the string to parse regular props
|
|
425
|
+
remaining = remaining.replace(/\.\.\.\{?(\w+)\}?/g, '');
|
|
426
|
+
|
|
427
|
+
// Now parse regular props
|
|
428
|
+
while (remaining.trim().length > 0) {
|
|
429
|
+
// Skip whitespace
|
|
430
|
+
remaining = remaining.replace(/^\s+/, '');
|
|
236
431
|
|
|
237
|
-
// Match prop name
|
|
432
|
+
// Match prop name
|
|
238
433
|
const nameMatch = remaining.match(/^(\w+)=/);
|
|
239
434
|
if (!nameMatch) break;
|
|
240
435
|
|
|
@@ -244,7 +439,7 @@ function parseJSXProps(propsString) {
|
|
|
244
439
|
|
|
245
440
|
// Match prop value
|
|
246
441
|
if (remaining.startsWith('"') || remaining.startsWith("'")) {
|
|
247
|
-
// String value
|
|
442
|
+
// String value
|
|
248
443
|
const quote = remaining[0];
|
|
249
444
|
const endQuoteIndex = remaining.indexOf(quote, 1);
|
|
250
445
|
if (endQuoteIndex === -1) {
|
|
@@ -256,12 +451,11 @@ function parseJSXProps(propsString) {
|
|
|
256
451
|
props[propName] = propValue;
|
|
257
452
|
remaining = remaining.substring(endQuoteIndex + 1);
|
|
258
453
|
} else if (remaining.startsWith('{')) {
|
|
259
|
-
// Object value - find matching closing brace
|
|
454
|
+
// Object value - find matching closing brace
|
|
260
455
|
let braceCount = 0;
|
|
261
456
|
let endIndex = -1;
|
|
262
|
-
const maxSearchLength = Math.min(remaining.length, 1000); // Limit search length
|
|
263
457
|
|
|
264
|
-
for (let i = 0; i <
|
|
458
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
265
459
|
if (remaining[i] === '{') braceCount++;
|
|
266
460
|
if (remaining[i] === '}') {
|
|
267
461
|
braceCount--;
|
|
@@ -281,23 +475,19 @@ function parseJSXProps(propsString) {
|
|
|
281
475
|
props[propName] = propValue;
|
|
282
476
|
remaining = remaining.substring(endIndex + 1);
|
|
283
477
|
} else {
|
|
284
|
-
// Boolean prop
|
|
478
|
+
// Boolean prop
|
|
285
479
|
props[propName] = true;
|
|
286
480
|
break;
|
|
287
481
|
}
|
|
288
482
|
|
|
289
|
-
// Skip whitespace
|
|
483
|
+
// Skip whitespace
|
|
290
484
|
remaining = remaining.replace(/^\s+/, '');
|
|
291
485
|
}
|
|
292
|
-
|
|
293
|
-
if (iterationCount >= MAX_ITERATIONS) {
|
|
294
|
-
warnings.push(`Maximum parsing iterations (${MAX_ITERATIONS}) reached`);
|
|
295
|
-
}
|
|
296
486
|
} catch (error) {
|
|
297
487
|
warnings.push(`Failed to parse props: ${error.message}`);
|
|
298
488
|
}
|
|
299
489
|
|
|
300
|
-
return { props, warnings };
|
|
490
|
+
return { props, warnings, spreadProps };
|
|
301
491
|
}
|
|
302
492
|
|
|
303
493
|
// Migrate props from old to new format
|
|
@@ -315,11 +505,12 @@ function migrateProps(props, oldComponent) {
|
|
|
315
505
|
`Migrated 'margin="${props.margin}"' to 'spacing="${newSpacing}"'`,
|
|
316
506
|
);
|
|
317
507
|
} else {
|
|
318
|
-
// Unknown margin value -
|
|
319
|
-
|
|
508
|
+
// Unknown margin value - suggest alternatives
|
|
509
|
+
const suggestions = getSpacingSuggestions(props.margin);
|
|
510
|
+
migratedProps.spacing = props.margin; // Keep original value for now
|
|
320
511
|
delete migratedProps.margin;
|
|
321
512
|
warnings.push(
|
|
322
|
-
`Migrated 'margin="${props.margin}"' to 'spacing="${props.margin}"' (unknown value
|
|
513
|
+
`Migrated 'margin="${props.margin}"' to 'spacing="${props.margin}"' (unknown value). ${suggestions}`,
|
|
323
514
|
);
|
|
324
515
|
}
|
|
325
516
|
}
|
|
@@ -346,6 +537,53 @@ function migrateProps(props, oldComponent) {
|
|
|
346
537
|
return { props: migratedProps, warnings };
|
|
347
538
|
}
|
|
348
539
|
|
|
540
|
+
// Helper function to suggest spacing alternatives for unknown margin values
|
|
541
|
+
function getSpacingSuggestions(unknownMargin) {
|
|
542
|
+
const suggestions = [];
|
|
543
|
+
|
|
544
|
+
// Check if it might be one of the old margin values
|
|
545
|
+
if (['top', 'bottom', 'both', 'none'].includes(unknownMargin)) {
|
|
546
|
+
suggestions.push(
|
|
547
|
+
`"${unknownMargin}" is a valid old margin value and will be migrated correctly.`,
|
|
548
|
+
);
|
|
549
|
+
return suggestions.join(' ');
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Check if it might be a directional value
|
|
553
|
+
if (
|
|
554
|
+
unknownMargin.includes('top') ||
|
|
555
|
+
unknownMargin.includes('bottom') ||
|
|
556
|
+
unknownMargin.includes('left') ||
|
|
557
|
+
unknownMargin.includes('right')
|
|
558
|
+
) {
|
|
559
|
+
suggestions.push(
|
|
560
|
+
'Consider using directional spacing like "md-top", "sm-bottom", etc.',
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Check if it might be a size value
|
|
565
|
+
if (['xs', 'sm', 'md', 'lg', 'xl'].includes(unknownMargin)) {
|
|
566
|
+
suggestions.push(
|
|
567
|
+
'Consider using size-based spacing like "xs", "sm", "md", "lg", "xl".',
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Check if it might be a specific variant
|
|
572
|
+
if (unknownMargin.includes('xs2')) {
|
|
573
|
+
suggestions.push(
|
|
574
|
+
'Consider using "xs2", "xs2-top", or "xs2-bottom" for extra small spacing.',
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (suggestions.length === 0) {
|
|
579
|
+
suggestions.push(
|
|
580
|
+
'Old margin values: "none", "top", "bottom", "both". New spacing values: "xs", "sm", "md", "lg", "xl", and directional variants.',
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return suggestions.join(' ');
|
|
585
|
+
}
|
|
586
|
+
|
|
349
587
|
// Convert props object back to JSX string
|
|
350
588
|
function propsToString(props) {
|
|
351
589
|
if (!props || Object.keys(props).length === 0) {
|
|
@@ -379,12 +617,46 @@ function updateImports(content) {
|
|
|
379
617
|
let updatedContent = content;
|
|
380
618
|
let changes = 0;
|
|
381
619
|
|
|
620
|
+
// First, update import paths
|
|
382
621
|
IMPORT_PATTERNS.forEach(pattern => {
|
|
383
622
|
const matches = content.match(pattern) || [];
|
|
384
623
|
changes += matches.length;
|
|
385
624
|
updatedContent = updatedContent.replace(pattern, `from '${BETA_IMPORT}'`);
|
|
386
625
|
});
|
|
387
626
|
|
|
627
|
+
// Then, update destructured import names - only within @entur/typography imports
|
|
628
|
+
// Find all import statements from @entur/typography and update component names
|
|
629
|
+
const importRegex =
|
|
630
|
+
/import\s*{([^}]+)}\s*from\s*['"']@entur\/typography['"']/g;
|
|
631
|
+
|
|
632
|
+
updatedContent = updatedContent.replace(importRegex, (match, importList) => {
|
|
633
|
+
let updatedImportList = importList;
|
|
634
|
+
let hasChanges = false;
|
|
635
|
+
const uniqueComponents = new Set();
|
|
636
|
+
|
|
637
|
+
// Check each component in the import list
|
|
638
|
+
Object.entries(COMPONENT_MAPPING).forEach(([oldComponent, mapping]) => {
|
|
639
|
+
const componentRegex = new RegExp(`\\b${oldComponent}\\b`, 'g');
|
|
640
|
+
if (componentRegex.test(updatedImportList)) {
|
|
641
|
+
updatedImportList = updatedImportList.replace(
|
|
642
|
+
componentRegex,
|
|
643
|
+
mapping.component,
|
|
644
|
+
);
|
|
645
|
+
uniqueComponents.add(mapping.component);
|
|
646
|
+
hasChanges = true;
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
if (hasChanges) {
|
|
651
|
+
changes++;
|
|
652
|
+
// Deduplicate components and create clean import statement
|
|
653
|
+
const finalImportList = Array.from(uniqueComponents).join(', ');
|
|
654
|
+
return `import {${finalImportList}} from '${BETA_IMPORT}'`;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
return match;
|
|
658
|
+
});
|
|
659
|
+
|
|
388
660
|
return { content: updatedContent, changes };
|
|
389
661
|
}
|
|
390
662
|
|
|
@@ -404,8 +676,11 @@ function updateComponents(content) {
|
|
|
404
676
|
changes++;
|
|
405
677
|
|
|
406
678
|
// Parse existing props
|
|
407
|
-
const {
|
|
408
|
-
|
|
679
|
+
const {
|
|
680
|
+
props: existingProps,
|
|
681
|
+
warnings: parseWarnings,
|
|
682
|
+
spreadProps,
|
|
683
|
+
} = parseJSXProps(propsString);
|
|
409
684
|
warnings.push(...parseWarnings);
|
|
410
685
|
|
|
411
686
|
// Migrate props
|
|
@@ -425,8 +700,10 @@ function updateComponents(content) {
|
|
|
425
700
|
|
|
426
701
|
// Handle Heading components
|
|
427
702
|
if (mapping.component === 'Heading') {
|
|
428
|
-
|
|
429
|
-
const
|
|
703
|
+
// Preserve existing 'as' prop if it exists, otherwise use mapping default
|
|
704
|
+
const asValue = existingProps.as || mapping.as;
|
|
705
|
+
// Preserve existing 'variant' prop if it exists, otherwise use mapping default
|
|
706
|
+
const variantValue = existingProps.variant || mapping.variant;
|
|
430
707
|
|
|
431
708
|
// Remove as and variant from props since we'll add them separately
|
|
432
709
|
delete newProps.as;
|
|
@@ -441,7 +718,9 @@ function updateComponents(content) {
|
|
|
441
718
|
Object.assign(orderedProps, newProps);
|
|
442
719
|
|
|
443
720
|
const propsString = propsToString(orderedProps);
|
|
444
|
-
|
|
721
|
+
const spreadPropsString =
|
|
722
|
+
spreadProps.length > 0 ? ` {...${spreadProps.join(', ...')}}` : '';
|
|
723
|
+
return `<Heading as="${asValue}" variant="${variantValue}"${propsString}${spreadPropsString}>`;
|
|
445
724
|
}
|
|
446
725
|
|
|
447
726
|
// Handle other components
|
|
@@ -464,7 +743,9 @@ function updateComponents(content) {
|
|
|
464
743
|
Object.assign(finalProps, newProps);
|
|
465
744
|
|
|
466
745
|
const otherPropsString = propsToString(finalProps);
|
|
467
|
-
|
|
746
|
+
const spreadPropsString =
|
|
747
|
+
spreadProps.length > 0 ? ` {...${spreadProps.join(', ...')}}` : '';
|
|
748
|
+
return `<${componentName}${otherPropsString}${spreadPropsString}>`;
|
|
468
749
|
},
|
|
469
750
|
);
|
|
470
751
|
|
|
@@ -492,15 +773,33 @@ function updateComponents(content) {
|
|
|
492
773
|
* @returns {string[]} Array of matching file paths
|
|
493
774
|
*/
|
|
494
775
|
function findFiles(pattern) {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
776
|
+
const allFiles = [];
|
|
777
|
+
|
|
778
|
+
// Process directory patterns
|
|
779
|
+
const directoryPatterns = ALLOWED_DIRECTORIES.filter(dir =>
|
|
780
|
+
dir.includes('**'),
|
|
781
|
+
);
|
|
782
|
+
const filePatterns = ALLOWED_DIRECTORIES.filter(dir => !dir.includes('**'));
|
|
783
|
+
|
|
784
|
+
// Handle directory patterns (e.g., src/**, app/**)
|
|
785
|
+
if (directoryPatterns.length > 0) {
|
|
786
|
+
const combinedDirPattern = `{${directoryPatterns.join(',')}}/${pattern}`;
|
|
787
|
+
const dirFiles = glob.sync(combinedDirPattern, {
|
|
788
|
+
ignore: BLOCKED_DIRECTORIES,
|
|
789
|
+
nodir: true,
|
|
790
|
+
absolute: false,
|
|
791
|
+
});
|
|
792
|
+
allFiles.push(...dirFiles);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// Handle file patterns (e.g., *.jsx, *.tsx)
|
|
796
|
+
filePatterns.forEach(filePattern => {
|
|
797
|
+
const files = glob.sync(filePattern, {
|
|
798
|
+
ignore: BLOCKED_DIRECTORIES,
|
|
799
|
+
nodir: true,
|
|
800
|
+
absolute: false,
|
|
801
|
+
});
|
|
802
|
+
allFiles.push(...files);
|
|
504
803
|
});
|
|
505
804
|
|
|
506
805
|
// Use Set for efficient deduplication and filtering
|
|
@@ -521,37 +820,29 @@ function findFiles(pattern) {
|
|
|
521
820
|
return uniqueFiles;
|
|
522
821
|
}
|
|
523
822
|
|
|
524
|
-
function updateImportsAndComponents(content
|
|
823
|
+
function updateImportsAndComponents(content) {
|
|
525
824
|
let updatedContent = content;
|
|
526
825
|
let changes = 0;
|
|
527
826
|
let warnings = [];
|
|
528
827
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
changes
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
content: finalContent,
|
|
541
|
-
changes: componentChanges,
|
|
542
|
-
warnings: componentWarnings,
|
|
543
|
-
} = updateComponents(newContent);
|
|
544
|
-
updatedContent = finalContent;
|
|
545
|
-
changes = importChanges + componentChanges;
|
|
546
|
-
warnings = componentWarnings;
|
|
547
|
-
}
|
|
828
|
+
// Update both imports and components
|
|
829
|
+
const { content: newContent, changes: importChanges } =
|
|
830
|
+
updateImports(content);
|
|
831
|
+
const {
|
|
832
|
+
content: finalContent,
|
|
833
|
+
changes: componentChanges,
|
|
834
|
+
warnings: componentWarnings,
|
|
835
|
+
} = updateComponents(newContent);
|
|
836
|
+
updatedContent = finalContent;
|
|
837
|
+
changes = importChanges + componentChanges;
|
|
838
|
+
warnings = componentWarnings;
|
|
548
839
|
|
|
549
840
|
return { content: updatedContent, changes, warnings };
|
|
550
841
|
}
|
|
551
842
|
|
|
552
|
-
function generateMigrationReport(files,
|
|
843
|
+
function generateMigrationReport(files, isDryRun = false) {
|
|
553
844
|
const report = {
|
|
554
|
-
strategy,
|
|
845
|
+
strategy: 'complete',
|
|
555
846
|
totalFiles: files.length,
|
|
556
847
|
migratedFiles: 0,
|
|
557
848
|
totalChanges: 0,
|
|
@@ -564,21 +855,32 @@ function generateMigrationReport(files, strategy, isDryRun = false) {
|
|
|
564
855
|
files.forEach(file => {
|
|
565
856
|
try {
|
|
566
857
|
const content = fs.readFileSync(file, 'utf8');
|
|
858
|
+
|
|
859
|
+
// Analyze file for problematic patterns BEFORE migration
|
|
860
|
+
const fileAnalysis = analyzeFile(file, content);
|
|
861
|
+
|
|
567
862
|
const {
|
|
568
863
|
content: updatedContent,
|
|
569
864
|
changes,
|
|
570
865
|
warnings,
|
|
571
|
-
} = updateImportsAndComponents(content
|
|
866
|
+
} = updateImportsAndComponents(content);
|
|
572
867
|
|
|
573
|
-
|
|
868
|
+
// Combine migration warnings with file analysis warnings
|
|
869
|
+
const allWarnings = [...warnings, ...fileAnalysis.warnings];
|
|
870
|
+
|
|
871
|
+
if (changes > 0 || fileAnalysis.warnings.length > 0) {
|
|
574
872
|
if (!isDryRun) {
|
|
575
873
|
fs.writeFileSync(file, updatedContent, 'utf8');
|
|
576
874
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
report.
|
|
875
|
+
if (changes > 0) {
|
|
876
|
+
report.migratedFiles++;
|
|
877
|
+
report.totalChanges += changes;
|
|
878
|
+
}
|
|
879
|
+
report.totalWarnings += allWarnings.length;
|
|
880
|
+
report.files.push({ file, changes, warnings: allWarnings });
|
|
881
|
+
report.warnings.push(
|
|
882
|
+
...allWarnings.map(warning => `${file}: ${warning}`),
|
|
883
|
+
);
|
|
582
884
|
}
|
|
583
885
|
} catch (error) {
|
|
584
886
|
report.warnings.push(`${file}: Error processing file - ${error.message}`);
|
|
@@ -620,24 +922,135 @@ function printReport(report) {
|
|
|
620
922
|
w.includes('check for conflicts'),
|
|
621
923
|
);
|
|
622
924
|
|
|
925
|
+
// New warning types from file analysis
|
|
926
|
+
const styleConflictWarnings = report.warnings.filter(
|
|
927
|
+
w => w.includes('style conflicts') || w.includes('style and margin'),
|
|
928
|
+
);
|
|
929
|
+
const nestedTypographyWarnings = report.warnings.filter(w =>
|
|
930
|
+
w.includes('nested typography'),
|
|
931
|
+
);
|
|
932
|
+
const accessibilityWarnings = report.warnings.filter(
|
|
933
|
+
w => w.includes('missing as prop') || w.includes('accessibility'),
|
|
934
|
+
);
|
|
935
|
+
const semanticMismatchWarnings = report.warnings.filter(w =>
|
|
936
|
+
w.includes('semantic mismatch'),
|
|
937
|
+
);
|
|
938
|
+
|
|
623
939
|
if (marginWarnings.length > 0) {
|
|
624
940
|
console.log(
|
|
625
941
|
`\n ๐ Margin โ Spacing Migrations (${marginWarnings.length}):`,
|
|
626
942
|
);
|
|
627
|
-
|
|
943
|
+
// Show first 5 warnings, then summarize the rest
|
|
944
|
+
marginWarnings
|
|
945
|
+
.slice(0, 5)
|
|
946
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
947
|
+
if (marginWarnings.length > 5) {
|
|
948
|
+
console.log(
|
|
949
|
+
` ... and ${marginWarnings.length - 5} more similar warnings`,
|
|
950
|
+
);
|
|
951
|
+
}
|
|
628
952
|
}
|
|
629
953
|
|
|
630
954
|
if (semanticWarnings.length > 0) {
|
|
631
955
|
console.log(`\n ๐ฏ Semantic HTML Issues (${semanticWarnings.length}):`);
|
|
632
|
-
|
|
956
|
+
// Show first 5 warnings, then summarize the rest
|
|
957
|
+
semanticWarnings
|
|
958
|
+
.slice(0, 5)
|
|
959
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
960
|
+
if (semanticWarnings.length > 5) {
|
|
961
|
+
console.log(
|
|
962
|
+
` ... and ${semanticWarnings.length - 5} more similar warnings`,
|
|
963
|
+
);
|
|
964
|
+
}
|
|
633
965
|
}
|
|
634
966
|
|
|
635
967
|
if (conflictWarnings.length > 0) {
|
|
636
968
|
console.log(`\n ๐จ Style Conflicts (${conflictWarnings.length}):`);
|
|
637
|
-
|
|
969
|
+
// Show first 5 warnings, then summarize the rest
|
|
970
|
+
conflictWarnings
|
|
971
|
+
.slice(0, 5)
|
|
972
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
973
|
+
if (conflictWarnings.length > 5) {
|
|
974
|
+
console.log(
|
|
975
|
+
` ... and ${conflictWarnings.length - 5} more similar warnings`,
|
|
976
|
+
);
|
|
977
|
+
}
|
|
638
978
|
console.log(` โ Review these components for styling conflicts`);
|
|
639
979
|
}
|
|
640
980
|
|
|
981
|
+
// Display new warning types
|
|
982
|
+
if (styleConflictWarnings.length > 0) {
|
|
983
|
+
console.log(
|
|
984
|
+
`\n ๐จ Style + Margin Conflicts (${styleConflictWarnings.length}):`,
|
|
985
|
+
);
|
|
986
|
+
styleConflictWarnings
|
|
987
|
+
.slice(0, 5)
|
|
988
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
989
|
+
if (styleConflictWarnings.length > 5) {
|
|
990
|
+
console.log(
|
|
991
|
+
` ... and ${
|
|
992
|
+
styleConflictWarnings.length - 5
|
|
993
|
+
} more similar warnings`,
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
console.log(` โ Remove margin prop when using inline styles`);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
if (nestedTypographyWarnings.length > 0) {
|
|
1000
|
+
console.log(
|
|
1001
|
+
`\n ๐ซ Nested Typography (${nestedTypographyWarnings.length}):`,
|
|
1002
|
+
);
|
|
1003
|
+
nestedTypographyWarnings
|
|
1004
|
+
.slice(0, 5)
|
|
1005
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
1006
|
+
if (nestedTypographyWarnings.length > 5) {
|
|
1007
|
+
console.log(
|
|
1008
|
+
` ... and ${
|
|
1009
|
+
nestedTypographyWarnings.length - 5
|
|
1010
|
+
} more similar warnings`,
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
console.log(
|
|
1014
|
+
` โ Use spans or other inline elements instead of nested Text components`,
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if (accessibilityWarnings.length > 0) {
|
|
1019
|
+
console.log(
|
|
1020
|
+
`\n โฟ Accessibility Issues (${accessibilityWarnings.length}):`,
|
|
1021
|
+
);
|
|
1022
|
+
accessibilityWarnings
|
|
1023
|
+
.slice(0, 5)
|
|
1024
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
1025
|
+
if (accessibilityWarnings.length > 5) {
|
|
1026
|
+
console.log(
|
|
1027
|
+
` ... and ${
|
|
1028
|
+
accessibilityWarnings.length - 5
|
|
1029
|
+
} more similar warnings`,
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
console.log(
|
|
1033
|
+
` โ Add 'as' prop to Heading components for proper semantic HTML`,
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
if (semanticMismatchWarnings.length > 0) {
|
|
1038
|
+
console.log(
|
|
1039
|
+
`\n ๐ Semantic Mismatches (${semanticMismatchWarnings.length}):`,
|
|
1040
|
+
);
|
|
1041
|
+
semanticMismatchWarnings
|
|
1042
|
+
.slice(0, 5)
|
|
1043
|
+
.forEach(warning => console.log(` ${warning}`));
|
|
1044
|
+
if (semanticMismatchWarnings.length > 5) {
|
|
1045
|
+
console.log(
|
|
1046
|
+
` ... and ${
|
|
1047
|
+
semanticMismatchWarnings.length - 5
|
|
1048
|
+
} more similar warnings`,
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
console.log(` โ Review heading level and variant combinations`);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
641
1054
|
console.log('\n๐ Summary:');
|
|
642
1055
|
if (marginWarnings.length > 0)
|
|
643
1056
|
console.log(
|
|
@@ -651,26 +1064,42 @@ function printReport(report) {
|
|
|
651
1064
|
console.log(
|
|
652
1065
|
` โข ${conflictWarnings.length} style conflicts need manual review`,
|
|
653
1066
|
);
|
|
1067
|
+
if (styleConflictWarnings.length > 0)
|
|
1068
|
+
console.log(
|
|
1069
|
+
` โข ${styleConflictWarnings.length} style + margin conflicts detected`,
|
|
1070
|
+
);
|
|
1071
|
+
if (nestedTypographyWarnings.length > 0)
|
|
1072
|
+
console.log(
|
|
1073
|
+
` โข ${nestedTypographyWarnings.length} nested typography components found`,
|
|
1074
|
+
);
|
|
1075
|
+
if (accessibilityWarnings.length > 0)
|
|
1076
|
+
console.log(
|
|
1077
|
+
` โข ${accessibilityWarnings.length} accessibility issues need attention`,
|
|
1078
|
+
);
|
|
1079
|
+
if (semanticMismatchWarnings.length > 0)
|
|
1080
|
+
console.log(
|
|
1081
|
+
` โข ${semanticMismatchWarnings.length} semantic mismatches detected`,
|
|
1082
|
+
);
|
|
1083
|
+
|
|
1084
|
+
// Add helpful note about warning limits
|
|
1085
|
+
if (report.warnings.length > 15) {
|
|
1086
|
+
console.log(
|
|
1087
|
+
'\n๐ก Note: Only showing first 5 warnings of each type to avoid overwhelming output.',
|
|
1088
|
+
);
|
|
1089
|
+
console.log(
|
|
1090
|
+
' All warnings are still logged in the migration report above.',
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
654
1093
|
}
|
|
655
1094
|
}
|
|
656
1095
|
|
|
657
|
-
function showNextSteps(
|
|
1096
|
+
function showNextSteps() {
|
|
658
1097
|
console.log('\n๐ Next Steps');
|
|
659
1098
|
console.log('=============');
|
|
660
1099
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
Object.entries(COMPONENT_MAPPING).forEach(([old, new_]) => {
|
|
665
|
-
console.log(` ${old} โ ${new_}`);
|
|
666
|
-
});
|
|
667
|
-
console.log('3. ๐งช Test your application');
|
|
668
|
-
console.log('4. ๐ Read the migration guide on our website');
|
|
669
|
-
} else if (strategy === 'complete') {
|
|
670
|
-
console.log('1. ๐งช Test your application thoroughly');
|
|
671
|
-
console.log('2. ๐ Review and adjust any component props if needed');
|
|
672
|
-
console.log('3. ๐ Read the migration guide on our website');
|
|
673
|
-
}
|
|
1100
|
+
console.log('1. ๐งช Test your application thoroughly');
|
|
1101
|
+
console.log('2. ๐ Review and adjust any component props if needed');
|
|
1102
|
+
console.log('3. ๐ Read the migration guide on our website');
|
|
674
1103
|
|
|
675
1104
|
console.log('\nโ ๏ธ Important Notes:');
|
|
676
1105
|
console.log('- Check warnings above for potential issues');
|
|
@@ -699,36 +1128,20 @@ function main() {
|
|
|
699
1128
|
console.log(
|
|
700
1129
|
' --dry-run Show what would be changed without modifying files',
|
|
701
1130
|
);
|
|
702
|
-
console.log(
|
|
703
|
-
' --import-only Import-only migration: update import paths only',
|
|
704
|
-
);
|
|
705
|
-
|
|
706
1131
|
console.log(' --help, -h Show this help message');
|
|
707
1132
|
console.log('');
|
|
708
|
-
console.log('Migration
|
|
709
|
-
console.log(' ๐ Complete Mode
|
|
1133
|
+
console.log('Migration Mode:');
|
|
1134
|
+
console.log(' ๐ Complete Mode: Updates everything');
|
|
710
1135
|
console.log(' - Replaces old components with beta components');
|
|
711
1136
|
console.log(' - May require prop/styling updates');
|
|
712
1137
|
console.log(' - Test thoroughly after migration');
|
|
713
1138
|
console.log('');
|
|
714
|
-
console.log(
|
|
715
|
-
' ๐ Import-Only Mode (--import-only): Only updates import paths',
|
|
716
|
-
);
|
|
717
|
-
console.log(' - Keeps your existing component usage unchanged');
|
|
718
|
-
console.log(' - Minimal risk, gradual migration');
|
|
719
|
-
console.log('');
|
|
720
1139
|
console.log('Examples:');
|
|
721
1140
|
console.log(' # See what would be changed');
|
|
722
1141
|
console.log(' npx @entur/typography@latest migrate --dry-run');
|
|
723
1142
|
console.log('');
|
|
724
1143
|
console.log(' # Complete migration: update everything (default)');
|
|
725
1144
|
console.log(' npx @entur/typography@latest migrate');
|
|
726
|
-
console.log('');
|
|
727
|
-
console.log(' # Import-only migration: update import paths only');
|
|
728
|
-
console.log(' npx @entur/typography@latest migrate --import-only');
|
|
729
|
-
console.log('');
|
|
730
|
-
|
|
731
|
-
console.log('');
|
|
732
1145
|
|
|
733
1146
|
console.log('Environment Variables:');
|
|
734
1147
|
console.log(
|
|
@@ -812,36 +1225,24 @@ function main() {
|
|
|
812
1225
|
|
|
813
1226
|
// Parse command line options
|
|
814
1227
|
const isDryRun = process.argv.includes('--dry-run');
|
|
815
|
-
const isImportOnly = process.argv.includes('--import-only');
|
|
816
1228
|
|
|
817
1229
|
if (isDryRun) {
|
|
818
1230
|
console.log('๐ DRY RUN MODE: No files will be modified');
|
|
819
1231
|
console.log('');
|
|
820
1232
|
}
|
|
821
1233
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
console.log('๐ COMPLETE MIGRATION: Updating imports + component usage');
|
|
828
|
-
console.log('โ ๏ธ WARNING: This will modify your component usage!');
|
|
829
|
-
console.log(' - Old components will be replaced with beta components');
|
|
830
|
-
console.log(' - You may need to update props and styling');
|
|
831
|
-
console.log(' - Test thoroughly after migration');
|
|
832
|
-
console.log(' (Use --import-only for import-only migration)');
|
|
833
|
-
}
|
|
1234
|
+
console.log('๐ COMPLETE MIGRATION: Updating imports + component usage');
|
|
1235
|
+
console.log('โ ๏ธ WARNING: This will modify your component usage!');
|
|
1236
|
+
console.log(' - Old components will be replaced with beta components');
|
|
1237
|
+
console.log(' - You may need to update props and styling');
|
|
1238
|
+
console.log(' - Test thoroughly after migration');
|
|
834
1239
|
|
|
835
1240
|
console.log('');
|
|
836
1241
|
|
|
837
1242
|
// Perform migration
|
|
838
|
-
const report = generateMigrationReport(
|
|
839
|
-
allFiles,
|
|
840
|
-
isImportOnly ? 'import-only' : 'complete',
|
|
841
|
-
isDryRun,
|
|
842
|
-
);
|
|
1243
|
+
const report = generateMigrationReport(allFiles, isDryRun);
|
|
843
1244
|
printReport(report);
|
|
844
|
-
showNextSteps(
|
|
1245
|
+
showNextSteps();
|
|
845
1246
|
|
|
846
1247
|
console.log('\n๐ฏ Migration complete!');
|
|
847
1248
|
}
|