- Identité noir & blanc pur (zéro gris, anti-ghosting e-ink) ; hachures pour conso/alarme - Typo vendorisée : Archivo (mots) + JetBrains Mono (nombres tabulaires), @font-face base64 - Jauge signature : noir = restant, repère seuil 20 %, hachures sous le seuil - Météo : glyphes 1-bit en silhouette (weather.kind) au lieu d'emoji couleur - Layout rééquilibré (plus de débordement), états dégradés soignés - dev/preview.py : aperçu hors-ligne du template
38 lines
1.3 KiB
Python
38 lines
1.3 KiB
Python
"""Génère le bloc CSS @font-face avec les woff2 vendorisés embarqués en data-URI.
|
|
|
|
Playwright rend via page.set_content() (pas de base URL) : les chemins de police
|
|
relatifs ne se résolvent pas. On embarque donc les woff2 en base64 directement dans
|
|
le CSS. Résultat mémoïsé (les fichiers ne changent pas au runtime)."""
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
|
|
FONTS_DIR = Path(__file__).parent / "static" / "fonts"
|
|
|
|
# (famille CSS, fichier, graisse)
|
|
_FACES = [
|
|
("Archivo", "archivo-700.woff2", 700),
|
|
("Archivo", "archivo-800.woff2", 800),
|
|
("JetBrains Mono", "jbmono-400.woff2", 400),
|
|
("JetBrains Mono", "jbmono-500.woff2", 500),
|
|
("JetBrains Mono", "jbmono-700.woff2", 700),
|
|
("JetBrains Mono", "jbmono-800.woff2", 800),
|
|
]
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def font_face_css() -> str:
|
|
"""CSS @font-face complet (data-URI) à injecter dans le <style> du template."""
|
|
blocks = []
|
|
for family, filename, weight in _FACES:
|
|
data = (FONTS_DIR / filename).read_bytes()
|
|
b64 = base64.b64encode(data).decode("ascii")
|
|
blocks.append(
|
|
"@font-face{font-family:'%s';font-style:normal;font-weight:%d;"
|
|
"font-display:block;src:url(data:font/woff2;base64,%s) format('woff2');}"
|
|
% (family, weight, b64)
|
|
)
|
|
return "\n".join(blocks)
|