Repository navigation
Releases: dXnSix/dXn.Dtcg
Releases · dXnSix/dXn.Dtcg
Release list
v1.3.0
Build and CI
- test on macOS arm64 too
- run the whole test suite on every platform, wasm32 included
Documentation
- (expressions) document token expressions in the guide, reference and website
Features
- (expressions) evaluate JavaScript and TypeScript token expressions
- (expressions) support wasm32-unknown-unknown and test it in CI
- (expressions) import host and document JavaScript and TypeScript modules
- (values) convert and compose colors, serialize every value model
- (expressions) call Rust functions from expressions through native modules
Fixes
- (expressions) keep stack overflows uncatchable and module values frozen
- (values) clip HSL, HWB and contrast into sRGB and keep near-gray hues
- (expressions) keep stack overflows uncatchable in async code and closing iterators
- (expressions) unwrap wrapped stack overflows however deeply nested
- (expressions) keep the stack margin small and give session setup its own limit
- (expressions) give the engine's overflow check room on large-frame builds
Tests
- (expressions) cover modules, native calls and colors on wasm32, and the module document limit
- (expressions) show that a configured stack limit applies on every platform
v1.2.0
Build and CI
- (toolchain) require Rust 1.97
Documentation
- (website) add the documentation site and GitHub Pages workflow
Features
- (extensions) move library extensions to dxn.dtcg.* and drop the project envelope
- Migration: token documents: set
"$type": "dxn.dtcg.blur"on blur tokens - Migration: Rust API: use
ValueExtensions::all(), theblurfield andwith_blur; unwrap project files yourself, applyLocalReferencePolicy::check_resolverif needed and pass the resolver tofrom_json_with_options; dropInvalidEnvelopeandEnvelopematch arms
- Migration: token documents: set
v1.1.0
Features
- (repository) rename the crates to dxn_dtcg and dxn_dtcg_derive
- Migration: RayX: depend on
dxn_dtcg = { git = "https://github.com/dXnSix/dXn.Dtcg", tag = "v1.1.0" }instead ofdtcg_runtime, and replacedtcg_runtime::anddtcg_runtime_derive::paths withdxn_dtcg::anddxn_dtcg_derive::.
- Migration: RayX: depend on
v1.0.0
The runtime now conforms fully to the DTCG 2025.10 Format, Color and Resolver modules: all 250
fixtures of the official conformance corpus pass. See docs/12-conformance.md
for the conformance tiers and every implementation-defined choice.
Added
- Official conformance corpus. The DTCG 2025.10 test suite (
design-tokens/community-groupat
882ebd6) is vendored undercrates/dtcg_runtime/tests/fixtures/dtcg-test-suite/2025.10/and
run bytests/official_test_suite.rs(official corpus: 250 passed, 0 known gaps). It is
excluded from the published crate. - Options.
RuntimeOptions { limits, extensions },ValueExtensions(line_height_dimension,
rayx_blur,ValueExtensions::rayx()),DtcgRuntime::with_options,
DtcgRuntime::from_json_with_options,DtcgRuntime::from_envelope_with_options,
DtcgRuntime::options()andvalidate_value_with. - Limits.
RuntimeLimits::max_value_nodes(default 4,000,000) andRuntimeLimits::max_tokens
(default 100,000), the setterswith_max_documents,with_max_reference_depth,
with_max_alias_depth,with_max_value_nodes,with_max_tokens, andDtcgRuntime::limits().
Resolved values nest at most 128 levels (kind: "value depth"), flattened paths at most 128
segments (kind: "path depth"). - Metadata.
ResolvedToken::descriptionandResolvedToken::deprecated(newDeprecation
enum, inherited from groups),ResolvedGroup,ResolvedTokens::groupand
ResolvedTokens::groups. - Typed values. The
valuesmodule (Color,Dimension,Duration,FontFamily,
FontWeight,CubicBezier,StrokeStyle,Border,Transition,Shadow,Gradient,
Typography,Blur,LineHeight,TypedValue),ResolvedToken::typedand
TypedValue::from_resolved. Every model implementsFromDtcgValue. - Export.
ResolvedTokens::to_documentwrites a resolution as a DTCG 2025.10 token document. - Inputs.
selection_from_jsonandselection_refs;DtcgError::InvalidInput. - Errors.
DtcgError::UnresolvedReference { resource, path, target, message }and the
diagnostic codesUnresolvedReferenceandInvalidInput. - API helpers.
Resolution::{map, is_ready, is_missing, missing},
SourceOccurrence::resource(),DtcgRuntime::replace_envelopeand aDebugimpl for
DtcgRuntimethat never prints document bodies.DtcgErrorisCloneandPartialEq. - Incremental resolution.
AffectedResolution::removed()andAffectedResolution::order(). - Derives.
Option<T>leaf fields (Option,core::option::Option,
std::option::Option, with or withoutwith) project toNonewhen the token is missing. - Documentation. The README and every
docs/chapter are compiled and run as doctests.
Changed
- Strict values by default.
validate_valueand resolution accept only DTCG 2025.10 values:
typographylineHeightmust be a number (or alias anumbertoken) anddev.rayx.bluris an
unsupported type, unlessValueExtensionsenables them. - One merged token structure. All active sources fold into one structure before resolution:
groups merge member by member, group$type,$description,$deprecatedand$extends
merge per key, group$extensionsmerge recursively, and tokens are still replaced whole.
Type inheritance,$extends,$deprecatedinheritance and JSON Pointers are evaluated on it,
so an override inherits its group's$typefrom an earlier source and$extendsreaches other
sources and groups produced by$extends. A path that is a token in one source and a group in
another is an error. - Type determination follows Format §5.2.2: own
$type, then the type of the token a
whole-value reference targets, then the group's$type. An own$typethat differs from the
referenced token's type is areference type mismatch. - Reference positions. Curly-brace aliases are allowed only as the whole value, at composite
members, and as shadow, gradient anddashArrayelements, and there they must target the
member's type (Format §7, §9). Aliases inside color, dimension, duration,cubicBezieror
fontFamilyarrays are rejected. - Token document structure. A string root
$schemais accepted and ignored. Tokens with child
members,$rootor$extends, tokens with both$valueand$ref, non-token$root
members, empty names, and mistyped$description,$deprecatedor$extensionsare rejected. - Resolver documents. Unknown members (including root
$extensionsandx-*members), an
emptyresolutionOrderand modifiers with a single context are rejected (Resolver §4).
$defsand$schemaare allowed..tokeneditorenvelopes apply the same rules todata, and
source_references()now fails withInvalidDocumentfor any resolver it reaches that breaks
them, asresolvedoes.
modifier_contextsrejects a single context. resolutionOrdersteps. A$refstep's sibling overrides define the modifier for every
API (resolve,validate_complete,modifiers(),normalize_selection, inspection). Two
steps defining the same modifier, and inline modifiers withoutname, are errors everywhere.
A token document with amodifiersgroup has no axes.- Inputs. Modifier and context names match case-insensitively. An input is valid when any
reached resolver declares it (nested resolvers, and the supplied source forpreview_sourceand
inspect_source); each resolver applies its own inputs and defaults; a graph without modifiers
ignores inputs.normalize_selectionvalidates likeresolveacross the whole graph and lists
every reached modifier, root first, in declared spelling. - Selection errors of
resolve. An unknown context (wasDtcgError::Token), a missing input
and a modifier selected twice (wereDtcgError::InvalidDocument) are now
DtcgError::UnknownContext, asnormalize_selectionalready reported them.
UnknownModifier::knownlists names in declaration order. - Missing alias and
$extendstargets areDtcgError::UnresolvedReference(was
DtcgError::Projection);Projectionis used only by projection. max_alias_depthcounts reference hops (aliases, token pointers and document pointers)
independently of authored order; a limit of 0 still resolves literal tokens.max_documentsalso counts every discovery expansion step, including expansions that
contribute no source.- JSON Pointers follow RFC 6901: percent-encoding is decoded and array indexes are strict.
- Resource ids reject
#, control characters,< > " | ? *, segments ending in a dot or
space, and Windows device names. - Incremental resolution compares the flattened tokens before and after an edit; deleting an
aliased token, group edits and document-pointer edits are handled, and
ResolvedTokens::apply_affectedyields exactly the full resolution. - Fingerprints hash values with sorted object keys; equality ignores object member order.
source_references()walks reference objects that target resolvers through their override
members and lists each authored site once however many reference objects reach it. Its work
is linear in the documents' size: the first walk of every location is free, targets without
source sites (token documents) are not walked, and walking a resolver or set again under
different overrides counts towardmax_documentsin discovery's units (failing with
LimitExceeded { kind: "documents" }), so every documentvalidate_completeaccepts is listed
unless the repeated walks pass through dormant definitions.#[non_exhaustive]onDtcgError,ValueValidationError,DtcgDiagnosticCode,
RuntimeLimits,ResolvedToken,ModifierAxis,DocumentRequest,ResolvedGroup,
RuntimeOptions,ValueExtensionsandTypedValue.- Derives. Attributes are parsed strictly: unknown, duplicated or misplaced keys,
idon
DtcgTokens,nestedwithwith,pathwithrename, andrestwith any other key are
compile errors. Type parameters are bounded per field (FromDtcgValuefor leaves,DtcgTokens
for nested fields) instead of all getting aDtcgTokensbound.
Fixed
- Hostile documents can no longer overflow the stack or run for exponential time: document-pointer
chains, pointer and$extendsfan-out, long$extendschains and discovery fan-out are bounded. - Pointer cycle detection no longer reports false cycles across sources or for sibling overrides
that point at their own target. ResourceId::parseandset_rootno longer silently drop a fragment.$extendsand type determination are evaluated per merged structure, so cross-source extensions
and inherited types work.normalize_selection,modifiers()and input validation honor$refstep overrides.- Affected resolution no longer accepts a deletion that breaks an alias, and snapshots no longer go
stale after group edits or moves. - Generated derive code uses fully qualified paths (a local
Resultalias no longer breaks it),
and raw identifiers such asr#typeread the tokentype. f32projection fails for numbers outside thef32range instead of producing infinity.- The
InvalidResourceIdandInvalidPointermessages close their backticks; theModifierAxis
anddiagnosticsmodule docs are accurate.
Migration
RayX
- Enable the RayX value extensions.
rayx_theme/src/project.rsopens projects with
DtcgRuntime::from_envelope; use
DtcgRuntime::from_envelope_with_options(path, envelope, RuntimeOptions::default().with_extensions(ValueExtensions::rayx())).
Without it the shipped design system (rayx_components_core/assets/dtcg/rayx/*.tokens.json)
fails: 33 typography tokens alias dimensionlineHeighttokens (first error:
``tokentheme.styles.text.typography.h1: reference type mismatch: expected number, found dimens...