* Generate a simple, user-friendly 2-3 word label for the component
(component: ComponentInfo)
| 29 | * Generate a simple, user-friendly 2-3 word label for the component |
| 30 | */ |
| 31 | function generateComponentLabel(component: ComponentInfo): string { |
| 32 | // Priority 1: Use aria-label (most semantic) |
| 33 | if (component.ariaLabel) { |
| 34 | return capitalizeWords(component.ariaLabel); |
| 35 | } |
| 36 | |
| 37 | // Priority 2: Use title attribute |
| 38 | if (component.title) { |
| 39 | return capitalizeWords(component.title); |
| 40 | } |
| 41 | |
| 42 | // Priority 3: For inputs, use placeholder or type |
| 43 | if (component.tagName === 'input') { |
| 44 | if (component.placeholder) { |
| 45 | return `${capitalizeWords(component.placeholder.slice(0, 20))} Input`; |
| 46 | } |
| 47 | if (component.type) { |
| 48 | return `${capitalizeWords(component.type)} Input`; |
| 49 | } |
| 50 | return 'Text Input'; |
| 51 | } |
| 52 | |
| 53 | // Priority 4: For images, use descriptive name |
| 54 | if (component.tagName === 'img') { |
| 55 | if (component.className?.includes('hero')) return 'Hero Image'; |
| 56 | if (component.className?.includes('logo')) return 'Logo'; |
| 57 | if (component.className?.includes('avatar')) return 'Avatar'; |
| 58 | if (component.className?.includes('icon')) return 'Icon'; |
| 59 | return 'Image'; |
| 60 | } |
| 61 | |
| 62 | // Priority 5: For buttons, combine text with "Button" |
| 63 | if (component.tagName === 'button' || component.type === 'submit' || component.type === 'button') { |
| 64 | if (component.text && component.text.trim().length > 0) { |
| 65 | const buttonText = component.text.trim().split(/\s+/).slice(0, 2).join(' '); |
| 66 | return `${capitalizeWords(buttonText)} Button`; |
| 67 | } |
| 68 | return 'Button'; |
| 69 | } |
| 70 | |
| 71 | // Priority 6: Meaningful component names (not generic HTML tags) |
| 72 | const genericTags = ['div', 'span', 'section', 'article', 'main', 'aside']; |
| 73 | if (component.componentName && |
| 74 | !genericTags.includes(component.componentName.toLowerCase())) { |
| 75 | return component.componentName; |
| 76 | } |
| 77 | |
| 78 | // Priority 7: Use first 2-3 words of text content |
| 79 | if (component.text && component.text.trim().length > 0) { |
| 80 | const words = component.text.trim().split(/\s+/).slice(0, 3).join(' '); |
| 81 | if (words.length > 0 && words.length < 40) { |
| 82 | return capitalizeWords(words); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // Priority 8: Fallback based on tag name |
| 87 | const tagLabels: Record<string, string> = { |
| 88 | 'a': 'Link', |
no test coverage detected