@templatical/quality
v0.6.1
Published
Accessibility linter for Templatical email templates
Maintainers
Readme
@templatical/quality
Accessibility linter for Templatical email templates. Runs in the browser or on Node.
Deterministic accessibility checks against the JSON TemplateContent block tree — missing alt text, low-contrast text and buttons, vague link / CTA copy, heading-skip, undersized touch targets, and more. Same package validates inside the editor (live sidebar tab + canvas badges) and in headless / CI checks.
MIT-licensed, JSON-only, no Vue, no DOM. Optional peer of @templatical/editor.
Install
npm install @templatical/qualityUsage
Headless
import { lintAccessibility } from "@templatical/quality";
import type { TemplateContent } from "@templatical/types";
const content: TemplateContent = JSON.parse(stored);
const issues = lintAccessibility(content);
for (const issue of issues) {
console.log(`[${issue.severity}] ${issue.ruleId}: ${issue.message}`);
}lintAccessibility(content, options?) is synchronous and pure — no DOM, no network, no fetch.
Editor
@templatical/editor lazy-imports this package on demand. Pass accessibility to init() / initCloud():
import { init } from "@templatical/editor";
init({
container: "#editor",
locale: "en",
accessibility: {
rules: {
"img-missing-alt": "warning",
"text-all-caps": "off",
},
thresholds: { minFontSize: 16 },
},
});The sidebar tab and inline canvas badges appear automatically once this peer is resolved.
Custom rules
Compose your own walkers using the same primitives the package ships:
import { walkBlocks, getContrastRatio } from "@templatical/quality";
walkBlocks(content, (block, ctx) => {
if (block.type === "title" && block.color) {
const ratio = getContrastRatio(block.color, ctx.resolvedBackgroundColor);
if (ratio < 4.5) {
console.warn(`Heading ${block.id} contrast ${ratio.toFixed(2)}:1`);
}
}
});