0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-11 11:25:42 +02:00

Improve dark diff contrast

Co-authored-by: Hermes Agent (GPT-5.5) <hermes-agent@nousresearch.com>
Signed-off-by: cyphercodes <cyphercodes@users.noreply.github.com>
This commit is contained in:
cyphercodes 2026-04-29 06:57:49 +03:00
parent 0ba862cb97
commit 40bcb68030
5 changed files with 78 additions and 7 deletions

View File

@ -1728,6 +1728,11 @@ tbody.commit-list {
margin-left: 0 !important;
}
.diff-file-header .tw-text-diff-added-fg,
.diff-file-header .tw-text-diff-removed-fg {
font-weight: var(--font-weight-semibold);
}
.diff-stats-bar {
display: inline-block;
background-color: var(--color-diff-removed-fg); /* the background is used as "text foreground color" */

View File

@ -8,11 +8,11 @@ gitea-theme-meta-info {
/* red/green colorblind-friendly colors */
:root {
--color-diff-added-fg: #58a6ff;
--color-diff-added-fg: #65adff;
--color-diff-added-linenum-bg: #243d5d;
--color-diff-added-row-bg: #132339;
--color-diff-added-word-bg: #214d87;
--color-diff-removed-fg: #f0883e;
--color-diff-removed-fg: #f2964f;
--color-diff-removed-linenum-bg: #5b361c;
--color-diff-removed-row-bg: #3c2419;
--color-diff-removed-word-bg: #824e1f;

View File

@ -8,7 +8,7 @@ gitea-theme-meta-info {
/* blue/yellow colorblind-friendly colors */
:root {
--color-diff-added-fg: #58a6ff;
--color-diff-added-fg: #65adff;
--color-diff-added-linenum-bg: #243d5d;
--color-diff-added-row-bg: #132339;
--color-diff-added-word-bg: #214d87;

View File

@ -146,14 +146,14 @@ gitea-theme-meta-info {
--color-grey-light: #898d96;
--color-gold: #b1983b;
--color-white: #ffffff;
--color-diff-added-fg: #87ab63;
--color-diff-added-fg: #93b373;
--color-diff-added-linenum-bg: #274227;
--color-diff-added-row-bg: #203224;
--color-diff-added-row-border: #314a37;
--color-diff-added-word-bg: #3c653c;
--color-diff-moved-row-bg: #818044;
--color-diff-moved-row-border: #bcca6f;
--color-diff-removed-fg: #cc4848;
--color-diff-removed-fg: #ff8585;
--color-diff-removed-linenum-bg: #482121;
--color-diff-removed-row-bg: #301e1e;
--color-diff-removed-row-border: #634343;
@ -253,8 +253,8 @@ gitea-theme-meta-info {
--color-syntax-keyword: #ff8854;
--color-syntax-bool: #25bbc9;
--color-syntax-control: #dd9e17;
--color-syntax-name: #c7a618;
--color-syntax-type: #eb8cb3;
--color-syntax-name: #fabd2f;
--color-syntax-type: #fabd2f;
--color-syntax-number: #63b2dd;
--color-syntax-operator: #ff8854;
--color-syntax-regexp: #b89de4;

View File

@ -0,0 +1,66 @@
import {readFile} from 'node:fs/promises';
import * as path from 'node:path';
type CssVariables = Record<string, string>;
async function loadThemeVariables(fileName: string, baseVariables: CssVariables = {}): Promise<CssVariables> {
const themePath = path.join(import.meta.dirname, '../../css/themes', fileName);
const css = await readFile(themePath, 'utf8');
const variables = {...baseVariables};
for (const match of css.matchAll(/(--[\w-]+):\s*(#[\dA-Fa-f]{6});/g)) {
variables[match[1]] = match[2];
}
return variables;
}
function relativeLuminance(hex: string): number {
const rgb = [
Number.parseInt(hex.slice(1, 3), 16),
Number.parseInt(hex.slice(3, 5), 16),
Number.parseInt(hex.slice(5, 7), 16),
].map((value) => {
const channel = value / 255;
return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
});
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
}
function contrastRatio(foreground: string, background: string): number {
const foregroundLuminance = relativeLuminance(foreground);
const backgroundLuminance = relativeLuminance(background);
return (Math.max(foregroundLuminance, backgroundLuminance) + 0.05) /
(Math.min(foregroundLuminance, backgroundLuminance) + 0.05);
}
function expectWcagAaaContrast(label: string, foreground: string, background: string): void {
expect(contrastRatio(foreground, background), label).toBeGreaterThanOrEqual(7);
}
test('dark diff stat colors have WCAG AAA contrast', async () => {
const darkVariables = await loadThemeVariables('theme-gitea-dark.css');
const colorblindVariables = await loadThemeVariables('theme-gitea-dark-protanopia-deuteranopia.css', darkVariables);
const tritanopiaVariables = await loadThemeVariables('theme-gitea-dark-tritanopia.css', darkVariables);
const themes: Array<[string, CssVariables, string]> = [
['dark added', darkVariables, '--color-diff-added-fg'],
['dark removed', darkVariables, '--color-diff-removed-fg'],
['dark protanopia/deuteranopia added', colorblindVariables, '--color-diff-added-fg'],
['dark protanopia/deuteranopia removed', colorblindVariables, '--color-diff-removed-fg'],
['dark tritanopia added', tritanopiaVariables, '--color-diff-added-fg'],
];
for (const [label, variables, colorVariable] of themes) {
expectWcagAaaContrast(label, variables[colorVariable], darkVariables['--color-body']);
}
});
test('dark syntax name colors have WCAG AAA contrast on diff rows', async () => {
const variables = await loadThemeVariables('theme-gitea-dark.css');
const backgrounds = ['--color-diff-added-row-bg', '--color-diff-removed-row-bg'] as const;
const foregrounds = ['--color-syntax-name', '--color-syntax-type'] as const;
for (const foreground of foregrounds) {
for (const background of backgrounds) {
expectWcagAaaContrast(`${foreground} on ${background}`, variables[foreground], variables[background]);
}
}
});