UNPKG

@mintlify/cli

Version:

The Mintlify CLI

112 lines (111 loc) 4.01 kB
import Color from 'color'; export const WCAG_STANDARDS = { AA_NORMAL: 4.5, AA_LARGE: 3, AAA_NORMAL: 7, AAA_LARGE: 4.5, }; export function checkColorContrast(foreground, background, minThreshold = WCAG_STANDARDS.AA_NORMAL) { try { const fg = Color(foreground); const bg = Color(background); const ratio = fg.contrast(bg); const level = fg.level(bg); const meetsAA = level === 'AA' || level === 'AAA'; const meetsAAA = level === 'AAA'; let recommendation; let message; if (minThreshold !== WCAG_STANDARDS.AA_NORMAL) { if (ratio >= minThreshold) { recommendation = 'pass'; message = `Contrast ratio: ${ratio.toFixed(2)}:1 (meets minimum threshold of ${minThreshold}:1)`; } else { recommendation = 'fail'; message = `Poor contrast ratio: ${ratio.toFixed(2)}:1 (fails minimum threshold, required: ${minThreshold}:1)`; } } else { if (meetsAAA) { recommendation = 'pass'; message = `Excellent contrast ratio: ${ratio.toFixed(2)}:1 (meets WCAG AAA)`; } else if (meetsAA) { recommendation = 'warning'; message = `Good contrast ratio: ${ratio.toFixed(2)}:1 (meets WCAG AA, consider AAA for better accessibility)`; } else { recommendation = 'fail'; message = `Poor contrast ratio: ${ratio.toFixed(2)}:1 (fails WCAG AA, minimum required: ${WCAG_STANDARDS.AA_NORMAL}:1)`; } } return { ratio, meetsAA, meetsAAA, recommendation, message, }; } catch (_a) { return null; } } export function checkDocsColors(colors, background, navigation) { var _a; const lightBackground = background.lightHex; const darkBackground = background.darkHex; const primaryContrast = colors.primary ? checkColorContrast(colors.primary, lightBackground) : null; const lightContrast = colors.light ? checkColorContrast(colors.light, darkBackground) : null; const darkContrast = colors.dark ? checkColorContrast(colors.dark, darkBackground, 3) : null; const darkOnLightContrast = colors.dark ? checkColorContrast(colors.dark, lightBackground, 3) : null; const anchorResults = []; if ((_a = navigation === null || navigation === void 0 ? void 0 : navigation.global) === null || _a === void 0 ? void 0 : _a.anchors) { for (const anchor of navigation.global.anchors) { if (anchor.color) { const lightContrast = anchor.color.light ? checkColorContrast(anchor.color.light, lightBackground) : null; const darkContrast = anchor.color.dark ? checkColorContrast(anchor.color.dark, darkBackground) : null; anchorResults.push({ name: anchor.anchor, lightContrast, darkContrast, }); } } } const results = [ primaryContrast, lightContrast, darkContrast, darkOnLightContrast, ...anchorResults.flatMap((anchor) => [anchor.lightContrast, anchor.darkContrast]), ].filter(Boolean); const hasFailure = results.some((result) => result.recommendation === 'fail'); const hasWarning = results.some((result) => result.recommendation === 'warning'); let overallScore; if (hasFailure) { overallScore = 'fail'; } else if (hasWarning) { overallScore = 'warning'; } else { overallScore = 'pass'; } return { primaryContrast, lightContrast, darkContrast, darkOnLightContrast, anchorResults, overallScore, }; }