Theme loading and layout resolution with inheritance.
A theme is a directory under themes/ containing layouts and optional static
assets. Themes can inherit from a parent (defaulting to "default").
Layout resolution walks the inheritance chain: custom theme -> parent -> default.
Theme Directory Structure
themes/my_theme/
├── layouts/
│ ├── article.html.eex
│ └── custom.html.eex
└── assets/
├── css/
└── images/Configuration
config :sayfa, :site,
theme: "my_theme",
theme_parent: "default"Examples
config = Sayfa.Config.resolve(theme: "my_theme")
dirs = Sayfa.Theme.resolve_layouts_dirs(config)
#=> ["themes/my_theme/layouts", ".../priv/default_theme/layouts"]
Summary
Functions
Copies theme assets to the output directory.
Finds the first existing layout file by walking the theme chain.
Returns an ordered list of layout directories for the theme chain.
Functions
Copies theme assets to the output directory.
Copies files from themes/<name>/assets/ to <output_dir>/assets/.
Does nothing if the theme has no assets directory.
Examples
Sayfa.Theme.copy_assets(config, "dist")
Finds the first existing layout file by walking the theme chain.
Returns the path to the layout file, or nil if not found in any theme.
Examples
iex> config = %{theme: "default", theme_parent: "default"}
iex> path = Sayfa.Theme.resolve_layout("base", config)
iex> String.ends_with?(path, "base.html.eex")
true
iex> config = %{theme: "default", theme_parent: "default"}
iex> Sayfa.Theme.resolve_layout("nonexistent_layout_xyz", config)
nil
Returns an ordered list of layout directories for the theme chain.
Walks from the current theme through its parent(s) to the default theme. Only directories that exist are included.
Examples
iex> config = %{theme: "default", theme_parent: "default"}
iex> dirs = Sayfa.Theme.resolve_layouts_dirs(config)
iex> length(dirs) >= 1
true