@@ -16,6 +16,7 @@ import type {
1616 TextInfo ,
1717 ComponentExtractionOptions
1818} from './types.js' ;
19+ import { detectSemanticTypeAdvanced , generateSemanticContext } from '../../tools/flutter/semantic-detection.js' ;
1920
2021/**
2122 * Extract component metadata
@@ -163,7 +164,9 @@ export function analyzeChildren(
163164 nestedComponents . push ( createNestedComponentInfo ( child ) ) ;
164165 }
165166
166- children . push ( createComponentChild ( child , importance , isComponent , options ) ) ;
167+ // Pass parent and siblings for better semantic detection
168+ const siblings = visibleChildren . filter ( sibling => sibling . id !== child . id ) ;
169+ children . push ( createComponentChild ( child , importance , isComponent , options , node , siblings ) ) ;
167170 } else {
168171 // Track skipped nodes
169172 skippedNodes . push ( {
@@ -200,7 +203,9 @@ export function createComponentChild(
200203 node : FigmaNode ,
201204 importance : number ,
202205 isNestedComponent : boolean ,
203- options : Required < ComponentExtractionOptions >
206+ options : Required < ComponentExtractionOptions > ,
207+ parent ?: FigmaNode ,
208+ siblings ?: FigmaNode [ ]
204209) : ComponentChild {
205210 const child : ComponentChild = {
206211 nodeId : node . id ,
@@ -219,7 +224,7 @@ export function createComponentChild(
219224
220225 // Extract text info for text nodes
221226 if ( node . type === 'TEXT' && options . extractTextContent ) {
222- child . basicInfo . text = extractTextInfo ( node ) ;
227+ child . basicInfo . text = extractTextInfo ( node , parent , siblings ) ;
223228 }
224229 }
225230
@@ -439,7 +444,7 @@ export function extractBasicStyling(node: FigmaNode): Partial<StylingInfo> {
439444/**
440445 * Extract enhanced text information
441446 */
442- export function extractTextInfo ( node : FigmaNode ) : TextInfo | undefined {
447+ export function extractTextInfo ( node : FigmaNode , parent ?: FigmaNode , siblings ?: FigmaNode [ ] ) : TextInfo | undefined {
443448 if ( node . type !== 'TEXT' ) return undefined ;
444449
445450 const textContent = getActualTextContent ( node ) ;
@@ -453,7 +458,7 @@ export function extractTextInfo(node: FigmaNode): TextInfo | undefined {
453458 fontWeight : node . style ?. fontWeight ,
454459 textAlign : node . style ?. textAlignHorizontal ,
455460 textCase : detectTextCase ( textContent ) ,
456- semanticType : detectSemanticType ( textContent , node . name ) ,
461+ semanticType : detectSemanticType ( textContent , node . name , node , parent , siblings ) ,
457462 placeholder : isPlaceholder
458463 } ;
459464}
@@ -670,16 +675,52 @@ function detectTextCase(content: string): 'uppercase' | 'lowercase' | 'capitaliz
670675
671676/**
672677 * Detect semantic type of text based on content and context
678+ * Enhanced with multi-factor analysis and confidence scoring
673679 */
674- function detectSemanticType ( content : string , nodeName : string ) : 'heading' | 'body' | 'label' | 'button' | 'link' | 'caption' | 'error' | 'success' | 'warning' | 'other' {
675- const lowerContent = content . toLowerCase ( ) . trim ( ) ;
676- const lowerNodeName = nodeName . toLowerCase ( ) ;
677-
680+ function detectSemanticType (
681+ content : string ,
682+ nodeName : string ,
683+ node ?: any ,
684+ parent ?: any ,
685+ siblings ?: any [ ]
686+ ) : 'heading' | 'body' | 'label' | 'button' | 'link' | 'caption' | 'error' | 'success' | 'warning' | 'other' {
678687 // Skip detection for placeholder text
679688 if ( isPlaceholderText ( content ) ) {
680689 return 'other' ;
681690 }
682691
692+ // Use advanced semantic detection if node properties are available
693+ if ( node ) {
694+ try {
695+ const context = generateSemanticContext ( node , parent , siblings ) ;
696+ const classification = detectSemanticTypeAdvanced ( content , nodeName , context , node ) ;
697+
698+ // Only use advanced classification if confidence is high enough
699+ if ( classification . confidence >= 0.6 ) {
700+ return classification . type ;
701+ }
702+
703+ // Log reasoning for debugging (in development)
704+ if ( process . env . NODE_ENV === 'development' ) {
705+ console . debug ( `Low confidence (${ classification . confidence } ) for "${ content } ": ${ classification . reasoning . join ( ', ' ) } ` ) ;
706+ }
707+ } catch ( error ) {
708+ // Fall back to legacy detection if advanced detection fails
709+ console . warn ( 'Advanced semantic detection failed, using legacy method:' , error ) ;
710+ }
711+ }
712+
713+ // Legacy detection as fallback
714+ return detectSemanticTypeLegacy ( content , nodeName ) ;
715+ }
716+
717+ /**
718+ * Legacy semantic type detection (fallback)
719+ */
720+ function detectSemanticTypeLegacy ( content : string , nodeName : string ) : 'heading' | 'body' | 'label' | 'button' | 'link' | 'caption' | 'error' | 'success' | 'warning' | 'other' {
721+ const lowerContent = content . toLowerCase ( ) . trim ( ) ;
722+ const lowerNodeName = nodeName . toLowerCase ( ) ;
723+
683724 // Button text patterns - exact matches for common button labels
684725 const buttonPatterns = [
685726 / ^ ( c l i c k | t a p | p r e s s | s u b m i t | s e n d | s a v e | c a n c e l | o k | y e s | n o | c o n t i n u e | n e x t | b a c k | c l o s e | d o n e | f i n i s h | s t a r t | b e g i n ) $ / i,
0 commit comments