Files
colour-tools/docs/ARCHITECTURE.md
T
zemion ed030cada6
Verify / verify (push) Canceled after 0s
Release Colour Tools 0.2.0
2026-09-02 07:11:11 +02:00

85 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Architecture
Colour Tools is a client-only React application built as relocatable static
files. The UI and calculation engine are intentionally separated so colour
operations can be tested without a browser and UI state can keep showing the
last valid result while an input is incomplete.
## Layers
1. `src/colour/` is the serialisable colour domain. It parses and formats
colours, converts gamuts, composites layers, interpolates stops, evaluates
contrast and Delta E, simulates colour-vision deficiencies, builds CSS
gradients, imports DTCG tokens, and builds or exports palettes. Its public
API is re-exported from `src/colour/index.ts`.
2. `src/palette/` contains browser-independent raster bounds, sampling and
deterministic OKLab clustering. `src/workers/palette.worker.ts` exposes the
expensive extraction path to a dedicated worker.
3. `src/components/` contains the seven workspaces and shared accessible
controls. Workspace selection is represented by a URL fragment, so a view
can be bookmarked without router or server support.
4. `src/hooks/` owns bounded device-local UI persistence. Image bytes are not
stored there.
5. `src/toolbox/` contains the checked manifest identity. The shared Toolbox
shell supplies navigation, contextual actions and theme behaviour without
changing the standalone application domain.
## Colour values
The engine's `ColourValue` is a plain object: colour-space identifier, three
numeric coordinates and alpha. It deliberately carries coordinates that may
sit outside a display gamut. Color.js 0.7.1 supplies standards-aligned parsing
and conversion primitives; Colour Tools wraps these in typed, bounded domain
operations and stable UI formats.
Browser preview is a separate operation. It maps a value to sRGB and reports
whether mapping occurred. This keeps display limitations from mutating the
source colour used by later conversions or comparisons.
`dtcg.ts` walks at most 32 group levels/10,000 tokens, validates DTCG 2025.10
structured colour components, resolves local curly aliases and local JSON
Pointer `$ref` token/property references with cycle detection, and resolves token type from
the token, its nearest group or its reference. It does not infer a missing
type. Numeric `none` semantics cannot be represented by `ColourValue`, so such
tokens produce an explicit diagnostic. Imported wide-gamut coordinates are
stored as CSS rather than being destructively mapped to the preview gamut.
`accessibility.ts` parses a maximum of 64 palette colours once before its
bounded 64×64 directional contrast loop. Each foreground/background cell
reports WCAG ratio thresholds after flattening transparency against a stated
canvas. `gradient.ts` validates 264 ascending stops and exports inert CSS plus
a schema-versioned recipe for linear, radial, conic and repeating syntax.
## Raster pipeline
The image picker validates the selected file before decode, rejects excessive
bytes/dimensions/pixels, then draws the decoded image to a same-origin in-memory
Canvas 2D surface. Sampling reads a bounded neighbourhood. Palette extraction
subsamples deterministically, converts points to OKLab and clusters them with a
fixed initialization and iteration bound. The worker client can fall back to
the same pure function when workers are unavailable.
Temporary object URLs are revoked and outstanding extraction is aborted when an
image is replaced or removed. No image or extracted palette is transmitted.
## Build and deployment
Vite builds with a relative base. `scripts/generate-toolbox-manifest.mjs`
checks package, application and Toolbox versions plus immutable source
identity. `scripts/prepare-release-files.mjs` places project documentation and
the exact installed runtime licence inventory beside the executable app.
The service worker is relative-scope and deployment-subpath aware. It is
progressive enhancement: the app remains usable when registration is rejected.
The deterministic packager rejects symbolic links, source maps, secret-like
filenames and root-absolute asset references before creating the release ZIP
and SHA-256 sidecar.
## Testing boundaries
Unit tests cover parsing, numerical operations, invalid inputs, raster bounds,
sampling and palette determinism. Browser smoke tests run the production build
under a restrictive policy at `/deep/nested/colour/`, exercise all major
workspaces and fail on uncaught errors or external network requests. The
Toolbox contract checker validates the static artifact independently.