pageweave/resources

theme-extraction

· .md

Theme extraction

Inspect the source site's CSS for colors (ranked hex codes from inline styles + <style> blocks) and fonts (ranked font families). This file describes the deterministic algorithm to derive a daisyUI theme from that input.

Step 1: classify each color

For each hex color from css_colors, convert to HSL. Then bucket:

Saturation Lightness Bucket
< 0.10 any neutral (gray)
≥ 0.10 < 0.30 dark-vivid
≥ 0.10 0.30 - 0.70 vivid
≥ 0.10 > 0.70 light-vivid

Step 2: assign semantic roles

If no vivid colors exist in the source, fall back to daisyUI defaults (blue 240 hue) and note this in your rebuild summary.

Step 3: convert hex to OKLCH

Use the OKLCH conversion. Ruby snippet (already available via the color gem if bundled, otherwise compute):

# Pseudocode — actual conversion uses CSS Color 4 spec
def hex_to_oklch(hex)
  rgb = parse_hex(hex)
  linear = rgb.map { |c| gamma_decode(c / 255.0) }
  # ... linear → XYZ → OKLab → OKLCH
  "#{lightness.round(0)}% #{chroma.round(3)} #{hue.round(0)}"
end

For OKLCH values, hue (h) is in degrees 0-360, lightness (L) is 0-100%, chroma (C) is typically 0-0.4.

Step 4: derive *-content colors

For each semantic color, the *-content color must contrast ≥4.5:1 (WCAG AA). Quick heuristic:

Step 5: assemble theme CSS

Wrap in [data-theme="custom"] { ... } block. Pass to set_theme tool. The platform's Website::Theme::ConfigNormalizer may auto-wrap; check the response.

If base-100 is dark (sanity check below), add color-scheme: dark; to the block — platform and browser UI detect darkness from it.

Sanity check

Before calling set_theme: