feat: add CSS generation system with custom properties and ETS cache
- Create theme-primitives.css with spacing, fonts, radius scales
- Create theme-semantic.css with semantic CSS variable aliases
- Update app.css to import theme CSS files
- Add CSSGenerator module for dynamic CSS token generation
- Generates mood variables (neutral, warm, cool, dark)
- Generates typography variables (7 font combinations)
- Generates shape variables (sharp, soft, round, pill)
- Generates density variables (spacious, balanced, compact)
- Converts hex colors to HSL for flexible manipulation
- Add CSSCache GenServer with ETS table for performance
- Caches generated CSS to avoid regeneration
- Warms cache on application startup
- Provides invalidation for theme updates
- Add CSSCache to application supervision tree
- Add comprehensive tests for CSS generation (29 tests)
- Add comprehensive tests for preset validation (14 tests)
- All tests passing (58 total tests, 0 failures)
- Verified CSS generation and caching work correctly in IEx
2025-12-30 21:41:25 +00:00
|
|
|
defmodule SimpleshopTheme.Theme.CSSCache do
|
|
|
|
|
@moduledoc """
|
|
|
|
|
GenServer that maintains an ETS table for caching generated theme CSS.
|
|
|
|
|
|
|
|
|
|
This provides fast lookups for theme CSS without regenerating it on every request.
|
|
|
|
|
The cache is invalidated when theme settings are updated.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
use GenServer
|
|
|
|
|
|
|
|
|
|
@table_name :theme_css_cache
|
|
|
|
|
|
|
|
|
|
## Client API
|
|
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
|
Starts the CSS cache GenServer.
|
|
|
|
|
"""
|
|
|
|
|
def start_link(opts) do
|
|
|
|
|
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
|
Gets cached CSS for the site theme.
|
|
|
|
|
|
|
|
|
|
Returns `{:ok, css}` if found in cache, or `:miss` if not cached.
|
|
|
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
|
|
iex> CSSCache.get()
|
|
|
|
|
{:ok, "/* Theme CSS ... */"}
|
|
|
|
|
|
|
|
|
|
iex> CSSCache.get()
|
|
|
|
|
:miss
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def get do
|
|
|
|
|
case :ets.lookup(@table_name, :site_theme) do
|
|
|
|
|
[{:site_theme, css}] -> {:ok, css}
|
|
|
|
|
[] -> :miss
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
|
Caches CSS for the site theme.
|
|
|
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
|
|
iex> CSSCache.put(css_string)
|
|
|
|
|
:ok
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def put(css) when is_binary(css) do
|
|
|
|
|
:ets.insert(@table_name, {:site_theme, css})
|
|
|
|
|
:ok
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
|
Invalidates the cached CSS, forcing regeneration on next request.
|
|
|
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
|
|
iex> CSSCache.invalidate()
|
|
|
|
|
:ok
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def invalidate do
|
|
|
|
|
:ets.delete(@table_name, :site_theme)
|
|
|
|
|
:ok
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@doc """
|
|
|
|
|
Warms the cache by generating and storing CSS from current theme settings.
|
|
|
|
|
|
|
|
|
|
## Examples
|
|
|
|
|
|
|
|
|
|
iex> CSSCache.warm()
|
|
|
|
|
:ok
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
def warm do
|
|
|
|
|
alias SimpleshopTheme.Settings
|
|
|
|
|
alias SimpleshopTheme.Theme.CSSGenerator
|
|
|
|
|
|
|
|
|
|
settings = Settings.get_theme_settings()
|
2026-01-25 09:32:06 +00:00
|
|
|
|
|
|
|
|
# Use endpoint's static_path for digested URLs in production
|
|
|
|
|
path_resolver = &SimpleshopThemeWeb.Endpoint.static_path/1
|
|
|
|
|
|
|
|
|
|
css = CSSGenerator.generate(settings, path_resolver)
|
feat: add CSS generation system with custom properties and ETS cache
- Create theme-primitives.css with spacing, fonts, radius scales
- Create theme-semantic.css with semantic CSS variable aliases
- Update app.css to import theme CSS files
- Add CSSGenerator module for dynamic CSS token generation
- Generates mood variables (neutral, warm, cool, dark)
- Generates typography variables (7 font combinations)
- Generates shape variables (sharp, soft, round, pill)
- Generates density variables (spacious, balanced, compact)
- Converts hex colors to HSL for flexible manipulation
- Add CSSCache GenServer with ETS table for performance
- Caches generated CSS to avoid regeneration
- Warms cache on application startup
- Provides invalidation for theme updates
- Add CSSCache to application supervision tree
- Add comprehensive tests for CSS generation (29 tests)
- Add comprehensive tests for preset validation (14 tests)
- All tests passing (58 total tests, 0 failures)
- Verified CSS generation and caching work correctly in IEx
2025-12-30 21:41:25 +00:00
|
|
|
put(css)
|
|
|
|
|
:ok
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
## Server Callbacks
|
|
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
|
def init(_opts) do
|
|
|
|
|
:ets.new(@table_name, [
|
|
|
|
|
:set,
|
|
|
|
|
:public,
|
|
|
|
|
:named_table,
|
|
|
|
|
read_concurrency: true,
|
|
|
|
|
write_concurrency: false
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
# Warm the cache on startup
|
|
|
|
|
warm()
|
|
|
|
|
|
|
|
|
|
{:ok, %{}}
|
|
|
|
|
end
|
|
|
|
|
end
|