Harden CMS security and theme contrast
This commit is contained in:
1 parent
2465ff2170
commit
4a1e1115b3
57 files changed
+1023
-231
No files matched your search
@@ -0,0 +1,47 @@
|
||||
type Rgb = readonly [number, number, number];
|
||||
|
||||
export function contrastRatio(foreground: string, background: string): number | null {
|
||||
const fg = parseHex(foreground);
|
||||
const bg = parseHex(background);
|
||||
if (!fg || !bg) return null;
|
||||
|
||||
const light = Math.max(relativeLuminance(fg), relativeLuminance(bg));
|
||||
const dark = Math.min(relativeLuminance(fg), relativeLuminance(bg));
|
||||
return (light + 0.05) / (dark + 0.05);
|
||||
}
|
||||
|
||||
export function readableColor(
|
||||
preferred: string,
|
||||
backgrounds: readonly string[],
|
||||
minimumRatio = 4.5,
|
||||
): string {
|
||||
const preferredRatios = backgrounds.map((background) => contrastRatio(preferred, background));
|
||||
if (preferredRatios.some((ratio) => ratio === null)) return preferred;
|
||||
if (preferredRatios.every((ratio) => (ratio as number) >= minimumRatio)) return preferred;
|
||||
|
||||
const candidates = ["#000000", "#ffffff"] as const;
|
||||
return candidates
|
||||
.map((color) => ({
|
||||
color,
|
||||
minimum: Math.min(...backgrounds.map((background) => contrastRatio(color, background) ?? 0)),
|
||||
}))
|
||||
.sort((a, b) => b.minimum - a.minimum)[0].color;
|
||||
}
|
||||
|
||||
function parseHex(value: string): Rgb | null {
|
||||
const match = /^#([0-9a-f]{6})$/i.exec(value.trim());
|
||||
if (!match) return null;
|
||||
return [
|
||||
Number.parseInt(match[1].slice(0, 2), 16),
|
||||
Number.parseInt(match[1].slice(2, 4), 16),
|
||||
Number.parseInt(match[1].slice(4, 6), 16),
|
||||
];
|
||||
}
|
||||
|
||||
function relativeLuminance(rgb: Rgb): number {
|
||||
const [red, green, blue] = rgb.map((channel) => {
|
||||
const value = channel / 255;
|
||||
return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
||||
});
|
||||
return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||
}
|
||||
Reference in new issue
Block a user