feat: custom themes polishing

This commit is contained in:
3252a8
2026-05-15 11:17:27 +03:00
parent b6ee5e8790
commit af7cee5014
28 changed files with 1474 additions and 306 deletions
+24 -5
View File
@@ -8,7 +8,7 @@ import re
from pathlib import Path
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field, model_validator
from pydantic import BaseModel, Field, field_validator, model_validator
logger = logging.getLogger(__name__)
@@ -48,6 +48,22 @@ class ThemeTokens(BaseModel):
admin_muted: Optional[str] = None
admin_dim: Optional[str] = None
@field_validator("accent")
@classmethod
def _normalize_accent_hex(cls, value: Optional[str]) -> Optional[str]:
if value is None:
return None
raw = str(value).strip()
if not raw:
return None
match = re.fullmatch(r"#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})", raw)
if not match:
raise ValueError("accent must be a hex color (#RGB or #RRGGBB)")
hex_value = match.group(1).lower()
if len(hex_value) == 3:
hex_value = "".join(char * 2 for char in hex_value)
return f"#{hex_value}"
class WebappTheme(BaseModel):
"""Single theme descriptor loaded from WEBAPP_THEMES_DIR/<key>/theme.json."""
@@ -256,10 +272,13 @@ def _theme_sort_key(theme: WebappTheme, index: int) -> tuple[int, int]:
def _sorted_themes(themes: List[WebappTheme]) -> List[WebappTheme]:
return [theme for _, theme in sorted(
((_theme_sort_key(t, i), t) for i, t in enumerate(themes)),
key=lambda pair: pair[0],
)]
return [
theme
for _, theme in sorted(
((_theme_sort_key(t, i), t) for i, t in enumerate(themes)),
key=lambda pair: pair[0],
)
]
def _themes_config_from_list(