Fix: parse oklch in visual-contrast and neon-text (#592)

Bare parseRgb() dropped Tailwind v4 computed colors, so contrast sampling skipped and neon-text never fired.

AI-assisted (Cursor agent).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Abdul Wahab
2026-08-22 05:25:50 +05:00
co-authored by Cursor
parent 56f44523f7
commit 1b7da15b56
6 changed files with 49 additions and 11 deletions
+4 -4
View File
@@ -626,7 +626,7 @@ if (IS_BROWSER) {
if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter');
if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter');
const solidBg = parseRgb(currentStyle.backgroundColor);
const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor);
if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break;
current = current.parentElement;
}
@@ -688,7 +688,7 @@ if (IS_BROWSER) {
// starve the url()-backed texts this mode exists to sample.
if (options.imageOnly && !reasons.includes('image background')) continue;
const textColor = parseRgb(style.color);
const textColor = parseRgb(style.color) || parseAnyColor(style.color);
const fontSize = parseFloat(style.fontSize) || 16;
const fontWeight = parseInt(style.fontWeight) || 400;
const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700);
@@ -985,7 +985,7 @@ if (IS_BROWSER) {
return sample;
}
}
const bg = parseRgb(style.backgroundColor);
const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor);
if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' };
return { status: 'unresolved', reason: 'no readable background' };
}
@@ -1115,7 +1115,7 @@ if (IS_BROWSER) {
}
const style = getComputedStyle(el);
const textColor = parseRgb(style.color) || candidate.textColor;
const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor;
if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' };
const rect = getDirectTextRect(el) || el.getBoundingClientRect();
+5 -5
View File
@@ -3986,7 +3986,7 @@ function checkElementAIPaletteDOM(el) {
}
// Check for neon text (vivid cyan/purple color on dark background)
const textColor = parseRgb(style.color);
const textColor = parseRgb(style.color) || parseAnyColor(style.color);
if (textColor && hasChroma(textColor, 80)) {
const hue = getHue(textColor);
const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310);
@@ -7281,7 +7281,7 @@ if (IS_BROWSER) {
if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter');
if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter');
const solidBg = parseRgb(currentStyle.backgroundColor);
const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor);
if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break;
current = current.parentElement;
}
@@ -7343,7 +7343,7 @@ if (IS_BROWSER) {
// starve the url()-backed texts this mode exists to sample.
if (options.imageOnly && !reasons.includes('image background')) continue;
const textColor = parseRgb(style.color);
const textColor = parseRgb(style.color) || parseAnyColor(style.color);
const fontSize = parseFloat(style.fontSize) || 16;
const fontWeight = parseInt(style.fontWeight) || 400;
const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700);
@@ -7640,7 +7640,7 @@ if (IS_BROWSER) {
return sample;
}
}
const bg = parseRgb(style.backgroundColor);
const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor);
if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' };
return { status: 'unresolved', reason: 'no readable background' };
}
@@ -7770,7 +7770,7 @@ if (IS_BROWSER) {
}
const style = getComputedStyle(el);
const textColor = parseRgb(style.color) || candidate.textColor;
const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor;
if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' };
const rect = getDirectTextRect(el) || el.getBoundingClientRect();
+1 -1
View File
@@ -2752,7 +2752,7 @@ function checkElementAIPaletteDOM(el) {
}
// Check for neon text (vivid cyan/purple color on dark background)
const textColor = parseRgb(style.color);
const textColor = parseRgb(style.color) || parseAnyColor(style.color);
if (textColor && hasChroma(textColor, 80)) {
const hue = getHue(textColor);
const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310);