#!/usr/bin/env python3 """Generate the Dupre palette preview HTML from dupre-palette.el. Reads the (name "#hex") pairs straight from the palette source so the preview can't drift from the theme. Groups colors into one row per family (by name prefix, e.g. gray-2/gray/gray+1 share the "gray" row), with fixed-width swatches so columns line up across rows. Regenerate the PNG from the HTML afterwards: google-chrome-stable --headless=new --screenshot=themes/dupre-palette.png \\ --window-size=975,1520 --hide-scrollbars --default-background-color=151311FF \\ "file://$PWD/themes/dupre-color-palette.html" """ import re from pathlib import Path HERE = Path(__file__).resolve().parent SRC = HERE / "dupre-palette.el" OUT = HERE / "dupre-color-palette.html" text = open(SRC).read() # Only the dupre-palette defconst has (name "#hex") pairs; semantic mappings are # (name colorname) with no hex, so this regex selects exactly the base palette. pairs = re.findall(r'\(([a-z0-9]+(?:[+\-]\d+)?(?:-[a-z]+)?)\s+"(#[0-9a-fA-F]{6})"\)', text) def family(name): m = re.match(r'^([a-z]+(?:-[a-z]+)??)(?:[+\-]\d+)?$', name) return m.group(1) if m else name # Group consecutive same-family entries (palette.el already orders them so). rows, cur_fam, cur = [], None, [] for name, hexv in pairs: fam = family(name) if fam != cur_fam: if cur: rows.append((cur_fam, cur)) cur_fam, cur = fam, [] cur.append((name, hexv)) if cur: rows.append((cur_fam, cur)) def swatch(name, hexv): return (f'
' f'
' f'
{name}
' f'
{hexv}
') body = [] for fam, items in rows: body.append('
') body.append(f'
{fam}
') body.extend(swatch(n, h) for n, h in items) body.append('
') html = f""" Dupre Theme Color Palette

Dupre Theme Color Palette

{chr(10).join(body)} """ open(OUT, "w").write(html) print(f"wrote {OUT}: {len(pairs)} colors in {len(rows)} family rows") print("families:", ", ".join(f for f, _ in rows))