sonance-brand-mcp 1.3.90 → 1.3.91

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.
@@ -322,41 +322,179 @@ function findElementLineInFile(
322
322
  }
323
323
  }
324
324
 
325
- // PRIORITY 3: Distinctive className patterns
326
- if (focusedElement.className) {
327
- // Extract distinctive class names (long, not hover/focus pseudo-classes)
328
- const classes = focusedElement.className.split(/\s+/)
329
- .filter(c => c.length > 8 && !c.startsWith('hover:') && !c.startsWith('focus:') && !c.startsWith('active:'));
330
-
331
- for (const cls of classes) {
325
+ // PRIORITY 2b: Look for icon patterns if type is button and no text (like X buttons)
326
+ if (focusedElement.type === 'button' && (!focusedElement.textContent || focusedElement.textContent.trim().length === 0)) {
327
+ // Common close/icon button patterns
328
+ const iconPatterns = ['<X ', '<X/', 'DialogClose', 'DialogPrimitive.Close', 'closeButton', 'CloseButton'];
329
+ for (const pattern of iconPatterns) {
332
330
  for (let i = 0; i < lines.length; i++) {
333
- if (lines[i].includes(cls)) {
331
+ if (lines[i].includes(pattern)) {
334
332
  return {
335
333
  lineNumber: i + 1,
336
334
  snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
337
- confidence: 'medium',
338
- matchedBy: `className contains "${cls}"`
335
+ confidence: 'low',
336
+ matchedBy: `icon pattern "${pattern}"`
339
337
  };
340
338
  }
341
339
  }
342
340
  }
341
+ }
342
+
343
+ // PRIORITY 3: Distinctive className patterns (ONLY semantic/custom classes)
344
+ if (focusedElement.className) {
345
+ // Filter OUT all Tailwind utility patterns - these are too generic and match wrong elements
346
+ const tailwindPatterns = [
347
+ /^p[xytblr]?-/, // padding: px-4, py-2, pt-1
348
+ /^m[xytblr]?-/, // margin: mx-auto, my-4
349
+ /^-?m[xytblr]?-/, // negative margins: -mt-4
350
+ /^w-/, // width: w-full, w-4
351
+ /^h-/, // height: h-10, h-full
352
+ /^min-/, // min-width/height
353
+ /^max-/, // max-width/height
354
+ /^size-/, // size utilities
355
+ /^bg-/, // background
356
+ /^text-/, // text color/size
357
+ /^font-/, // font-weight
358
+ /^leading-/, // line-height
359
+ /^tracking-/, // letter-spacing
360
+ /^rounded/, // border-radius: rounded-sm, rounded-lg
361
+ /^border/, // border
362
+ /^outline/, // outline
363
+ /^ring/, // ring
364
+ /^shadow/, // shadow
365
+ /^flex/, // flex utilities
366
+ /^grow/, // flex-grow
367
+ /^shrink/, // flex-shrink
368
+ /^basis-/, // flex-basis
369
+ /^grid/, // grid utilities
370
+ /^col-/, // grid columns
371
+ /^row-/, // grid rows
372
+ /^gap-/, // gap
373
+ /^items-/, // align-items
374
+ /^justify-/, // justify-content
375
+ /^self-/, // align-self
376
+ /^place-/, // place utilities
377
+ /^space-/, // space-x, space-y
378
+ /^overflow/, // overflow
379
+ /^scroll/, // scroll utilities
380
+ /^cursor-/, // cursor
381
+ /^pointer-/, // pointer-events
382
+ /^select-/, // user-select
383
+ /^opacity-/, // opacity
384
+ /^visible/, // visibility
385
+ /^invisible/, // visibility
386
+ /^z-/, // z-index
387
+ /^inset/, // inset utilities
388
+ /^top-/, // positioning
389
+ /^right-/, // positioning
390
+ /^bottom-/, // positioning
391
+ /^left-/, // positioning
392
+ /^static/, // position
393
+ /^fixed/, // position
394
+ /^absolute/, // position
395
+ /^relative/, // position
396
+ /^sticky/, // position
397
+ /^transition/, // transitions
398
+ /^duration-/, // duration
399
+ /^ease-/, // timing function
400
+ /^delay-/, // delay
401
+ /^animate-/, // animations
402
+ /^transform/, // transform
403
+ /^scale-/, // scale
404
+ /^rotate-/, // rotate
405
+ /^translate-/, // translate
406
+ /^skew-/, // skew
407
+ /^origin-/, // transform-origin
408
+ /^appearance-/, // appearance
409
+ /^accent-/, // accent-color
410
+ /^caret-/, // caret-color
411
+ /^fill-/, // SVG fill
412
+ /^stroke-/, // SVG stroke
413
+ /^object-/, // object-fit/position
414
+ /^aspect-/, // aspect-ratio
415
+ /^container/, // container
416
+ /^columns-/, // columns
417
+ /^break-/, // word-break
418
+ /^truncate/, // text-overflow
419
+ /^whitespace-/, // whitespace
420
+ /^list-/, // list-style
421
+ /^decoration-/, // text-decoration
422
+ /^underline/, // underline
423
+ /^overline/, // overline
424
+ /^line-through/, // line-through
425
+ /^no-underline/, // no underline
426
+ /^antialiased/, // font-smoothing
427
+ /^subpixel/, // subpixel-antialiased
428
+ /^italic/, // font-style
429
+ /^not-italic/, // font-style
430
+ /^uppercase/, // text-transform
431
+ /^lowercase/, // text-transform
432
+ /^capitalize/, // text-transform
433
+ /^normal-case/, // text-transform
434
+ /^align-/, // vertical-align
435
+ /^indent-/, // text-indent
436
+ /^content-/, // content
437
+ /^will-change/, // will-change
438
+ /^hover:/, // hover states
439
+ /^focus:/, // focus states
440
+ /^focus-within:/, // focus-within states
441
+ /^focus-visible:/, // focus-visible states
442
+ /^active:/, // active states
443
+ /^visited:/, // visited states
444
+ /^disabled:/, // disabled states
445
+ /^checked:/, // checked states
446
+ /^group-/, // group utilities
447
+ /^peer-/, // peer utilities
448
+ /^dark:/, // dark mode
449
+ /^light:/, // light mode
450
+ /^motion-/, // motion utilities
451
+ /^print:/, // print utilities
452
+ /^portrait:/, // orientation
453
+ /^landscape:/, // orientation
454
+ /^sm:|^md:|^lg:|^xl:|^2xl:/, // responsive prefixes
455
+ /^data-\[/, // data attribute variants
456
+ /^aria-/, // aria variants
457
+ /^supports-/, // supports variants
458
+ /^has-/, // has variants
459
+ /^group$/, // group class itself
460
+ /^peer$/, // peer class itself
461
+ /^sr-only/, // screen reader only
462
+ /^not-sr-only/, // not screen reader only
463
+ /^isolate/, // isolation
464
+ /^block$/, // display
465
+ /^inline/, // display
466
+ /^hidden$/, // display
467
+ /^table/, // display table
468
+ ];
343
469
 
344
- // Try shorter but unique-looking class names (not utility classes)
345
- const uniqueClasses = focusedElement.className.split(/\s+/)
346
- .filter(c => c.length > 4 && !c.match(/^(p[xytblr]?-|m[xytblr]?-|w-|h-|bg-|text-|flex|grid|block|hidden)/));
470
+ const isTailwindUtility = (cls: string) =>
471
+ tailwindPatterns.some(pattern => pattern.test(cls));
347
472
 
348
- for (const cls of uniqueClasses) {
349
- for (let i = 0; i < lines.length; i++) {
350
- if (lines[i].includes(cls)) {
351
- return {
352
- lineNumber: i + 1,
353
- snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
354
- confidence: 'low',
355
- matchedBy: `className contains "${cls}"`
356
- };
473
+ // Only use classes that are NOT Tailwind utilities (likely custom/semantic)
474
+ const semanticClasses = focusedElement.className.split(/\s+/)
475
+ .filter(c => c.length > 3 && !isTailwindUtility(c));
476
+
477
+ // Only proceed if we found semantic classes
478
+ if (semanticClasses.length > 0) {
479
+ for (const cls of semanticClasses) {
480
+ for (let i = 0; i < lines.length; i++) {
481
+ if (lines[i].includes(cls)) {
482
+ return {
483
+ lineNumber: i + 1,
484
+ snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
485
+ confidence: 'medium',
486
+ matchedBy: `semantic className "${cls}"`
487
+ };
488
+ }
357
489
  }
358
490
  }
359
491
  }
492
+
493
+ // Log when we filtered out all classes (helpful for debugging)
494
+ if (semanticClasses.length === 0 && focusedElement.className.trim().length > 0) {
495
+ console.log('[findElementLineInFile] All classes filtered as Tailwind utilities:',
496
+ focusedElement.className.substring(0, 100));
497
+ }
360
498
  }
361
499
 
362
500
  return null;
@@ -1512,8 +1650,9 @@ ${elementLocation.snippet}
1512
1650
  `;
1513
1651
  } else {
1514
1652
  textContent += `\n`;
1515
- debugLog("Could not locate focused element in file - no ID, textContent, or className match", {
1653
+ debugLog("WARNING: Could not locate focused element in file", {
1516
1654
  file: recommendedFileContent.path,
1655
+ hint: "The clicked element may be rendered by a child component (e.g., DialogContent, Button component). Check the component's source file instead.",
1517
1656
  focusedElements: focusedElements.map(el => ({
1518
1657
  name: el.name,
1519
1658
  type: el.type,
@@ -1522,6 +1661,18 @@ ${elementLocation.snippet}
1522
1661
  elementId: el.elementId,
1523
1662
  }))
1524
1663
  });
1664
+
1665
+ // Add a hint to the LLM that we couldn't precisely locate the element
1666
+ textContent += `
1667
+ ⚠️ WARNING: Could not precisely locate the clicked element in this file.
1668
+ The element may be:
1669
+ - Rendered by a child component (e.g., DialogContent, Button)
1670
+ - Dynamically generated
1671
+ - In a different file imported by this component
1672
+
1673
+ Please proceed with caution and verify you're modifying the correct element.
1674
+
1675
+ `;
1525
1676
  }
1526
1677
  }
1527
1678
 
@@ -318,41 +318,179 @@ function findElementLineInFile(
318
318
  }
319
319
  }
320
320
 
321
- // PRIORITY 3: Distinctive className patterns
322
- if (focusedElement.className) {
323
- // Extract distinctive class names (long, not hover/focus pseudo-classes)
324
- const classes = focusedElement.className.split(/\s+/)
325
- .filter(c => c.length > 8 && !c.startsWith('hover:') && !c.startsWith('focus:') && !c.startsWith('active:'));
326
-
327
- for (const cls of classes) {
321
+ // PRIORITY 2b: Look for icon patterns if type is button and no text (like X buttons)
322
+ if (focusedElement.type === 'button' && (!focusedElement.textContent || focusedElement.textContent.trim().length === 0)) {
323
+ // Common close/icon button patterns
324
+ const iconPatterns = ['<X ', '<X/', 'DialogClose', 'DialogPrimitive.Close', 'closeButton', 'CloseButton'];
325
+ for (const pattern of iconPatterns) {
328
326
  for (let i = 0; i < lines.length; i++) {
329
- if (lines[i].includes(cls)) {
327
+ if (lines[i].includes(pattern)) {
330
328
  return {
331
329
  lineNumber: i + 1,
332
330
  snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
333
- confidence: 'medium',
334
- matchedBy: `className contains "${cls}"`
331
+ confidence: 'low',
332
+ matchedBy: `icon pattern "${pattern}"`
335
333
  };
336
334
  }
337
335
  }
338
336
  }
337
+ }
338
+
339
+ // PRIORITY 3: Distinctive className patterns (ONLY semantic/custom classes)
340
+ if (focusedElement.className) {
341
+ // Filter OUT all Tailwind utility patterns - these are too generic and match wrong elements
342
+ const tailwindPatterns = [
343
+ /^p[xytblr]?-/, // padding: px-4, py-2, pt-1
344
+ /^m[xytblr]?-/, // margin: mx-auto, my-4
345
+ /^-?m[xytblr]?-/, // negative margins: -mt-4
346
+ /^w-/, // width: w-full, w-4
347
+ /^h-/, // height: h-10, h-full
348
+ /^min-/, // min-width/height
349
+ /^max-/, // max-width/height
350
+ /^size-/, // size utilities
351
+ /^bg-/, // background
352
+ /^text-/, // text color/size
353
+ /^font-/, // font-weight
354
+ /^leading-/, // line-height
355
+ /^tracking-/, // letter-spacing
356
+ /^rounded/, // border-radius: rounded-sm, rounded-lg
357
+ /^border/, // border
358
+ /^outline/, // outline
359
+ /^ring/, // ring
360
+ /^shadow/, // shadow
361
+ /^flex/, // flex utilities
362
+ /^grow/, // flex-grow
363
+ /^shrink/, // flex-shrink
364
+ /^basis-/, // flex-basis
365
+ /^grid/, // grid utilities
366
+ /^col-/, // grid columns
367
+ /^row-/, // grid rows
368
+ /^gap-/, // gap
369
+ /^items-/, // align-items
370
+ /^justify-/, // justify-content
371
+ /^self-/, // align-self
372
+ /^place-/, // place utilities
373
+ /^space-/, // space-x, space-y
374
+ /^overflow/, // overflow
375
+ /^scroll/, // scroll utilities
376
+ /^cursor-/, // cursor
377
+ /^pointer-/, // pointer-events
378
+ /^select-/, // user-select
379
+ /^opacity-/, // opacity
380
+ /^visible/, // visibility
381
+ /^invisible/, // visibility
382
+ /^z-/, // z-index
383
+ /^inset/, // inset utilities
384
+ /^top-/, // positioning
385
+ /^right-/, // positioning
386
+ /^bottom-/, // positioning
387
+ /^left-/, // positioning
388
+ /^static/, // position
389
+ /^fixed/, // position
390
+ /^absolute/, // position
391
+ /^relative/, // position
392
+ /^sticky/, // position
393
+ /^transition/, // transitions
394
+ /^duration-/, // duration
395
+ /^ease-/, // timing function
396
+ /^delay-/, // delay
397
+ /^animate-/, // animations
398
+ /^transform/, // transform
399
+ /^scale-/, // scale
400
+ /^rotate-/, // rotate
401
+ /^translate-/, // translate
402
+ /^skew-/, // skew
403
+ /^origin-/, // transform-origin
404
+ /^appearance-/, // appearance
405
+ /^accent-/, // accent-color
406
+ /^caret-/, // caret-color
407
+ /^fill-/, // SVG fill
408
+ /^stroke-/, // SVG stroke
409
+ /^object-/, // object-fit/position
410
+ /^aspect-/, // aspect-ratio
411
+ /^container/, // container
412
+ /^columns-/, // columns
413
+ /^break-/, // word-break
414
+ /^truncate/, // text-overflow
415
+ /^whitespace-/, // whitespace
416
+ /^list-/, // list-style
417
+ /^decoration-/, // text-decoration
418
+ /^underline/, // underline
419
+ /^overline/, // overline
420
+ /^line-through/, // line-through
421
+ /^no-underline/, // no underline
422
+ /^antialiased/, // font-smoothing
423
+ /^subpixel/, // subpixel-antialiased
424
+ /^italic/, // font-style
425
+ /^not-italic/, // font-style
426
+ /^uppercase/, // text-transform
427
+ /^lowercase/, // text-transform
428
+ /^capitalize/, // text-transform
429
+ /^normal-case/, // text-transform
430
+ /^align-/, // vertical-align
431
+ /^indent-/, // text-indent
432
+ /^content-/, // content
433
+ /^will-change/, // will-change
434
+ /^hover:/, // hover states
435
+ /^focus:/, // focus states
436
+ /^focus-within:/, // focus-within states
437
+ /^focus-visible:/, // focus-visible states
438
+ /^active:/, // active states
439
+ /^visited:/, // visited states
440
+ /^disabled:/, // disabled states
441
+ /^checked:/, // checked states
442
+ /^group-/, // group utilities
443
+ /^peer-/, // peer utilities
444
+ /^dark:/, // dark mode
445
+ /^light:/, // light mode
446
+ /^motion-/, // motion utilities
447
+ /^print:/, // print utilities
448
+ /^portrait:/, // orientation
449
+ /^landscape:/, // orientation
450
+ /^sm:|^md:|^lg:|^xl:|^2xl:/, // responsive prefixes
451
+ /^data-\[/, // data attribute variants
452
+ /^aria-/, // aria variants
453
+ /^supports-/, // supports variants
454
+ /^has-/, // has variants
455
+ /^group$/, // group class itself
456
+ /^peer$/, // peer class itself
457
+ /^sr-only/, // screen reader only
458
+ /^not-sr-only/, // not screen reader only
459
+ /^isolate/, // isolation
460
+ /^block$/, // display
461
+ /^inline/, // display
462
+ /^hidden$/, // display
463
+ /^table/, // display table
464
+ ];
339
465
 
340
- // Try shorter but unique-looking class names (not utility classes)
341
- const uniqueClasses = focusedElement.className.split(/\s+/)
342
- .filter(c => c.length > 4 && !c.match(/^(p[xytblr]?-|m[xytblr]?-|w-|h-|bg-|text-|flex|grid|block|hidden)/));
466
+ const isTailwindUtility = (cls: string) =>
467
+ tailwindPatterns.some(pattern => pattern.test(cls));
343
468
 
344
- for (const cls of uniqueClasses) {
345
- for (let i = 0; i < lines.length; i++) {
346
- if (lines[i].includes(cls)) {
347
- return {
348
- lineNumber: i + 1,
349
- snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
350
- confidence: 'low',
351
- matchedBy: `className contains "${cls}"`
352
- };
469
+ // Only use classes that are NOT Tailwind utilities (likely custom/semantic)
470
+ const semanticClasses = focusedElement.className.split(/\s+/)
471
+ .filter(c => c.length > 3 && !isTailwindUtility(c));
472
+
473
+ // Only proceed if we found semantic classes
474
+ if (semanticClasses.length > 0) {
475
+ for (const cls of semanticClasses) {
476
+ for (let i = 0; i < lines.length; i++) {
477
+ if (lines[i].includes(cls)) {
478
+ return {
479
+ lineNumber: i + 1,
480
+ snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
481
+ confidence: 'medium',
482
+ matchedBy: `semantic className "${cls}"`
483
+ };
484
+ }
353
485
  }
354
486
  }
355
487
  }
488
+
489
+ // Log when we filtered out all classes (helpful for debugging)
490
+ if (semanticClasses.length === 0 && focusedElement.className.trim().length > 0) {
491
+ console.log('[findElementLineInFile] All classes filtered as Tailwind utilities:',
492
+ focusedElement.className.substring(0, 100));
493
+ }
356
494
  }
357
495
 
358
496
  return null;
@@ -1481,8 +1619,9 @@ ${elementLocation.snippet}
1481
1619
  `;
1482
1620
  } else {
1483
1621
  textContent += `\n`;
1484
- debugLog("Could not locate focused element in file - no ID, textContent, or className match", {
1622
+ debugLog("WARNING: Could not locate focused element in file", {
1485
1623
  file: recommendedFileContent.path,
1624
+ hint: "The clicked element may be rendered by a child component (e.g., DialogContent, Button component). Check the component's source file instead.",
1486
1625
  focusedElements: focusedElements.map(el => ({
1487
1626
  name: el.name,
1488
1627
  type: el.type,
@@ -1491,6 +1630,18 @@ ${elementLocation.snippet}
1491
1630
  elementId: el.elementId,
1492
1631
  }))
1493
1632
  });
1633
+
1634
+ // Add a hint to the LLM that we couldn't precisely locate the element
1635
+ textContent += `
1636
+ ⚠️ WARNING: Could not precisely locate the clicked element in this file.
1637
+ The element may be:
1638
+ - Rendered by a child component (e.g., DialogContent, Button)
1639
+ - Dynamically generated
1640
+ - In a different file imported by this component
1641
+
1642
+ Please proceed with caution and verify you're modifying the correct element.
1643
+
1644
+ `;
1494
1645
  }
1495
1646
  }
1496
1647
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.90",
3
+ "version": "1.3.91",
4
4
  "description": "MCP Server for Sonance Brand Guidelines and Component Library - gives Claude instant access to brand colors, typography, and UI components.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",