Coverage for src\genesis\writer\template_mapper.py: 95%
27 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 14:20 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 14:20 +0800
1"""模板 → 有序章节规格映射(Phase 5)。
3真实 ParsedTemplate.sections 为 ChapterMarker 列表;章节由 type=="heading" 起,
4紧随其后的 type=="placeholder" 且形如 `section:<id>` 的标记归属该章,
5用于确定 chapter_id 与 section_placeholder(语言无关、按文档顺序)。
7design.md §6.5 映射规则:仅 Heading level<=1 起章(1 章 = 1 次生成循环);
8level>=2 的节/小节归入当前章 sub_headings,随本章一并生成——避免无
9{{section:id}} 锚点的子章「生成后静默丢弃」。
10"""
11from __future__ import annotations
13import re
15from genesis.data_models import ParsedTemplate
16from genesis.writer.models import ChapterSpec
18_SECTION_RE = re.compile(r"^section:(.+)$", re.IGNORECASE)
21def map_template(parsed: ParsedTemplate) -> list[ChapterSpec]:
22 specs: list[ChapterSpec] = []
23 idx = 0
24 current: ChapterSpec | None = None
25 for ch in getattr(parsed, "sections", []):
26 t = getattr(ch, "type", None)
27 if t == "heading":
28 level = int(getattr(ch, "level", 1) or 1)
29 if level > 1 and current is not None:
30 # §6.5:节/小节归入父章,不独立成章
31 current.sub_headings.append(getattr(ch, "name", ""))
32 continue
33 idx += 1
34 current = ChapterSpec(
35 chapter_id=f"chapter_{idx}", title=getattr(ch, "name", ""), section_placeholder=None
36 )
37 specs.append(current)
38 elif t == "placeholder" and current is not None:
39 m = _SECTION_RE.match(getattr(ch, "name", ""))
40 if m: 40 ↛ 25line 40 didn't jump to line 25 because the condition on line 40 was always true
41 sid = m.group(1)
42 current.section_placeholder = getattr(ch, "name", "")
43 if current.chapter_id.startswith("chapter_"): 43 ↛ 25line 43 didn't jump to line 25 because the condition on line 43 was always true
44 current.chapter_id = sid
45 return specs