Tooling
Two lint plugins that turn the system's most important rules from advice into build failures. A rule enforced only by review is a rule enforced only sometimes.
The short version
NOT IMPLEMENTED. This component does not exist in any released version of opsinjs. There is no package to install, no module to import and no props interface to generate code against. Everything on this page is a specification of intended behaviour and may change without notice. Do not write code against it.
This component is not built yet
PlannedRoadmapWhat “planned” means
Two packages are specified:
eslint-plugin-opsinjscovers JSX and TypeScript. Catches a raw colour, a mixed axis, a banned word, and a component used against its documented contract.stylelint-plugin-opsinjscovers CSS. Catches a hardcoded colour, a token used outside its tier, and a status token applied to a category surface.
The reasoning is simple arithmetic. The never-mix-the-axes rule has one page of doctrine, one section on every component page, a paragraph in the agent skill and a mention in the contributing checklist. That is five places asking a human to remember. A lint rule asks nobody.
How it works
The rules divide by what they can see.
A lint rule can check a syntactic invariant. Is this a hex colour in a
className? Are status and category both being passed to a component whose
documentation says they must not both change the surface? Is this CSS custom
property from the status namespace being assigned to a category role? These are
decidable from the source and are exactly what a plugin should own.
A lint rule cannot check a semantic one. Whether this particular reading
deserves urgent is a clinical judgement, and no static analysis will ever
answer it. The plugins deliberately do not try; they enforce the shape of the
system, and the meaning stays with the people who own the thresholds.
The third layer is runtime: development-mode warnings for the mistakes that only become visible when data flows through them. See Error codes. Each layer catches what the one before it cannot, and the error codes and lint rule names are deliberately aligned so that one search finds both.
Do this
- Install both plugins and turn them on in CI. A rule that runs only locally is a rule that runs only for the people who remember.
- Start with the recommended config. It contains the rules that are almost never a false positive; add the stricter ones once the codebase is clean.
- Fix rather than disable. If you must disable, disable the specific rule on the specific line with a comment saying why. A bare file-level disable removes protection nobody will notice is gone.
- Report a false positive. A noisy rule gets disabled wholesale, and then the real violations get through too.
Not this
- Do not treat the plugins as sufficient. They enforce shape. Every component has been audited against WCAG 2.2 AA, but that audit was run by the authors, not an independent reviewer; see ADR 0025 for the record. The independent accessibility review, the clinical review and the content review are still the things that catch the failures that matter most.
- Do not add project rules to the
opsinjs/namespace. Use your own; the namespace is versioned. - Do not run the plugins on generated output.
.source/,lib/generated/andpublic/r/are excluded in this repository for exactly that reason.
Gotchas
- The plugins do not exist yet. Both pages are specifications. They carry proposed rule names so that the error codes, the documentation and the future implementation can be written against one vocabulary rather than three.
- A lint rule cannot follow a variable. A colour assembled at runtime, or a status read from a variable, is invisible to static analysis. That is what the runtime warnings are for.
- Tailwind arbitrary values are the escape hatch that defeats most rules.
bg-[--my-var]andbg-[#e11d48]look similar and only one is a violation; the rule has to parse the arbitrary value rather than the class name.
Related
- ESLint plugin has the proposed JavaScript and JSX rules.
- Stylelint plugin has the proposed CSS rules.
- Error codes covers the runtime layer, and how the codes align with the rule names.
- The two colour axes is the invariant all of this exists to protect.
Testing your integration
What to assert about a component you did not write. The stable contracts, the accessibility assertions worth copying, and the tests that break on any refactor.
ESLint plugin
The proposed rule set for JSX and TypeScript covers raw colours, mixed axes, banned words, and the component contracts a reviewer should not have to remember.