Skip to main content
╔════════════════════════════════════════════════════════════════════════════════════════════╗
║                                                                                            ║
║                    ██████╗  █████╗ ████████╗███████╗██╗  ██╗██╗████████╗                   ║
║                   ██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝██║ ██╔╝██║╚══██╔══╝                   ║
║                   ██║  ███╗███████║   ██║   █████╗  █████╔╝ ██║   ██║                      ║
║                   ██║   ██║██╔══██║   ██║   ██╔══╝  ██╔═██╗ ██║   ██║                      ║
║                   ╚██████╔╝██║  ██║   ██║   ███████╗██║  ██╗██║   ██║                      ║
║                    ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝╚═╝  ╚═╝╚═╝   ╚═╝                      ║
║                                                                                            ║
║                           three gates a linter will not give you                           ║
║                                                                                            ║
╚════════════════════════════════════════════════════════════════════════════════════════════╝

Three gates for defects a linter does not have an opinion about, because none of them is a syntax error. Each one exists because a real person read something and could not.

Gate Fails the build when
typefloor Type is declared below a readable floor (13px by default)
contrast-gate A declared colour cannot reach 4.5:1 on any surface the file also declares
deadname-gate A retired name reaches anything a human reads

Install

pip install legible

Use

typefloor ./src                  # every CSS and inline declaration
contrast-gate ./src              # WCAG 4.5:1 against declared surfaces
deadname-gate ./src              # a name that should be gone

Each exits non-zero on a finding and prints the file and line. --list shows every offender rather than the summary.

Why these three

typefloor. Six-point type is not a style choice. This was written after the same reader reported the same thing more than once, and the first time it was pointed at a folder it found every violation immediately — what was missing was never the tool, it was anything that pulled it.

contrast-gate. It reads CSS custom properties — --ink: #hex against --bg: #hex — and reports the best surface each ink can reach. Dark grey on navy measured 2.64:1 where body text needs 4.5, and a person found that, not a build.

It does not read literal color: declarations. A stylesheet using neither has nothing to compare, and it says so and exits 0 — which in CI reads as a pass on a site nobody checked. Pass --require-pairs to fail instead when nothing was found. The Action sets it.

deadname-gate. Fails a build when a name that should be gone reaches a title, a footer, a byline, alt text or a comment — while leaving machine identifiers alone, because renaming a repository path or a published artifact breaks working links or contradicts a deposited record. Both halves matter: a gate that cannot tell those apart gets switched off.

Written for a company rename. It is the same shape as the problem of a person changing their name and finding it in three hundred places, which is the harder version and the one worth getting right.

Exit codes

Code Means
0 Clean
1 It found something. The file and line are printed.
2 Misconfigured — it could not check, and will not report clean

The third one matters. deadname-gate forbids nothing out of the box, so a fresh install exits 2 with an explanation rather than 0. A gate that reports a pass while checking nothing is worse than no gate, and every one of these three shipped a version that did exactly that before it was caught.

Configuration

Each gate reads a JSON file of exceptions, so a deliberate choice is recorded with a reason rather than silently re-flagged.

typefloor ./src --config typefloor.json
contrast-gate ./src --config contrast.json
deadname-gate ./src --config deadname_gate.json

TYPEFLOOR_CONFIG, CONTRAST_CONFIG and DEADNAME_CONFIG do the same.

In CI

- run: pip install legible
- run: typefloor ./src
- run: contrast-gate ./src --require-pairs
- run: deadname-gate ./src

There are Actions too, in .github/actions/ of the source repository.

A note on the argument

An earlier version ignored a bare path and scanned its own directory instead, then printed OK. A gate that reports a pass on a tree it never opened is worse than no gate, so a positional path is now the root. If you pinned an earlier build, check what it is actually reading.

Licence

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

legible-0.1.0.tar.gz (16.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

legible-0.1.0-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file legible-0.1.0.tar.gz.

File metadata

  • Download URL: legible-0.1.0.tar.gz
  • Upload date:
  • Size: 16.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for legible-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3b29774f2edc547dbb54c9f67bcd4061b3deb45b69ec75f284333b4a3d05068b
MD5 19ffcdf284987c2e9884ecbb5d9d5cae
BLAKE2b-256 2f6afef8b1d692dd00c1632cbd1304fd9f922ccdcfe3874a041e5f3a374d164d

See more details on using hashes here.

File details

Details for the file legible-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: legible-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for legible-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 37beb99f788884d8fb5b24507f7acc93d68cbc31660f414d2106871f79c11b89
MD5 7bd130e3d5f9d469a9677049c031979e
BLAKE2b-256 43cbbb42811847d8704175c802cf0719c4e4b8cdc54dcad0fd6a17d533480a20

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page