Current section
Files
Jump to
Current section
Files
lib/jetons.ex
defmodule Jetons do
@moduledoc """
A simple, flexible library for managing design tokens in Elixir.
Jetons generates compile-time token accessor functions from parsed JSON maps,
with support for single or multiple themes (light/dark/custom).
## Generated Functions
Single theme modules generate:
- `token/1` - Get token by path (returns nil if not found)
- `token!/1` - Get token by path (raises if not found)
- `list_<category>/0` - List all tokens in a category
- `group_by_path/2` - Group tokens by path depth
- `get_groups/1` - Get top-level groups for a category
- `get_in_group/2` - Get all tokens in a specific group
Multi-theme modules additionally generate:
- `token/2` - Get token by path for specific theme
- `token!/2` - Get token by path for specific theme (raises if not found)
- `list_<category>/1` - List tokens in category for specific theme
- `list/0` - List all tokens (uses default theme)
- `list/1` - List all tokens for specific theme
- `themes/0` - List all available theme names
## What `use Jetons` Injects
When you `use Jetons`, it generates the following functions in your module:
**Single Theme Mode:**
- `token/1` - Retrieves token value by path (returns nil if not found)
- `token!/1` - Retrieves token value by path (raises KeyError if not found)
- `list_<category>/0` - One function per category (e.g., `list_colors/0`)
- `group_by_path/2` - Groups tokens by path depth
- `get_groups/1` - Returns sorted list of top-level groups
- `get_in_group/2` - Returns all tokens in a specific group
**Multi-Theme Mode (when 2+ themes provided):**
All of the above, plus:
- `token/2` - Retrieves token with explicit theme parameter
- `token!/2` - Retrieves token with theme (raises if not found)
- `list_<category>/1` - List category tokens for specific theme
- `themes/0` - Returns list of all available theme names
- All helper functions with `/3` variants accepting theme parameter
**Compile-Time Dependencies:**
Note that token files must exist at compile time. Changing token files
requires recompiling any modules that use them.
"""
@doc """
Generates token accessor functions at compile time.
## Single Theme (No Theme Switching)
For single-theme tokens, provide one theme key:
defmodule MyTokens do
use Jetons,
main: File.read!("tokens.json") |> Jason.decode!()
end
MyTokens.token("color.text.primary") # No theme parameter needed
MyTokens.list_color() # List all color tokens
## Multiple Themes (With Theme Switching)
For multi-theme support, provide multiple theme keys:
defmodule MyTokens do
use Jetons,
light: File.read!("tokens/light.json") |> Jason.decode!(),
dark: File.read!("tokens/dark.json") |> Jason.decode!(),
high_contrast: File.read!("tokens/high-contrast.json") |> Jason.decode!()
end
MyTokens.token("color.text.primary") # Uses default (first theme: :light)
MyTokens.token("color.text.primary", :dark) # Explicit dark theme
MyTokens.token("color.text.primary", :high_contrast) # High contrast theme
MyTokens.themes() # [:light, :dark, :high_contrast]
MyTokens.list_color(:dark) # List colors for dark theme
## Requirements
* All theme values must be parsed JSON maps (use `Jason.decode!/1`)
* Token files must follow the Design Tokens Community Group (DTCG) format
* For multi-theme setups, all themes should have the same token structure
"""
defmacro __using__(opts) do
Jetons.Macro.__using__(opts)
end
# Public API delegates to Jetons.Parser
defdelegate from_files(groups), to: Jetons.Parser
defdelegate from_files(groups, opts), to: Jetons.Parser
defdelegate from_config(config), to: Jetons.Parser
defdelegate from_config(config, opts), to: Jetons.Parser
defdelegate parse_tokens(input), to: Jetons.Parser
defdelegate extract_categories(tokens), to: Jetons.Parser
defdelegate extract_type_map(config), to: Jetons.Parser
defdelegate group_by_path(tokens, category, depth), to: Jetons.Parser
defdelegate get_groups(tokens, category), to: Jetons.Parser
defdelegate get_in_group(tokens, category, group), to: Jetons.Parser
defdelegate flatten_tokens(map, prefix), to: Jetons.Parser
defdelegate resolve_extends(config), to: Jetons.Parser
defdelegate deep_merge(left, right), to: Jetons.Parser
defdelegate resolve_token_refs(tokens), to: Jetons.Parser
end