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_/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_/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 ## Extending Jetons Jetons supports custom transformers for generating output in any format. See the "Extending Jetons" guide for creating iOS, Android, or custom transformers. ## 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_/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_/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) # 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.DTCG, as: :type_map defdelegate extract_descriptions(config), to: Jetons.DTCG, as: :descriptions defdelegate extract_deprecated(config), to: Jetons.DTCG, as: :deprecated defdelegate group_by_path(tokens, category, depth), to: Jetons.Query defdelegate get_groups(tokens, category), to: Jetons.Query defdelegate get_in_group(tokens, category, group), to: Jetons.Query defdelegate flatten_tokens(map, prefix), to: Jetons.DTCG, as: :flatten defdelegate resolve_extends(config), to: Jetons.DTCG, as: :apply_extends defdelegate deep_merge(left, right), to: Jetons.Map defdelegate resolve_token_refs(tokens), to: Jetons.Ref, as: :expand # Resolver delegates defdelegate resolve_file!(path, input \\ %{}), to: Jetons.Resolver defdelegate resolve!(document, input \\ %{}, opts \\ []), to: Jetons.Resolver defdelegate list_permutations(document), to: Jetons.Resolver end