feat: single-source theme discovery replaces three hardcoded whitelists

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-22 17:14:44 +08:00
parent cd109cf873
commit 204c5039ab
4 changed files with 38 additions and 4 deletions
+18 -1
View File
@@ -4,12 +4,29 @@ import json
import re
import socket
import uuid
from pathlib import Path
from urllib.parse import urlparse, unquote
import bleach
from . import db
ROOT = Path(__file__).resolve().parent.parent
def discover_themes():
"""Discover built-in themes from themes/*/manifest.json (single source of truth)."""
found = []
for entry in sorted((ROOT / 'themes').iterdir()):
if not entry.is_dir() or entry.name.startswith('_'):
continue
try:
manifest = json.loads((entry / 'manifest.json').read_text(encoding='utf-8'))
except (OSError, ValueError):
continue
if isinstance(manifest, dict) and manifest.get('id') == entry.name:
found.append(entry.name)
return tuple(found)
TYPES = ('page','product','post','service','case','brand','vehicle','other')
THEMES = ('automotive','industrial','corporate','minimal')
THEMES = discover_themes()
ALLOWED_TAGS = ['p','br','b','i','u','em','strong','h1','h2','h3','h4','h5','h6','ul','ol','li','blockquote','pre','code','a','img','figure','figcaption','table','thead','tbody','tr','th','td','hr','div','span']
ALLOWED_ATTRS = {'a':['href','title','target','rel'], 'img':['src','alt','title','loading','width','height'], 'td':['colspan','rowspan'], 'th':['colspan','rowspan']}
+1 -2
View File
@@ -13,9 +13,8 @@ from pathlib import Path
from urllib.parse import quote
from jinja2 import Environment, FileSystemLoader, select_autoescape
from markupsafe import Markup
from .core import sanitize, route_path
from .core import sanitize, route_path, THEMES
THEMES=('automotive','industrial','corporate','minimal')
ROOT=Path(__file__).resolve().parent.parent
LOADER=Environment(loader=FileSystemLoader(str(ROOT/'themes')),autoescape=select_autoescape(['html','xml']))
+1 -1
View File
@@ -8,10 +8,10 @@ from __future__ import annotations
import io, json, re, zipfile, shutil
from pathlib import Path
from . import db
from .core import THEMES as BUILTIN
BASE=Path(__file__).resolve().parent.parent/'themes'
THEME_ROOT=db.DATA/'theme_packages'
BUILTIN=('automotive','industrial','corporate','minimal')
THEME_ID=re.compile(r'^[a-z][a-z0-9-]{2,39}$')
VERSION=re.compile(r'^\d+\.\d+\.\d+$')