@cellarnode/elabel-compliance
v0.5.1
Published
EU FIC 1169/2011 + WCAG 2.x + ISO/IEC 18004 QR validators for CellarNode e-label edit-time and render-time compliance gates (headless TypeScript, zero-dep).
Downloads
1,378
Maintainers
Readme
@cellarnode/elabel-compliance
EU FIC 1169/2011 + WCAG 2.x + ISO/IEC 18004 QR validators for CellarNode e-label edit-time and render-time compliance gates.
Headless TypeScript, zero runtime dependencies — consume from any frontend or backend.
npm install @cellarnode/elabel-complianceimport { checkContrastRatio, predictFicXHeight, checkQrScannability } from "@cellarnode/elabel-compliance";
// WCAG 2.2 AA contrast (default: normal text, 4.5:1)
const verdict = checkContrastRatio("#2d6e3c", "#f5fbf4");
// { ratio: 5.87, threshold: 4.5, passes: true, level: "AA", textSize: "normal" }
// EU FIC 1169/2011 Article 13.2 — mandatory particulars min x-height (1.2mm)
const xHeight = predictFicXHeight({ fontSizePx: 16 });
// { predictedMm: 2.20, minMm: 1.2, passes: true }
// ISO/IEC 18004 QR scannability heuristics
const qr = checkQrScannability({ plannedSizeMm: 15, qrVersion: 1 });
// { moduleSizeMm: 0.71, recommendedMinModuleMm: 0.5, quietZoneModules: 4, passes: true }import { checkVoluntaryDeclarations } from "@cellarnode/elabel-compliance";
// Producer-authored free text that renders on the public scan page. Rejects
// web addresses, e-mail addresses, prices, discounts and calls to action.
const verdict = checkVoluntaryDeclarations(["Contains sulphites", "Buy now at wine.example.com"]);
// {
// passes: false,
// rejected: [{
// index: 1,
// value: "Buy now at wine.example.com",
// findings: [
// { reason: "call_to_action", excerpt: "Buy now" },
// { reason: "bare_domain", excerpt: "wine.example.com" },
// ],
// }],
// }passes means no rule fired. It is not a statement that a declaration is
lawful, accurate, non-misleading or permitted on an electronic label — FIC
Article 7 is a judgement about meaning, which pattern matching cannot make.
Consumers must surface the verdict as "no marketing content detected" and keep
the producer's own responsibility explicit. Reason codes are stable wire values;
layer your own i18n message bag on top.
See AGENTS.md for full API + dev commands.
