Skip to main content

Sassy — Feature Inventory

Authoring Formats

  • YAML Input — Write themes in clean, human-readable YAML

Variable System

  • Palette Layer — Define raw colour values in an isolated, self-contained palette scope
  • Vars Layer — Build semantic meaning on top of palette with a dedicated variable layer
  • Nested Variables — Define deeply nested variable hierarchies with dot-path addressing
  • Three Reference Syntaxes$(var), $var, ${var} — pick the style that fits the context
  • Palette Aliases$$name shorthand auto-expands to $(palette.name) for concise palette references
  • Cross-Layer References — Variables can reference other variables, palette entries, and theme values
  • Recursive Resolution — Multi-pass evaluation engine resolves chained variable references automatically
  • Circular Dependency Detection — Catches self-referential or looping variable chains before they hang

Colour Functions

  • lighten / darken — Perceptually uniform brightness adjustments via OKLCH
  • mix — Blend two colours at any ratio with OKLCH interpolation
  • alpha — Set exact transparency on any colour
  • fade / solidify — Relative opacity adjustments — reduce or increase alpha proportionally
  • invert — Flip lightness while preserving hue and saturation
  • saturate / desaturate — Adjust chroma intensity in OKLCH space
  • mute / pop — Semantic aliases for desaturation and saturation
  • tint / shade — Mix toward white or black by a given percentage
  • shiftHue — Rotate hue by arbitrary degrees
  • complement — 180° hue shift in one call
  • grayscale — Strip all chroma for a perceptually accurate greyscale
  • contrast — Returns black or white, whichever has better contrast against the input
  • css() — Use any CSS named colour (css(tomato), css(deepskyblue), etc.)
  • Composable Functions — Nest function calls inside each other: fade(lighten($(bg), 20), 0.5)

Colour Space Support

  • Hex#rgb, #rrggbb, #rrggbbaa — with short-form auto-expansion
  • RGB / RGBArgb(r, g, b) and rgba(r, g, b, a) constructors
  • HSL / HSLAhsl(h, s, l) and hsla(h, s, l, a) constructors
  • HSV / HSVAhsv(h, s, v) and hsva(h, s, v, a) constructors
  • OKLCH / OKLCHA — Perceptually uniform colour space for professional palette design
  • Any Culori Format — LAB, LCH, HWB, Display P3, Rec. 2020 — if Culori parses it, Sassy compiles it
  • Cross-Space Mixing — Freely combine colours from different spaces in the same theme
  • Alpha Preservation — Hex alpha channels are tracked and preserved through transformations

Import & Composition

  • File Imports — Pull in external YAML files via config.import
  • Deep Object Merging — Palette, vars, colors, semanticTokenColors merge by deep key override
  • Append-Only tokenColors — Imported tokenColors prepend, your file's rules append — correct precedence by default
  • Multi-File Import Chains — Import as many files as needed, merged in declaration order
  • Modular Theme Architecture — Split palettes, variables, UI colours, syntax rules, and semantics into separate files
  • Shared Palettes — One palette file, many theme variants
  • Dynamic Import Paths — Use variables in import paths: ./import/palette-$(type).yaml

Séance Operator

  • Prior Value References^ references the same key's value from a previously imported file
  • Derived Variants — Create "hushed", "vivid", or any theme variant by transforming inherited values: shade(^, 25)
  • Multi-Layer Séance — Chain through multiple import layers with automatic versioned tracking

Theme Sections

  • colors — Full support for VS Code workbench colour properties
  • tokenColors — TextMate-style syntax highlighting rules with scope selectors
  • semanticTokenColors — Semantic token colour definitions for language-aware highlighting
  • config.custom — Pass-through block for arbitrary VS Code properties like semanticHighlighting: true
  • config.$schema — Embed the VS Code colour theme schema reference in output

CLI — Build Command

  • Single or Multi-File Builds — Compile one or many theme files in a single invocation
  • Watch Mode — Live recompilation on file save with automatic dependency tracking
  • Dependency-Aware Watching — Edits to any imported file trigger a rebuild of the parent theme
  • Custom Output Directory — Route compiled output wherever you want with --output-dir
  • Dry Run — Print compiled JSON to stdout without writing any files
  • Silent Mode — Suppress all output except errors — ideal for scripts and CI
  • Nerd Mode — Verbose error traces with full stack context for debugging
  • Interactive Watch ControlsF5 to force rebuild, Ctrl-C to quit — with a live prompt
  • Hash-Based Skip — SHA-256 output comparison prevents unnecessary file writes
  • Graceful Signal Handling — Clean shutdown on SIGINT, SIGTERM, SIGHUP

CLI — Resolve Command

  • Color Resolution — Trace any colors.* property through its full variable chain
  • tokenColor Resolution — Resolve any TextMate scope to its final foreground value
  • semanticTokenColor Resolution — Resolve any semantic token scope to its final value
  • Full Resolution Trail — See every substitution step from raw expression to final hex
  • Scope Disambiguation — When a scope appears in multiple rules, lists all matches with selectable qualifiers
  • Precedence-Aware Resolution — Shows when a broader scope masks your specific one
  • Colour Swatches — Truecolour terminal swatches next to resolved hex values
  • Alpha Compositing Preview--bg flag composites transparent colours against a background for preview

CLI — Proof Command

  • Composed Document View — See the fully merged theme document after all imports, overrides, and séance are applied — before any evaluation
  • Séance Inlining^ operators replaced with the actual prior values so the output reads naturally: shade(#4b8ebd, 25)
  • YAML Output — Outputs in the authoring language, not the compiled format — stays in your world
  • Import-Free Output — Imports are resolved and merged; the import key is gone — what you see is what the engine sees
  • Aerial Debugging — Orient yourself in a layered theme before reaching for resolve — the map before the dig

CLI — Lint Command

  • Duplicate Scope Detection — Finds TextMate scopes that appear in multiple tokenColors rules
  • Undefined Variable Detection — Catches references to variables that don't exist
  • Unused Variable Detection — Identifies vars defined but never referenced in theme content
  • Scope Precedence Analysis — Warns when a broad scope masks a more specific one due to rule ordering
  • Token Colour Settings Validation — Validates settings objects: hex colours, fontStyle keywords, unknown properties
  • Missing/Empty Settings Detection — Catches tokenColors entries with no settings or empty settings objects
  • Deprecated Background Detection — Flags the deprecated background property in tokenColors settings
  • Multiple Global Default Detection — Warns when multiple scopeless tokenColors entries exist (only the last takes effect)
  • Unknown Settings Property Detection — Flags unrecognised properties in tokenColors settings objects
  • Semantic Selector Validation — Validates semanticTokenColors selectors against VS Code's parser rules
  • Semantic Token Type Registry — Checks token types and modifiers against VS Code's 23 standard types and 10 standard modifiers
  • Semantic Value Validation — Validates hex colours, fontStyle keywords, and catches the fontStyle-vs-boolean override trap
  • Semantic Coherence Checks — Warns when semanticTokenColors rules exist but semanticHighlighting is not enabled
  • Duplicate Selector Detection — Finds semanticTokenColors selectors that are identical after modifier normalisation
  • Shadowed Rule Detection — Identifies semantic rules overshadowed by higher-specificity rules with the same properties
  • Deprecated Usage Warnings — Flags the deprecated member token type and non-functional background property
  • Cross-Section Linting — Validates variables in colors, tokenColors, and semanticTokenColors
  • Strict Mode--strict treats warnings as errors for CI enforcement
  • Severity Levels — Issues categorised as high/medium/low with colour-coded terminal output
  • Source Location Reporting — Every lint issue includes file, line, and column — even across imported files
  • Unnamed Rule Labels — Unnamed tokenColors entries display as (unnamed rule #N) for easy identification
  • Import-Aware Analysis — Lints across all imported files, not just the main theme
  • Modular Rule Architecture — Lint rules organised in dedicated modules for maintainability

Output

  • VS Code .color-theme.json — Standard output format, ready for use in VS Code extensions
  • Deterministic Output — Same input always produces the same output
  • Pretty-Printed JSON — 2-space indented, human-readable output
  • Automatic File Namingmy-theme.yamlmy-theme.color-theme.json

Architecture & Performance

  • Compose-Then-Evaluate Pipeline — Shared composition step (import → merge → séance) feeds both compile and proof — one source of truth, two consumers
  • Phase-Based Compilation — Compose → decompose → evaluate → resolve → assemble — clean, predictable pipeline
  • File Caching — Imported files are cached and reused across themes in the same session
  • Colour Caching — Parsed colours and mix results are memoised for repeat calls
  • OKLCH-Native Operations — Lighten, darken, mix, and saturate all work in perceptually uniform space
  • Structured Error Reporting — Chained error contexts with .trace() for precise failure diagnostics
  • Max-Iteration Guards — Bounded resolution passes prevent runaway compilation

Programmatic API

  • ES Module Exportsimport {Theme, Lint, Resolve, Proof, Colour} from '@gesslar/sassy'
  • Builder Patternnew Theme().setCwd(cwd).setThemeFile(file).withOptions(opts) — no CLI dependencies required
  • Engine ClassesLint, Resolve, and Proof work standalone — give them a Theme, get structured data back
  • Cache-Optional Loadingload() falls back to FileObject.loadData() when no cache is set
  • Embeddable Compilation — Build themes programmatically without the CLI
  • Lint Enginenew Lint().run(theme) — returns categorised issues with severity levels
  • Resolve Enginenew Resolve().color(theme, key) — trace any token through its resolution chain
  • Proof Enginenew Proof().run(theme) — composed document view before evaluation
  • YamlSource ExportYamlSource class available for source location tracking in custom tooling
  • Source Location LookupTheme.findSourceLocation(path) maps compiled output paths back to source file positions
  • Lint Issue Locations — Lint issue objects include a location property with file, line, and column
  • Full Class Access — Theme, Colour, and all engine classes are importable

Developer Experience

  • Zero-Install Usagenpx @gesslar/sassy build — no global install required
  • TypeScript Definitions — Auto-generated .d.ts files from JSDoc for editor support
  • Docusaurus Documentation Site — Full docs at sassy.gesslar.io
  • Example Themes — Simple and advanced examples included in the repository
  • Unlicense — Use however you want — no restrictions