Skip to content

Evaluator

Evaluator.js handles variable substitution and colour function dispatch during theme compilation.

setTheme(theme) gives the Evaluator a back-reference to the owning Theme instance. This enables source-location lookups: when an evaluation error occurs, the Evaluator calls theme.findSourceLocation(dottedPath) and, if a location is found, appends file:line:col to the error’s trace context. The result is error messages that point directly to the offending line in the original YAML source.

Three static patterns drive token detection:

  • Evaluator.sub — matches variable references in three syntaxes: $(var), $var, ${var}
  • Evaluator.func — matches function calls: functionName(args)
  • Evaluator.paletteAlias — matches palette alias syntax: $$name, $($name), ${$name}. These are expanded to $palette.name, $(palette.name), ${palette.name} before resolution begins.

The main entry point. Takes an array of {flatPath, value} entries and resolves them in-place.

Before the resolution loop begins, a pre-pass expands all palette aliases ($$name$palette.name) via expandPaletteAliases(). This ensures palette references are in their canonical form before any resolution attempts.

Resolution is then iterative:

  1. Loop through all entries, calling #evaluateValue() on each string value.
  2. #evaluateValue() dispatches based on the value’s form:
    • Hex literal#resolveHex (pass through)
    • Variable reference ($(...)) → #resolveVariable (look up in pool)
    • Function call (func(...)) → #resolveFunction (dispatch to colour function)
    • Otherwise#resolveLiteral
  3. Repeat passes until no unresolved tokens remain or maxIterations (10) is reached.
  4. If max iterations are exhausted, a Sass error is thrown listing the unresolved tokens. This catches circular references.

All errors thrown during evaluation are enriched with source locations when available — the Evaluator uses its Theme reference to resolve the dotted path back to a file:line:col position in the original YAML.

#resolveFunction parses the function call and delegates to #colourFunction, which switches on the function name:

FunctionDescription
lightenLighten a colour by a percentage
darkenDarken a colour by a percentage
fadeReduce alpha (increase transparency)
solidifyIncrease alpha (reduce transparency)
alphaSet alpha to a specific value
invertInvert a colour
mixMix two colours with a ratio
cssOutput as CSS colour string

The default case passes the raw expression to Colour.toHex() as a Culori passthrough — any valid Culori colour expression works.

This switch statement is the extension point for adding new colour functions.

Each resolution creates or updates ThemeToken entries in the pool:

  • New tokens are created with raw value, resolved value, and kind.
  • Existing tokens have their value updated and resolution trail appended.
  • The pool’s lookup map enables chained dependency resolution — later tokens can reference earlier-resolved values.
  • Resolution trails are tracked for the resolve command’s debugging output.