"""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) }