# template-rendering **Repository Path**: jeanarysun/template-rendering ## Basic Information - **Project Name**: template-rendering - **Description**: 通用 HTML 模板渲染:Jinja2 多模板 + Playwright 出图,零框架依赖,任意 Python 项目可用。一套数据,多种风格换皮,详见 README - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-08-20 - **Last Updated**: 2026-08-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🎨 template-rendering 通用 **数据 → HTML 模板 → PNG 图片** 渲染工具:Jinja2 多模板 + Playwright 出图。 **零框架依赖**,不绑定任何业务框架,任意 Python 项目可用。一套数据,任意风格换皮。 ## ✨ 十套风格 | 风格名 | 视觉 | |---|---| | `scrapbook` | 手账风:米黄点阵纸 + 五色便签 + 胶带 + 蜡笔柱状图 | | `ATRI` | 马卡龙日系 UI:角色 + 渐变玻璃卡 + 漂浮贴纸 | | `BlueArchive` | 青绿薄荷:看板娘速报 + 彩色图标 KPI | | `HatsuneMiku` | 淡紫梦幻:初音主题 + 24 色渐变柱状图 | | `retro_futurism` | 报纸头版橙红:CRT 扫描线 + 终端风 | | `spring_festival` | 春节红金:红包 KPI + 灯笼装饰 | | `simple` | 极简单蓝 BI | | `format` | 黑白出版物 | | `hack` | 黑底琥珀橙霓虹:终端代码块 + 命令行区块标题 | | `generic_card` | 白底通用卡片:标题 / k-v 明细表 / 列表 / 署名 | ## 🚀 快速开始 ```bash pip install jinja2 playwright playwright install chromium ``` ```python import asyncio, sys sys.path.insert(0, "path/to/template-rendering/scripts") from template_render_engine import render_template_one, default_templates_root payload = { "title": "今日热点速览", "date": "2026-08-15", "kpis": [{"label": "热点总数", "value": "12", "icon": "chat"}], "topics": [{"title": "标题", "desc": "细节", "tag": "01"}], "footer": "署名", } async def main(): # 同一份数据,换风格名即换皮 for style in ["scrapbook", "hack", "ATRI", "simple"]: img = await render_template_one(style, payload, default_templates_root()) open(f"/tmp/{style}.png", "wb").write(img) asyncio.run(main()) ``` ## 🧩 三种使用层次 | API | 输入 | 适合 | |---|---|---| | `render_data(data)` | 结构化数据 | 不想管排版,给数据就出图 | | `render_styled(style, html)` | 任意 HTML | 要自己排版,只套皮肤 | | `render_html_to_image(html)` | 任意 HTML | 完全自由,不经过模板系统 | ### 通用 payload 契约(所有字段可选) ```python payload = { "title": "主标题", "date": "2026-08-15", "kpis": [{"label": "指标", "value": "12", "icon": "chat"}], # icon: chat/users/emoji/text "highlight": {"value": "巅峰信息", "desc": "说明"}, "topics": [{"title": "标题", "desc": "细节", "tag": "01"}], "titles": [{"name": "人名", "title": "头衔", "badge": "徽章", "reason": "理由"}], "quotes": [{"content": "金句", "sender": "说话人", "reason": "点评"}], "chart_data": [{"label": "0时", "value": 26}], "footer": "署名", "meta": "附加信息", } ``` ## 🏗️ 模板机制 一个风格 = 一个子目录,即插即用: ``` templates/ ├── scrapbook/ │ ├── image_template.html # 主模板(Jinja2) │ ├── topic_item.html # 子模板,自动注入为 {{ topics_html }} │ └── skin.html # 皮肤:head + CSS + {{ content_html }} 占位 └── my_style/ # 自定义风格,随便放 .html 即可 ``` 引擎自动渲染目录下所有子模板,以 `文件名 + "_html"` 为键注入 payload,零注册代码。 ## ⚠️ 坑位提醒 1. `wait_until` 用 `load`,别用 `networkidle`(外链会卡死超时) 2. 引用注入片段必须 `{{ xxx_html | safe }}`(否则被转义成纯文本) 3. HTML 里嵌用户文本 → `html.escape()` 防 XSS 4. PNG > 500KB 手机加载慢 → `screenshot(type="jpeg", quality=85)` ## 📄 完整文档 详见 [SKILL.md](SKILL.md):渲染链路、payload 契约、坑位清单、集成方式。 ## 📦 结构 ``` template-rendering/ ├── SKILL.md # 完整使用文档 ├── scripts/ │ ├── template_render_engine.py # 渲染引擎:jinja2 + playwright │ └── demo_render_all.py # 独立验证:一份 payload 渲全部 10 套 └── templates/ # 10 套现成模板 ``` ## 📜 License MIT