@jjlmoya/utils-games-development 1.60.0 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +2 -1
- package/src/index.ts +1 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/spanish_leakage.test.ts +25 -3
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/gameUIAccessibilityTester/bibliography.astro +6 -0
- package/src/tool/gameUIAccessibilityTester/bibliography.ts +10 -0
- package/src/tool/gameUIAccessibilityTester/component.astro +210 -0
- package/src/tool/gameUIAccessibilityTester/controller-actions.ts +92 -0
- package/src/tool/gameUIAccessibilityTester/controller.ts +237 -0
- package/src/tool/gameUIAccessibilityTester/dom-views.ts +193 -0
- package/src/tool/gameUIAccessibilityTester/entry.ts +28 -0
- package/src/tool/gameUIAccessibilityTester/evaluator.ts +43 -0
- package/src/tool/gameUIAccessibilityTester/game-ui-accessibility-stress-tester.css +982 -0
- package/src/tool/gameUIAccessibilityTester/i18n/de.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/en.ts +199 -0
- package/src/tool/gameUIAccessibilityTester/i18n/es.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/fr.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/id.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/it.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/ja.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/ko.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/nl.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/pl.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/pt.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/ru.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/sv.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/tr.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/i18n/zh.ts +203 -0
- package/src/tool/gameUIAccessibilityTester/index.ts +11 -0
- package/src/tool/gameUIAccessibilityTester/logic.test.ts +57 -0
- package/src/tool/gameUIAccessibilityTester/logic.ts +157 -0
- package/src/tool/gameUIAccessibilityTester/report.ts +59 -0
- package/src/tool/gameUIAccessibilityTester/seo.astro +15 -0
- package/src/tool/gameUIAccessibilityTester/storage.ts +34 -0
- package/src/tool/gameUIAccessibilityTester/ui.ts +80 -0
- package/src/tools.ts +2 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
colorDistance,
|
|
4
|
+
contrastRatio,
|
|
5
|
+
fromHex,
|
|
6
|
+
relativeLuminance,
|
|
7
|
+
separationRetention,
|
|
8
|
+
simulateColor,
|
|
9
|
+
toHex,
|
|
10
|
+
} from './logic';
|
|
11
|
+
|
|
12
|
+
describe('game UI accessibility stress tester logic', () => {
|
|
13
|
+
it('matches WCAG reference luminance and contrast cases', () => {
|
|
14
|
+
expect(relativeLuminance({ r: 0, g: 0, b: 0 })).toBe(0);
|
|
15
|
+
expect(relativeLuminance({ r: 255, g: 255, b: 255 })).toBe(1);
|
|
16
|
+
expect(contrastRatio({ r: 0, g: 0, b: 0 }, { r: 255, g: 255, b: 255 })).toBe(21);
|
|
17
|
+
expect(contrastRatio({ r: 119, g: 119, b: 119 }, { r: 255, g: 255, b: 255 })).toBeCloseTo(4.478, 2);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('applies documented severity one CVD matrices in linear RGB', () => {
|
|
21
|
+
const red = { r: 255, g: 0, b: 0 };
|
|
22
|
+
expect(simulateColor(red, 'protanopia')).toEqual({ r: 109, g: 95, b: 0 });
|
|
23
|
+
expect(simulateColor(red, 'deuteranopia')).toEqual({ r: 163, g: 144, b: 0 });
|
|
24
|
+
expect(simulateColor(red, 'tritanopia')).toEqual({ r: 255, g: 0, b: 15 });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('preserves black and white through every CVD matrix', () => {
|
|
28
|
+
const modes = ['protanopia', 'deuteranopia', 'tritanopia'] as const;
|
|
29
|
+
modes.forEach((mode) => {
|
|
30
|
+
expect(simulateColor({ r: 0, g: 0, b: 0 }, mode)).toEqual({ r: 0, g: 0, b: 0 });
|
|
31
|
+
expect(simulateColor({ r: 255, g: 255, b: 255 }, mode)).toEqual({ r: 255, g: 255, b: 255 });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('supports grayscale, desaturation, reduced contrast and original modes', () => {
|
|
36
|
+
expect(simulateColor({ r: 255, g: 0, b: 0 }, 'achromatopsia')).toEqual({ r: 127, g: 127, b: 127 });
|
|
37
|
+
expect(simulateColor({ r: 255, g: 0, b: 0 }, 'desaturation')).toEqual({ r: 159, g: 95, b: 95 });
|
|
38
|
+
expect(simulateColor({ r: 255, g: 0, b: 0 }, 'reduced-contrast')).toEqual({ r: 198, g: 58, b: 58 });
|
|
39
|
+
expect(simulateColor({ r: 300, g: -10, b: Number.NaN }, 'original')).toEqual({ r: 255, g: 0, b: 0 });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('measures separation loss with stable limits', () => {
|
|
43
|
+
const black = { r: 0, g: 0, b: 0 };
|
|
44
|
+
const white = { r: 255, g: 255, b: 255 };
|
|
45
|
+
expect(colorDistance(black, black)).toBe(0);
|
|
46
|
+
expect(separationRetention(black, white, black, white)).toBe(100);
|
|
47
|
+
expect(separationRetention(black, white, black, black)).toBe(0);
|
|
48
|
+
expect(separationRetention(black, black, black, white)).toBe(0);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('formats clamped RGB colors as lowercase hexadecimal', () => {
|
|
52
|
+
expect(toHex({ r: 255, g: 16, b: 0 })).toBe('#ff1000');
|
|
53
|
+
expect(toHex({ r: -1, g: 300, b: Number.NaN })).toBe('#00ff00');
|
|
54
|
+
expect(fromHex('#1aB2c3')).toEqual({ r: 26, g: 178, b: 195 });
|
|
55
|
+
expect(fromHex('invalid')).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export type SimulationMode =
|
|
2
|
+
| 'original'
|
|
3
|
+
| 'protanopia'
|
|
4
|
+
| 'deuteranopia'
|
|
5
|
+
| 'tritanopia'
|
|
6
|
+
| 'achromatopsia'
|
|
7
|
+
| 'reduced-contrast'
|
|
8
|
+
| 'desaturation';
|
|
9
|
+
|
|
10
|
+
export interface RGBColor {
|
|
11
|
+
r: number;
|
|
12
|
+
g: number;
|
|
13
|
+
b: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Matrix3 = readonly [
|
|
17
|
+
number, number, number,
|
|
18
|
+
number, number, number,
|
|
19
|
+
number, number, number,
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const CVD_MATRICES: Partial<Record<SimulationMode, Matrix3>> = {
|
|
23
|
+
protanopia: [
|
|
24
|
+
0.152286, 1.052583, -0.204868,
|
|
25
|
+
0.114503, 0.786281, 0.099216,
|
|
26
|
+
-0.003882, -0.048116, 1.051998,
|
|
27
|
+
],
|
|
28
|
+
deuteranopia: [
|
|
29
|
+
0.367322, 0.860646, -0.227968,
|
|
30
|
+
0.280085, 0.672501, 0.047413,
|
|
31
|
+
-0.011820, 0.042940, 0.968881,
|
|
32
|
+
],
|
|
33
|
+
tritanopia: [
|
|
34
|
+
1.255528, -0.076749, -0.178779,
|
|
35
|
+
-0.078411, 0.930809, 0.147602,
|
|
36
|
+
0.004733, 0.691367, 0.303900,
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function clamp(value: number, minimum: number, maximum: number): number {
|
|
41
|
+
if (!Number.isFinite(value)) return minimum;
|
|
42
|
+
return Math.min(maximum, Math.max(minimum, value));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeChannel(value: number): number {
|
|
46
|
+
return clamp(value, 0, 255) / 255;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function linearize(value: number): number {
|
|
50
|
+
const channel = normalizeChannel(value);
|
|
51
|
+
return channel <= 0.04045
|
|
52
|
+
? channel / 12.92
|
|
53
|
+
: ((channel + 0.055) / 1.055) ** 2.4;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function encodeLinear(value: number): number {
|
|
57
|
+
const channel = clamp(value, 0, 1);
|
|
58
|
+
const encoded = channel <= 0.0031308
|
|
59
|
+
? 12.92 * channel
|
|
60
|
+
: 1.055 * channel ** (1 / 2.4) - 0.055;
|
|
61
|
+
return Math.round(encoded * 255);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function multiplyMatrix(color: RGBColor, matrix: Matrix3): RGBColor {
|
|
65
|
+
const [red, green, blue] = [linearize(color.r), linearize(color.g), linearize(color.b)];
|
|
66
|
+
return {
|
|
67
|
+
r: encodeLinear(matrix[0] * red + matrix[1] * green + matrix[2] * blue),
|
|
68
|
+
g: encodeLinear(matrix[3] * red + matrix[4] * green + matrix[5] * blue),
|
|
69
|
+
b: encodeLinear(matrix[6] * red + matrix[7] * green + matrix[8] * blue),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function grayscale(color: RGBColor): RGBColor {
|
|
74
|
+
const value = encodeLinear(relativeLuminance(color));
|
|
75
|
+
return { r: value, g: value, b: value };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function reduceContrast(color: RGBColor): RGBColor {
|
|
79
|
+
const midpoint = 128;
|
|
80
|
+
const factor = 0.55;
|
|
81
|
+
return {
|
|
82
|
+
r: Math.round(midpoint + (clamp(color.r, 0, 255) - midpoint) * factor),
|
|
83
|
+
g: Math.round(midpoint + (clamp(color.g, 0, 255) - midpoint) * factor),
|
|
84
|
+
b: Math.round(midpoint + (clamp(color.b, 0, 255) - midpoint) * factor),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function desaturate(color: RGBColor): RGBColor {
|
|
89
|
+
const gray = grayscale(color);
|
|
90
|
+
const saturation = 0.25;
|
|
91
|
+
return {
|
|
92
|
+
r: Math.round(gray.r + (clamp(color.r, 0, 255) - gray.r) * saturation),
|
|
93
|
+
g: Math.round(gray.g + (clamp(color.g, 0, 255) - gray.g) * saturation),
|
|
94
|
+
b: Math.round(gray.b + (clamp(color.b, 0, 255) - gray.b) * saturation),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function simulateColor(color: RGBColor, mode: SimulationMode): RGBColor {
|
|
99
|
+
const matrix = CVD_MATRICES[mode];
|
|
100
|
+
if (matrix) return multiplyMatrix(color, matrix);
|
|
101
|
+
if (mode === 'achromatopsia') return grayscale(color);
|
|
102
|
+
if (mode === 'reduced-contrast') return reduceContrast(color);
|
|
103
|
+
if (mode === 'desaturation') return desaturate(color);
|
|
104
|
+
return {
|
|
105
|
+
r: Math.round(clamp(color.r, 0, 255)),
|
|
106
|
+
g: Math.round(clamp(color.g, 0, 255)),
|
|
107
|
+
b: Math.round(clamp(color.b, 0, 255)),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function relativeLuminance(color: RGBColor): number {
|
|
112
|
+
return 0.2126 * linearize(color.r)
|
|
113
|
+
+ 0.7152 * linearize(color.g)
|
|
114
|
+
+ 0.0722 * linearize(color.b);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function contrastRatio(first: RGBColor, second: RGBColor): number {
|
|
118
|
+
const firstLuminance = relativeLuminance(first);
|
|
119
|
+
const secondLuminance = relativeLuminance(second);
|
|
120
|
+
const lighter = Math.max(firstLuminance, secondLuminance);
|
|
121
|
+
const darker = Math.min(firstLuminance, secondLuminance);
|
|
122
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function colorDistance(first: RGBColor, second: RGBColor): number {
|
|
126
|
+
const red = linearize(first.r) - linearize(second.r);
|
|
127
|
+
const green = linearize(first.g) - linearize(second.g);
|
|
128
|
+
const blue = linearize(first.b) - linearize(second.b);
|
|
129
|
+
return Math.sqrt(red ** 2 + green ** 2 + blue ** 2);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function separationRetention(
|
|
133
|
+
originalFirst: RGBColor,
|
|
134
|
+
originalSecond: RGBColor,
|
|
135
|
+
simulatedFirst: RGBColor,
|
|
136
|
+
simulatedSecond: RGBColor,
|
|
137
|
+
): number {
|
|
138
|
+
const original = colorDistance(originalFirst, originalSecond);
|
|
139
|
+
if (original === 0) return 0;
|
|
140
|
+
const simulated = colorDistance(simulatedFirst, simulatedSecond);
|
|
141
|
+
return clamp((simulated / original) * 100, 0, 100);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function toHex(color: RGBColor): string {
|
|
145
|
+
const channel = (value: number) => Math.round(clamp(value, 0, 255)).toString(16).padStart(2, '0');
|
|
146
|
+
return `#${channel(color.r)}${channel(color.g)}${channel(color.b)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function fromHex(value: string): RGBColor | null {
|
|
150
|
+
const match = value.trim().match(/^#([\da-f]{6})$/i)?.[1];
|
|
151
|
+
if (!match) return null;
|
|
152
|
+
return {
|
|
153
|
+
r: Number.parseInt(match.slice(0, 2), 16),
|
|
154
|
+
g: Number.parseInt(match.slice(2, 4), 16),
|
|
155
|
+
b: Number.parseInt(match.slice(4, 6), 16),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { PairDiagnostic } from './evaluator';
|
|
2
|
+
import { toHex, type RGBColor, type SimulationMode } from './logic';
|
|
3
|
+
import { triggerDownload } from './dom-views';
|
|
4
|
+
import type { GameUiAccessibilityTesterUI } from './ui';
|
|
5
|
+
|
|
6
|
+
export interface ReportInput {
|
|
7
|
+
mode: SimulationMode;
|
|
8
|
+
blur: number;
|
|
9
|
+
downscale: number;
|
|
10
|
+
firstName: string;
|
|
11
|
+
secondName: string;
|
|
12
|
+
first: RGBColor;
|
|
13
|
+
second: RGBColor;
|
|
14
|
+
diagnostic: PairDiagnostic;
|
|
15
|
+
findings: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function reportFindings(input: ReportInput, ui: GameUiAccessibilityTesterUI): string[] {
|
|
19
|
+
const findings = [...input.findings];
|
|
20
|
+
if (input.diagnostic.status === 'review') findings.unshift(ui.reportFindingReview);
|
|
21
|
+
return findings;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function createReport(input: ReportInput, ui: GameUiAccessibilityTesterUI): Record<string, unknown> {
|
|
25
|
+
return {
|
|
26
|
+
title: ui.reportTitle,
|
|
27
|
+
generatedAt: new Date().toISOString(),
|
|
28
|
+
scope: 'manual-review-aid',
|
|
29
|
+
processing: 'local-browser-only',
|
|
30
|
+
settings: {
|
|
31
|
+
simulation: input.mode,
|
|
32
|
+
blurPixels: input.blur,
|
|
33
|
+
downscale: input.downscale,
|
|
34
|
+
},
|
|
35
|
+
samples: [
|
|
36
|
+
{ name: input.firstName, color: toHex(input.first) },
|
|
37
|
+
{ name: input.secondName, color: toHex(input.second) },
|
|
38
|
+
],
|
|
39
|
+
measurements: {
|
|
40
|
+
originalContrastRatio: Number(input.diagnostic.originalContrast.toFixed(3)),
|
|
41
|
+
simulatedContrastRatio: Number(input.diagnostic.simulatedContrast.toFixed(3)),
|
|
42
|
+
},
|
|
43
|
+
heuristic: {
|
|
44
|
+
separationRetainedPercent: Number(input.diagnostic.retained.toFixed(1)),
|
|
45
|
+
reviewStatus: input.diagnostic.status,
|
|
46
|
+
},
|
|
47
|
+
findings: reportFindings(input, ui),
|
|
48
|
+
limitations: ui.limitationDisclosure,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function downloadStructuredReport(
|
|
53
|
+
input: ReportInput,
|
|
54
|
+
ui: GameUiAccessibilityTesterUI,
|
|
55
|
+
): void {
|
|
56
|
+
const report = createReport(input, ui);
|
|
57
|
+
const blob = new Blob([JSON.stringify(report, null, 2)], { type: 'application/json' });
|
|
58
|
+
triggerDownload(blob, 'game-ui-accessibility-review.json');
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { gameUiAccessibilityTester } from './entry';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props;
|
|
11
|
+
const loader = gameUiAccessibilityTester.i18n[locale] ?? gameUiAccessibilityTester.i18n.en;
|
|
12
|
+
const content = loader ? await loader() : null;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
{content && content.seo.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SimulationMode } from './logic';
|
|
2
|
+
|
|
3
|
+
export interface StoredSettings {
|
|
4
|
+
mode: SimulationMode;
|
|
5
|
+
compare: 'side' | 'split' | 'press';
|
|
6
|
+
blur: number;
|
|
7
|
+
downscale: number;
|
|
8
|
+
zoom: number;
|
|
9
|
+
heatmap: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STORAGE_KEY = 'game-ui-accessibility-stress-tester-settings';
|
|
13
|
+
|
|
14
|
+
export function loadSettings(fallback: StoredSettings): StoredSettings {
|
|
15
|
+
try {
|
|
16
|
+
const value = localStorage.getItem(STORAGE_KEY);
|
|
17
|
+
if (!value) return fallback;
|
|
18
|
+
return { ...fallback, ...JSON.parse(value) as Partial<StoredSettings> };
|
|
19
|
+
} catch {
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function saveSettings(settings: StoredSettings): void {
|
|
25
|
+
try {
|
|
26
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
|
|
27
|
+
} catch {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function clearSettings(): void {
|
|
31
|
+
try {
|
|
32
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export interface GameUiAccessibilityTesterUI extends Record<string, string> {
|
|
2
|
+
onboarding: string;
|
|
3
|
+
privacyNote: string;
|
|
4
|
+
dropTitle: string;
|
|
5
|
+
dropHint: string;
|
|
6
|
+
chooseImage: string;
|
|
7
|
+
replaceImage: string;
|
|
8
|
+
supportedFiles: string;
|
|
9
|
+
lensLabel: string;
|
|
10
|
+
lensOriginal: string;
|
|
11
|
+
lensProtanopia: string;
|
|
12
|
+
lensDeuteranopia: string;
|
|
13
|
+
lensTritanopia: string;
|
|
14
|
+
lensAchromatopsia: string;
|
|
15
|
+
lensReducedContrast: string;
|
|
16
|
+
lensDesaturation: string;
|
|
17
|
+
compareLabel: string;
|
|
18
|
+
compareSideBySide: string;
|
|
19
|
+
compareSplit: string;
|
|
20
|
+
comparePress: string;
|
|
21
|
+
holdOriginal: string;
|
|
22
|
+
splitPosition: string;
|
|
23
|
+
stressLabel: string;
|
|
24
|
+
blurLabel: string;
|
|
25
|
+
downscaleLabel: string;
|
|
26
|
+
downscaleFull: string;
|
|
27
|
+
downscaleHalf: string;
|
|
28
|
+
downscaleQuarter: string;
|
|
29
|
+
downscaleEighth: string;
|
|
30
|
+
zoomLabel: string;
|
|
31
|
+
heatmapLabel: string;
|
|
32
|
+
heatmapHint: string;
|
|
33
|
+
originalView: string;
|
|
34
|
+
simulatedView: string;
|
|
35
|
+
emptyCanvas: string;
|
|
36
|
+
sampleTitle: string;
|
|
37
|
+
sampleInstructions: string;
|
|
38
|
+
sampleA: string;
|
|
39
|
+
sampleB: string;
|
|
40
|
+
sampleAName: string;
|
|
41
|
+
sampleBName: string;
|
|
42
|
+
manualColor: string;
|
|
43
|
+
sampleAInitial: string;
|
|
44
|
+
sampleBInitial: string;
|
|
45
|
+
noSample: string;
|
|
46
|
+
originalContrast: string;
|
|
47
|
+
simulatedContrast: string;
|
|
48
|
+
separationRetained: string;
|
|
49
|
+
statusStrong: string;
|
|
50
|
+
statusWatch: string;
|
|
51
|
+
statusReview: string;
|
|
52
|
+
statusPending: string;
|
|
53
|
+
measurementLabel: string;
|
|
54
|
+
heuristicLabel: string;
|
|
55
|
+
manualReviewLabel: string;
|
|
56
|
+
measurementHint: string;
|
|
57
|
+
heuristicHint: string;
|
|
58
|
+
promptTitle: string;
|
|
59
|
+
promptColorOnly: string;
|
|
60
|
+
promptChangingBackground: string;
|
|
61
|
+
promptMinimap: string;
|
|
62
|
+
promptStates: string;
|
|
63
|
+
promptShape: string;
|
|
64
|
+
findingLabel: string;
|
|
65
|
+
findingPlaceholder: string;
|
|
66
|
+
addFinding: string;
|
|
67
|
+
findingsEmpty: string;
|
|
68
|
+
exportSheet: string;
|
|
69
|
+
exportReport: string;
|
|
70
|
+
resetTool: string;
|
|
71
|
+
uploadError: string;
|
|
72
|
+
fileTooLarge: string;
|
|
73
|
+
imageReady: string;
|
|
74
|
+
reportDownloaded: string;
|
|
75
|
+
sheetDownloaded: string;
|
|
76
|
+
localOnlyDisclosure: string;
|
|
77
|
+
limitationDisclosure: string;
|
|
78
|
+
reportTitle: string;
|
|
79
|
+
reportFindingReview: string;
|
|
80
|
+
}
|
package/src/tools.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { LOCALIZATION_SANITIZER_TOOL } from './tool/localizationSanitizer';
|
|
|
9
9
|
import { STEAM_BBCODE_TRANSLATOR_TOOL } from './tool/steamBbcodeTranslator';
|
|
10
10
|
import { RETRO_SFX_GENERATOR_TOOL } from './tool/retroSfxGenerator';
|
|
11
11
|
import { PIXEL_ART_PALETTE_SWAPPER_TOOL } from './tool/pixelArtPaletteSwapper';
|
|
12
|
+
import { GAME_UI_ACCESSIBILITY_TESTER_TOOL } from './tool/gameUIAccessibilityTester';
|
|
12
13
|
|
|
13
14
|
export const ALL_TOOLS: ToolDefinition[] = [
|
|
14
15
|
STEAM_CAPSULE_GENERATOR_TOOL,
|
|
@@ -20,4 +21,5 @@ export const ALL_TOOLS: ToolDefinition[] = [
|
|
|
20
21
|
STEAM_BBCODE_TRANSLATOR_TOOL,
|
|
21
22
|
RETRO_SFX_GENERATOR_TOOL,
|
|
22
23
|
PIXEL_ART_PALETTE_SWAPPER_TOOL,
|
|
24
|
+
GAME_UI_ACCESSIBILITY_TESTER_TOOL,
|
|
23
25
|
];
|