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

1"""模板 → 有序章节规格映射(Phase 5)。 

2 

3真实 ParsedTemplate.sections 为 ChapterMarker 列表;章节由 type=="heading" 起, 

4紧随其后的 type=="placeholder" 且形如 `section:<id>` 的标记归属该章, 

5用于确定 chapter_id 与 section_placeholder(语言无关、按文档顺序)。 

6 

7design.md §6.5 映射规则:仅 Heading level<=1 起章(1 章 = 1 次生成循环); 

8level>=2 的节/小节归入当前章 sub_headings,随本章一并生成——避免无 

9{{section:id}} 锚点的子章「生成后静默丢弃」。 

10""" 

11from __future__ import annotations 

12 

13import re 

14 

15from genesis.data_models import ParsedTemplate 

16from genesis.writer.models import ChapterSpec 

17 

18_SECTION_RE = re.compile(r"^section:(.+)$", re.IGNORECASE) 

19 

20 

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