Formatting & Serialization
See how normalized, internal coordinates are cleanly serialized back into spec-compliant CSS strings, hex codes, or custom formats.
The final step in a color engine's lifecycle is serialization—taking mathematically complex, floating-point data and transforming it into clean, spec-compliant CSS strings.
To achieve this without creating a massive, monolithic switch statement for every possible syntax, Saturon utilizes a modular, auto-generating Formatting Registry. This architecture strictly separates the internal coordinate logic from the string construction rules.
Here is a breakdown of how the formatting architecture operates under the hood.
The Public API
Saturon exposes serialization through two primary interfaces, ensuring developers have flexibility depending on their performance requirements.
Color.prototype.to(format)
The standard method attached to every Color instance. It accepts a target output format and optional formatting configurations (like precision rounding, legacy syntax, or gamut fitting).
const color = Color.from("oklch(70% 0.1 330)");
color.to("rgb");
// Returns: "rgb(204 122 235)"
color.to("hex-color");
// Returns: "#cc7aeb"format(colorData, toType)
The underlying utility that bypasses object instantiation overhead. It takes raw ColorData, processes it through the necessary conversion and formatting pipelines, and returns the final string.
1. The Formatter Registry
At the core of the serialization engine is the formatters dictionary. Instead of manually writing formatting logic for every color space, Saturon dynamically generates the bulk of this registry at initialization.
-
Auto-Generation: The engine iterates through the centralized
colorModelsregistry. It automatically constructs a highly optimizedColorFormatterobject for every standard CSS color model (e.g.,rgb,hsl,display-p3,oklch). -
Custom Overrides: After the standard models are generated, the engine manually appends specialized output formats that require unique serialization logic, such as
"hex-color","named-color", and"device-cmyk".
This design ensures that if a new color space is added to the engine's core configuration, a formatter for it is instantly and automatically available without writing additional string-building logic.
2. Integration with the Bridge Pattern
The formatting architecture inherently relies on the conversion engine's graph-based routing.
A specific formatter does not need to know how to translate coordinates from every possible origin model. It only needs to declare a bridge model.
For example, the "hex-color" formatter declares "rgb" as its bridge. If you request a hex string from an oklch color, the formatting pipeline intercepts this:
- It passes the
oklchdata to the conversion engine, requesting a route to the"rgb"bridge. - The conversion engine returns the normalized RGB coordinates.
- The formatter safely maps those RGB numbers into a base-16 string.
3. The Execution Pipeline
When format() is invoked, the data flows through a strict pipeline to ensure the output is physically accurate, mathematically precise, and syntactically correct.
- Routing & Conversion
The engine checks if the color is already in the target format. If not, it leverages the conversion graph to translate the color into the formatter's designated
bridgespace, and then pushes it through thefromBridgemethod to get the final local coordinates. - Gamut Mapping (
fit) Before any string concatenation happens, the coordinates are passed through the gamut mapping engine. Depending on thefitoption provided (defaulting to the engine's global config), the color is mathematically constrained to ensure the output represents a valid, displayable color in that specific space. - Component Normalization
The constrained coordinates are processed by
normalizeComponentValue. This step applies decimal precision rounding. It also checks the component definitions to determine if specific numbers require CSS units. If configured, it automatically appends%for percentage channels ordegfor hue channels. - Syntax Construction
Finally, the
formatmethod evaluates the target output type and constructs the string. It handles logic for modern CSS Level 4 syntax (space-separated, e.g.,hsl(250 50% 50% / 0.5)), thecolor()function syntax (e.g.,color(display-p3 1 0 0)), or falls back to legacy comma-separated syntax if explicitly requested and supported by the format.
Gamut Mapping
Understand how out-of-bounds wide-gamut coordinates are intelligently fitted to renderable targets using customizable mapping algorithms.
Extensibility & Dynamic Registry
Explore how Saturon's decoupled registry allows you to dynamically inject and unregister custom color spaces, syntaxes, formatters, and algorithms at runtime.