sonance-brand-mcp 1.3.67 → 1.3.69
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.
|
@@ -480,18 +480,32 @@ export function analyzeContrastRelationships(
|
|
|
480
480
|
// Track which backgrounds we've analyzed to add white/black alternatives
|
|
481
481
|
const analyzedBackgrounds: { name: string; rgb: RGB }[] = [];
|
|
482
482
|
|
|
483
|
+
// DEBUG: Log start of analysis
|
|
484
|
+
const varCount = Object.keys(cssVariables).length;
|
|
485
|
+
console.log("[Contrast] Starting analysis with", varCount, "variables");
|
|
486
|
+
|
|
487
|
+
let skippedForeground = 0;
|
|
488
|
+
let skippedNonColor = 0;
|
|
489
|
+
let failedParse = 0;
|
|
490
|
+
let noForegroundVar = 0;
|
|
491
|
+
let pairsAnalyzed = 0;
|
|
492
|
+
|
|
483
493
|
// Find all bg/foreground pairs automatically
|
|
484
494
|
for (const [varName, value] of Object.entries(cssVariables)) {
|
|
485
495
|
// Skip if this is a foreground variable
|
|
486
|
-
if (varName.includes("foreground"))
|
|
496
|
+
if (varName.includes("foreground")) {
|
|
497
|
+
skippedForeground++;
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
487
500
|
|
|
488
501
|
// Skip non-color variables
|
|
489
502
|
if (
|
|
490
503
|
varName.includes("radius") ||
|
|
491
504
|
varName.includes("shadow") ||
|
|
492
505
|
varName.includes("ring") ||
|
|
493
|
-
varName.includes("border") && !varName.match(/border$/)
|
|
506
|
+
(varName.includes("border") && !varName.match(/border$/))
|
|
494
507
|
) {
|
|
508
|
+
skippedNonColor++;
|
|
495
509
|
continue;
|
|
496
510
|
}
|
|
497
511
|
|
|
@@ -500,19 +514,30 @@ export function analyzeContrastRelationships(
|
|
|
500
514
|
|
|
501
515
|
// Parse background color
|
|
502
516
|
const bgRgb = parseColorToRgb(value);
|
|
503
|
-
if (!bgRgb)
|
|
517
|
+
if (!bgRgb) {
|
|
518
|
+
// DEBUG: Log failed parses for important color variables
|
|
519
|
+
if (baseName.includes("primary") || baseName.includes("accent") || baseName.includes("success")) {
|
|
520
|
+
console.log("[Contrast] Failed to parse:", varName, "=", value);
|
|
521
|
+
}
|
|
522
|
+
failedParse++;
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
504
525
|
|
|
505
526
|
// Track this background for alternative suggestions
|
|
506
527
|
analyzedBackgrounds.push({ name: baseName, rgb: bgRgb });
|
|
507
528
|
|
|
508
529
|
// Check if there's a corresponding foreground variable
|
|
509
530
|
if (cssVariables[foregroundVar]) {
|
|
531
|
+
pairsAnalyzed++;
|
|
510
532
|
const fgRgb = parseColorToRgb(cssVariables[foregroundVar]);
|
|
511
533
|
|
|
512
534
|
if (fgRgb) {
|
|
513
535
|
const ratio = getContrastRatio(bgRgb, fgRgb);
|
|
514
536
|
const passes = ratio >= 4.5; // WCAG AA for normal text
|
|
515
537
|
|
|
538
|
+
// DEBUG: Log analyzed pairs
|
|
539
|
+
console.log("[Contrast] Pair:", baseName, "bg:", value, "fg:", cssVariables[foregroundVar], "ratio:", ratio.toFixed(1), passes ? "PASS" : "FAIL");
|
|
540
|
+
|
|
516
541
|
if (!passes) {
|
|
517
542
|
// Find the best alternative
|
|
518
543
|
const alternative = getBestAlternative(bgRgb);
|
|
@@ -531,9 +556,26 @@ export function analyzeContrastRelationships(
|
|
|
531
556
|
});
|
|
532
557
|
}
|
|
533
558
|
}
|
|
559
|
+
} else {
|
|
560
|
+
// DEBUG: Log important variables without foreground
|
|
561
|
+
if (baseName.includes("primary") || baseName.includes("accent") || baseName.includes("success")) {
|
|
562
|
+
console.log("[Contrast] No foreground var for:", baseName, "looked for:", foregroundVar);
|
|
563
|
+
}
|
|
564
|
+
noForegroundVar++;
|
|
534
565
|
}
|
|
535
566
|
}
|
|
536
567
|
|
|
568
|
+
// DEBUG: Summary
|
|
569
|
+
console.log("[Contrast] Summary:", {
|
|
570
|
+
total: varCount,
|
|
571
|
+
skippedForeground,
|
|
572
|
+
skippedNonColor,
|
|
573
|
+
failedParse,
|
|
574
|
+
noForegroundVar,
|
|
575
|
+
pairsAnalyzed,
|
|
576
|
+
analyzedBackgrounds: analyzedBackgrounds.length,
|
|
577
|
+
});
|
|
578
|
+
|
|
537
579
|
// Add white/black alternatives for all analyzed backgrounds
|
|
538
580
|
const whiteRgb: RGB = { r: 255, g: 255, b: 255 };
|
|
539
581
|
const blackRgb: RGB = { r: 0, g: 0, b: 0 };
|
|
@@ -627,6 +669,53 @@ export async function discoverTheme(projectRoot: string): Promise<DiscoveredThem
|
|
|
627
669
|
return result;
|
|
628
670
|
}
|
|
629
671
|
|
|
672
|
+
/**
|
|
673
|
+
* Get a human-readable description of a color based on its luminance and name
|
|
674
|
+
* This helps the LLM understand what colors look like visually
|
|
675
|
+
*/
|
|
676
|
+
function getColorDescription(value: string, name: string): string {
|
|
677
|
+
const rgb = parseColorToRgb(value);
|
|
678
|
+
if (!rgb) return "";
|
|
679
|
+
|
|
680
|
+
const luminance = getLuminance(rgb);
|
|
681
|
+
const baseName = name.replace(/^--/, "");
|
|
682
|
+
|
|
683
|
+
// Very light colors (like white)
|
|
684
|
+
if (luminance > 0.9) {
|
|
685
|
+
if (baseName.includes("foreground")) {
|
|
686
|
+
return " (WHITE text)";
|
|
687
|
+
}
|
|
688
|
+
return " ⚠️ WHITE - do NOT use for buttons";
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Very dark colors
|
|
692
|
+
if (luminance < 0.1) {
|
|
693
|
+
if (baseName.includes("background")) {
|
|
694
|
+
return " (DARK background)";
|
|
695
|
+
}
|
|
696
|
+
return " (BLACK/DARK)";
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Semantic color guidance
|
|
700
|
+
if (baseName.includes("accent")) {
|
|
701
|
+
return " ✓ ACCENT - good for buttons/CTAs";
|
|
702
|
+
}
|
|
703
|
+
if (baseName.includes("success")) {
|
|
704
|
+
return " ✓ GREEN - good for positive actions";
|
|
705
|
+
}
|
|
706
|
+
if (baseName.includes("destructive")) {
|
|
707
|
+
return " ✓ RED - good for danger/delete";
|
|
708
|
+
}
|
|
709
|
+
if (baseName.includes("warning")) {
|
|
710
|
+
return " (ORANGE/YELLOW - caution)";
|
|
711
|
+
}
|
|
712
|
+
if (baseName.includes("primary") && luminance > 0.7) {
|
|
713
|
+
return " ⚠️ LIGHT - avoid for buttons on light backgrounds";
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return "";
|
|
717
|
+
}
|
|
718
|
+
|
|
630
719
|
/**
|
|
631
720
|
* Format discovered theme as context for the LLM prompt
|
|
632
721
|
* Includes contrast warnings to prevent bad color combinations
|
|
@@ -637,9 +726,15 @@ export function formatThemeForPrompt(theme: DiscoveredTheme): string {
|
|
|
637
726
|
lines.push("**TARGET CODEBASE THEME (discovered):**");
|
|
638
727
|
lines.push("");
|
|
639
728
|
|
|
729
|
+
// Quick reference for button colors
|
|
730
|
+
lines.push("BUTTON COLOR QUICK REFERENCE:");
|
|
731
|
+
lines.push(" ✓ Use for buttons: bg-accent, bg-success, bg-destructive");
|
|
732
|
+
lines.push(" ✗ Avoid for buttons: bg-primary (may be WHITE), bg-secondary (may be transparent)");
|
|
733
|
+
lines.push("");
|
|
734
|
+
|
|
640
735
|
// CSS Variables
|
|
641
736
|
if (Object.keys(theme.cssVariables).length > 0) {
|
|
642
|
-
lines.push("
|
|
737
|
+
lines.push("COLOR TOKENS (with usage guidance):");
|
|
643
738
|
|
|
644
739
|
// Group by category
|
|
645
740
|
const categories: Record<string, string[]> = {
|
|
@@ -648,7 +743,10 @@ export function formatThemeForPrompt(theme: DiscoveredTheme): string {
|
|
|
648
743
|
};
|
|
649
744
|
|
|
650
745
|
for (const [name, value] of Object.entries(theme.cssVariables)) {
|
|
651
|
-
|
|
746
|
+
// Add color description for important tokens
|
|
747
|
+
const description = getColorDescription(value, name);
|
|
748
|
+
const entry = ` ${name}: ${value}${description}`;
|
|
749
|
+
|
|
652
750
|
if (
|
|
653
751
|
name.includes("background") ||
|
|
654
752
|
name.includes("foreground") ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.69",
|
|
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",
|