@mintlify/cli
Version:
The Mintlify CLI
112 lines (111 loc) • 4.01 kB
JavaScript
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,
};
}