Parent
#1 — context2html Framework
What to build
Extend theme/theme-index.json with recommendation fields, then build context2html/theme.py that provides programmatic access to 20 brand themes.
theme-index.json extension — add two optional fields per theme entry:
{
"name": "warm",
"display_name": "暖阳",
"brand": "default",
"accent": "#c0392b",
"bg": "#faf9f7",
"recommend_for": ["report", "article"],
"recommend_topics": ["经济", "社会", "教育"]
}
Existing entries keep working — recommend_for and recommend_topics are optional, defaulting to all content types / empty topic list.
ThemeProvider API:
ThemeProvider.list_themes() → list of ThemeInfo (name, display_name, brand, accent, bg)
ThemeProvider.get_theme(name) → ThemeInfo with all variables
ThemeProvider.recommend_theme(content_type, topic=None) → theme name string
- Exact topic match (check
recommend_topics includes topic) → exact content type match → fall back to warm
Acceptance criteria
Blocked by
Parent
#1 — context2html Framework
What to build
Extend
theme/theme-index.jsonwith recommendation fields, then buildcontext2html/theme.pythat provides programmatic access to 20 brand themes.theme-index.json extension — add two optional fields per theme entry:
{ "name": "warm", "display_name": "暖阳", "brand": "default", "accent": "#c0392b", "bg": "#faf9f7", "recommend_for": ["report", "article"], "recommend_topics": ["经济", "社会", "教育"] }Existing entries keep working —
recommend_forandrecommend_topicsare optional, defaulting to all content types / empty topic list.ThemeProvider API:
ThemeProvider.list_themes()→ list ofThemeInfo(name, display_name, brand, accent, bg)ThemeProvider.get_theme(name)→ThemeInfowith all variablesThemeProvider.recommend_theme(content_type, topic=None)→ theme name stringrecommend_topicsincludes topic) → exact content type match → fall back to warmAcceptance criteria
theme/theme-index.jsonhas the new fields for all 20 themesget_theme("warm")returns aThemeInfowith accent="#c0392b", bg="#faf9f7"recommend_theme("report", "经济")returns a reasonable theme (not just "warm" for everything)recommend_theme("blog", null)— unknown content type — returns default ("warm")theme/theme-index.jsonas-is to catch schema driftBlocked by