"""services/docgen/html_css.py —— 自家 render_html 产物的 CSS 解析(缺陷 #47a,2026-09-11)。
render_html 返回 (html, css):html 是模板 wrapper(css 不内联,
css 由调用方单独持有——PDF 路径与预览拼装时注入)。html2docx 的输入
原本只有 html,缺陷 #47a 后调用方(docgen 路由)把 css 一并传入
(converter.docx_from_html_document(html, title, css)),本模块负责:
- 解析 html 内嵌 ", "html.parser")
for decl in _declarations(wrapped.style):
block = merged.setdefault(decl["selector"], {})
block.update(decl["block"])
return merged
def letterhead_style(styles: dict[str, dict[str, str]]) -> tuple[_ColorRGB, float]:
"""红头样式:(rgb 颜色, 字号 pt)。解析不到时回退历史常量。"""
block = styles.get(".doc-letterhead") or {}
color = parse_rgb(block.get("color", "")) or _LEGACY_LETTERHEAD_COLOR
size = parse_size_pt(block.get("font-size", ""))
if size is None:
size = _LEGACY_LETTERHEAD_SIZE_PT
return color, size
def heading_sizes(styles: dict[str, dict[str, str]]) -> dict[int, float]:
"""h1-h3 字号(pt):解析 h1.doc-title、h2、h3 声明;缺失回落历史常量。"""
h1 = styles.get("h1.doc-title") or styles.get("h1") or {}
h2 = styles.get("h2") or {}
h3 = styles.get("h3") or {}
parsed = {
1: parse_size_pt(h1.get("font-size", "")),
2: parse_size_pt(h2.get("font-size", "")),
3: parse_size_pt(h3.get("font-size", "")),
}
return {
level: parsed[level] if parsed[level] is not None else _LEGACY_HEADING_SIZES_PT[level]
for level in (1, 2, 3)
}