sonance-brand-mcp 1.3.105 → 1.3.106
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.
|
@@ -624,6 +624,52 @@ function findElementLineInFile(
|
|
|
624
624
|
}
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
+
// ========== FALLBACK MATCHING (for non-Sonance codebases) ==========
|
|
628
|
+
// These are lower confidence but help find elements in ANY codebase
|
|
629
|
+
|
|
630
|
+
// FALLBACK 1: Flexible text search (just find the text anywhere)
|
|
631
|
+
if (focusedElement.textContent && focusedElement.textContent.trim().length > 5) {
|
|
632
|
+
const searchText = focusedElement.textContent.trim().substring(0, 30);
|
|
633
|
+
for (let i = 0; i < lines.length; i++) {
|
|
634
|
+
if (lines[i].includes(searchText)) {
|
|
635
|
+
debugLog("Fallback: Flexible text match found", { searchText, lineNumber: i + 1 });
|
|
636
|
+
return {
|
|
637
|
+
lineNumber: i + 1,
|
|
638
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
639
|
+
confidence: 'low',
|
|
640
|
+
matchedBy: `flexible text match "${searchText}${focusedElement.textContent.length > 30 ? '...' : ''}"`
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// FALLBACK 2: Class fingerprint (use first few classes as unique identifier)
|
|
647
|
+
if (focusedElement.className && focusedElement.className.trim().length > 15) {
|
|
648
|
+
// Take first 2-3 distinctive classes as a fingerprint
|
|
649
|
+
const classes = focusedElement.className.trim().split(/\s+/);
|
|
650
|
+
// Filter out very common single-word utilities
|
|
651
|
+
const distinctiveClasses = classes.filter(c =>
|
|
652
|
+
c.length > 4 && !['flex', 'grid', 'block', 'hidden', 'relative', 'absolute'].includes(c)
|
|
653
|
+
).slice(0, 3);
|
|
654
|
+
|
|
655
|
+
if (distinctiveClasses.length >= 2) {
|
|
656
|
+
const fingerprint = distinctiveClasses.join(' ');
|
|
657
|
+
for (let i = 0; i < lines.length; i++) {
|
|
658
|
+
// Check if line contains ALL fingerprint classes
|
|
659
|
+
const lineHasAll = distinctiveClasses.every(cls => lines[i].includes(cls));
|
|
660
|
+
if (lineHasAll) {
|
|
661
|
+
debugLog("Fallback: Class fingerprint match found", { fingerprint, lineNumber: i + 1 });
|
|
662
|
+
return {
|
|
663
|
+
lineNumber: i + 1,
|
|
664
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
665
|
+
confidence: 'low',
|
|
666
|
+
matchedBy: `class fingerprint "${fingerprint}"`
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
627
673
|
return null;
|
|
628
674
|
}
|
|
629
675
|
|
|
@@ -655,9 +701,14 @@ function scoreFilesForTextContent(
|
|
|
655
701
|
filesCount: importedFiles.length
|
|
656
702
|
});
|
|
657
703
|
|
|
658
|
-
//
|
|
704
|
+
// Search component files and page files (where JSX text lives)
|
|
705
|
+
// Expanded to work with ANY codebase structure
|
|
659
706
|
const componentFiles = importedFiles.filter(f =>
|
|
660
|
-
f.path.includes('components/') ||
|
|
707
|
+
f.path.includes('components/') ||
|
|
708
|
+
f.path.includes('/ui/') ||
|
|
709
|
+
f.path.includes('/_components/') ||
|
|
710
|
+
f.path.endsWith('.tsx') ||
|
|
711
|
+
f.path.endsWith('.jsx')
|
|
661
712
|
);
|
|
662
713
|
|
|
663
714
|
const results: { path: string; content: string; score: number; matchedTexts: string[]; firstMatchLine: number }[] = [];
|
|
@@ -753,9 +804,25 @@ function findElementInImportedFiles(
|
|
|
753
804
|
const routeName = pageDir.split('/').pop() || ''; // e.g., "typography"
|
|
754
805
|
|
|
755
806
|
for (const file of importedFiles) {
|
|
756
|
-
// Focus on component files (where UI elements live)
|
|
807
|
+
// Focus on component/page files (where UI elements live)
|
|
757
808
|
// Skip types, stores, utils, hooks - they don't contain JSX elements
|
|
758
|
-
|
|
809
|
+
// Expanded to work with ANY codebase structure
|
|
810
|
+
const isComponentFile =
|
|
811
|
+
file.path.includes('components/') ||
|
|
812
|
+
file.path.includes('/ui/') ||
|
|
813
|
+
file.path.includes('/_components/') ||
|
|
814
|
+
file.path.endsWith('.tsx') ||
|
|
815
|
+
file.path.endsWith('.jsx');
|
|
816
|
+
|
|
817
|
+
// Skip non-component files but allow page files
|
|
818
|
+
if (!isComponentFile) continue;
|
|
819
|
+
|
|
820
|
+
// Skip known non-UI files
|
|
821
|
+
if (file.path.includes('/types') ||
|
|
822
|
+
file.path.includes('/hooks/') ||
|
|
823
|
+
file.path.includes('/utils/') ||
|
|
824
|
+
file.path.includes('/lib/') ||
|
|
825
|
+
file.path.includes('.d.ts')) continue;
|
|
759
826
|
|
|
760
827
|
const result = findElementLineInFile(file.content, focusedElement);
|
|
761
828
|
if (result && result.confidence !== 'low') {
|
|
@@ -2580,7 +2647,7 @@ ${linesWithNumbers}
|
|
|
2580
2647
|
path: actualTargetFile.path,
|
|
2581
2648
|
lines: targetContent.split('\n').length,
|
|
2582
2649
|
size: targetContent.length,
|
|
2583
|
-
wasRedirected: actualTargetFile.path !== recommendedFileContent
|
|
2650
|
+
wasRedirected: actualTargetFile.path !== recommendedFileContent?.path
|
|
2584
2651
|
});
|
|
2585
2652
|
} else if (pageContext.pageContent) {
|
|
2586
2653
|
// Fallback: use page file if no recommended file
|
|
@@ -620,6 +620,52 @@ function findElementLineInFile(
|
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
+
// ========== FALLBACK MATCHING (for non-Sonance codebases) ==========
|
|
624
|
+
// These are lower confidence but help find elements in ANY codebase
|
|
625
|
+
|
|
626
|
+
// FALLBACK 1: Flexible text search (just find the text anywhere)
|
|
627
|
+
if (focusedElement.textContent && focusedElement.textContent.trim().length > 5) {
|
|
628
|
+
const searchText = focusedElement.textContent.trim().substring(0, 30);
|
|
629
|
+
for (let i = 0; i < lines.length; i++) {
|
|
630
|
+
if (lines[i].includes(searchText)) {
|
|
631
|
+
debugLog("Fallback: Flexible text match found", { searchText, lineNumber: i + 1 });
|
|
632
|
+
return {
|
|
633
|
+
lineNumber: i + 1,
|
|
634
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
635
|
+
confidence: 'low',
|
|
636
|
+
matchedBy: `flexible text match "${searchText}${focusedElement.textContent.length > 30 ? '...' : ''}"`
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// FALLBACK 2: Class fingerprint (use first few classes as unique identifier)
|
|
643
|
+
if (focusedElement.className && focusedElement.className.trim().length > 15) {
|
|
644
|
+
// Take first 2-3 distinctive classes as a fingerprint
|
|
645
|
+
const classes = focusedElement.className.trim().split(/\s+/);
|
|
646
|
+
// Filter out very common single-word utilities
|
|
647
|
+
const distinctiveClasses = classes.filter(c =>
|
|
648
|
+
c.length > 4 && !['flex', 'grid', 'block', 'hidden', 'relative', 'absolute'].includes(c)
|
|
649
|
+
).slice(0, 3);
|
|
650
|
+
|
|
651
|
+
if (distinctiveClasses.length >= 2) {
|
|
652
|
+
const fingerprint = distinctiveClasses.join(' ');
|
|
653
|
+
for (let i = 0; i < lines.length; i++) {
|
|
654
|
+
// Check if line contains ALL fingerprint classes
|
|
655
|
+
const lineHasAll = distinctiveClasses.every(cls => lines[i].includes(cls));
|
|
656
|
+
if (lineHasAll) {
|
|
657
|
+
debugLog("Fallback: Class fingerprint match found", { fingerprint, lineNumber: i + 1 });
|
|
658
|
+
return {
|
|
659
|
+
lineNumber: i + 1,
|
|
660
|
+
snippet: lines.slice(Math.max(0, i - 3), i + 5).join('\n'),
|
|
661
|
+
confidence: 'low',
|
|
662
|
+
matchedBy: `class fingerprint "${fingerprint}"`
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
623
669
|
return null;
|
|
624
670
|
}
|
|
625
671
|
|
|
@@ -651,9 +697,14 @@ function scoreFilesForTextContent(
|
|
|
651
697
|
filesCount: importedFiles.length
|
|
652
698
|
});
|
|
653
699
|
|
|
654
|
-
//
|
|
700
|
+
// Search component files and page files (where JSX text lives)
|
|
701
|
+
// Expanded to work with ANY codebase structure
|
|
655
702
|
const componentFiles = importedFiles.filter(f =>
|
|
656
|
-
f.path.includes('components/') ||
|
|
703
|
+
f.path.includes('components/') ||
|
|
704
|
+
f.path.includes('/ui/') ||
|
|
705
|
+
f.path.includes('/_components/') ||
|
|
706
|
+
f.path.endsWith('.tsx') ||
|
|
707
|
+
f.path.endsWith('.jsx')
|
|
657
708
|
);
|
|
658
709
|
|
|
659
710
|
const results: { path: string; content: string; score: number; matchedTexts: string[]; firstMatchLine: number }[] = [];
|
|
@@ -749,9 +800,25 @@ function findElementInImportedFiles(
|
|
|
749
800
|
const routeName = pageDir.split('/').pop() || ''; // e.g., "typography"
|
|
750
801
|
|
|
751
802
|
for (const file of importedFiles) {
|
|
752
|
-
// Focus on component files (where UI elements live)
|
|
803
|
+
// Focus on component/page files (where UI elements live)
|
|
753
804
|
// Skip types, stores, utils, hooks - they don't contain JSX elements
|
|
754
|
-
|
|
805
|
+
// Expanded to work with ANY codebase structure
|
|
806
|
+
const isComponentFile =
|
|
807
|
+
file.path.includes('components/') ||
|
|
808
|
+
file.path.includes('/ui/') ||
|
|
809
|
+
file.path.includes('/_components/') ||
|
|
810
|
+
file.path.endsWith('.tsx') ||
|
|
811
|
+
file.path.endsWith('.jsx');
|
|
812
|
+
|
|
813
|
+
// Skip non-component files but allow page files
|
|
814
|
+
if (!isComponentFile) continue;
|
|
815
|
+
|
|
816
|
+
// Skip known non-UI files
|
|
817
|
+
if (file.path.includes('/types') ||
|
|
818
|
+
file.path.includes('/hooks/') ||
|
|
819
|
+
file.path.includes('/utils/') ||
|
|
820
|
+
file.path.includes('/lib/') ||
|
|
821
|
+
file.path.includes('.d.ts')) continue;
|
|
755
822
|
|
|
756
823
|
const result = findElementLineInFile(file.content, focusedElement);
|
|
757
824
|
if (result && result.confidence !== 'low') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.106",
|
|
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",
|