@gamut-all/audit
v0.1.1
Published
CI audit tooling for gamut-all design tokens
Readme
@gamut-all/audit
CI tooling for @gamut-all/core design tokens. Audits every token variant for compliance, scans the DOM for misconfigured theme and stack attributes, and produces coverage reports showing which steps pass at each font size.
Installation
npm install @gamut-all/audit @gamut-all/coreFor auditURL (Playwright-based DOM auditing), also install Playwright as a peer:
npm install playwrightCLI
gamut-audit --registry ./dist/tokens.js [options]| Flag | Default | Description |
|------|---------|-------------|
| --registry | (required) | Path to a JS/TS file that exports TokenRegistry |
| --html | — | HTML file or URL to scan with auditDOM |
| --engine | wcag21 | wcag21 or apca |
| --level | AA | AA or AAA |
| --format | text | text or json |
| --report | audit | audit or coverage |
| --font-size | 16 | Font size (px) used for coverage report |
Exit code is 0 when there are no errors, 1 when errors are found.
Programmatic API
auditRegistry(registry, engine, level?)
Checks every variant in the registry against the compliance engine. Fails on non-compliant resolved steps (surface utility tokens included).
import { auditRegistry, formatText } from '@gamut-all/audit';
import { wcag21 } from '@gamut-all/core';
const result = auditRegistry(registry, wcag21, 'AA');
console.log(formatText(result));
if (result.failCount > 0) process.exit(1);auditDOM(root, registry, options?)
Scans a live DOM tree for attribute errors:
unknown-theme—data-themevalue not present in the registrymissing-data-theme— element with token CSS vars but nodata-themeancestorunknown-surface—data-bgvalue not inregistry.surfacesmissing-data-stack(warning) — contextual element with nodata-stackunknown-token-var— CSSvar(--fg-*)reference to an unknown token
import { auditDOM, formatText } from '@gamut-all/audit';
const result = auditDOM(document.body, registry);
console.log(formatText(result));auditURL(url, registry, options?)
Launches a Playwright browser, navigates to url, and runs auditDOM against the rendered page. Requires playwright as a peer dependency.
import { auditURL, formatJSON } from '@gamut-all/audit';
const result = await auditURL('https://localhost:3000', registry, {
width: 1280,
height: 720,
browser: 'chromium', // 'chromium' | 'firefox' | 'webkit'
});
console.log(formatJSON(result));auditCoverage(registry, engine, level?, opts?)
For each token and each background, reports the full range of steps that pass compliance and where the configured step falls within that range. Useful for designers checking step choices.
import { auditCoverage, formatCoverageText } from '@gamut-all/audit';
import { wcag21 } from '@gamut-all/core';
const report = auditCoverage(registry, wcag21, 'AA', { fontSizePx: 16 });
console.log(formatCoverageText(report));Result types
AuditResult
interface AuditResult {
issues: AuditIssue[];
variantsChecked: number;
elementsChecked: number;
passCount: number;
failCount: number;
}
interface AuditIssue {
type: IssueType;
severity: 'error' | 'warning';
token?: string;
element?: string; // CSS selector path (DOM audits)
message: string;
context?: Record<string, unknown>;
}
type IssueType =
| 'non-compliant-variant'
| 'non-compliant-surface-token'
| 'unknown-theme'
| 'missing-data-theme'
| 'unknown-surface'
| 'missing-data-stack'
| 'unknown-token-var';CoverageReport
interface CoverageReport {
tokens: TokenCoverage[];
meta: {
engine: string;
level: 'AA' | 'AAA';
fontSize: string;
generatedAt: string;
};
}Formatters
import {
formatText, // Human-readable audit result
formatJSON, // Machine-readable audit result
formatCoverageText, // Tabular coverage report
formatCoverageJSON, // JSON coverage export
} from '@gamut-all/audit';CI example
# .github/workflows/tokens.yml
- name: Audit tokens
run: |
node -e "
import('@gamut-all/audit').then(async ({ auditRegistry, formatText }) => {
const { registry } = await import('./dist/tokens.js');
const { wcag21 } = await import('@gamut-all/core');
const result = auditRegistry(registry, wcag21, 'AA');
console.log(formatText(result));
process.exit(result.failCount > 0 ? 1 : 0);
});
"