Between formats, with the losses named
Every alias resolved, every cycle caught by name, and each export saying what it could not carry.
Between formats, with the losses named
Paste DTCG, CSS custom properties or flat JSON. Every alias is resolved, every cycle is caught by name, and each export says what it could not carry.
Resolved
Convert to
What is checked on the way in
Cycles. A reference graph can contain a loop, and a resolver that follows references without checking gives you a stack overflow rather than the name of the token that points at itself. Every chain is reported by path.
Dangling references. A token pointing at something not in the file is named rather than silently resolving to nothing.
Type disagreements. A token declared dimension that points at a color is one of them being wrong.
Reserved names. __proto__, constructor and prototype are refused as token names on the way in and on the way out. In JavaScript they can alter the prototype of every object in the program, and a token file has no reason to contain one.
Type inference from CSS is a guess. A hex is a colour and 16px is a dimension, but free text is left untyped rather than guessed at — a wrong type is worse than none.
Flattening is lossy in a way you do not see
An alias flattened to its literal value looks identical. The loss appears later: somebody changes the primitive, and the tokens that used to follow it do not move. Nothing errors, and the drift is only visible by comparison.
Formats that can carry a reference keep it here. The ones that cannot say so at the point of export.
Round-tripping is not guaranteed
DTCG to CSS to DTCG loses the type information CSS cannot carry, and inference on the way back is a guess. Keep the DTCG file as the source and generate the rest from it.