Showing
1 changed file
with
34 additions
and
1 deletions
| @@ -45,10 +45,20 @@ class DocumentComposer: | @@ -45,10 +45,20 @@ class DocumentComposer: | ||
| 45 | 返回: | 45 | 返回: |
| 46 | dict: 满足渲染器需求的Document IR。 | 46 | dict: 满足渲染器需求的Document IR。 |
| 47 | """ | 47 | """ |
| 48 | + # 构建从chapterId到toc anchor的映射 | ||
| 49 | + toc_anchor_map = self._build_toc_anchor_map(metadata) | ||
| 50 | + | ||
| 48 | ordered = sorted(chapters, key=lambda c: c.get("order", 0)) | 51 | ordered = sorted(chapters, key=lambda c: c.get("order", 0)) |
| 49 | for idx, chapter in enumerate(ordered, start=1): | 52 | for idx, chapter in enumerate(ordered, start=1): |
| 50 | chapter.setdefault("chapterId", f"S{idx}") | 53 | chapter.setdefault("chapterId", f"S{idx}") |
| 51 | - anchor = chapter.get("anchor") or f"section-{idx}" | 54 | + |
| 55 | + # 优先级:1. 目录配置的anchor 2. 章节自带的anchor 3. 默认anchor | ||
| 56 | + chapter_id = chapter.get("chapterId") | ||
| 57 | + anchor = ( | ||
| 58 | + toc_anchor_map.get(chapter_id) or | ||
| 59 | + chapter.get("anchor") or | ||
| 60 | + f"section-{idx}" | ||
| 61 | + ) | ||
| 52 | chapter["anchor"] = self._ensure_unique_anchor(anchor) | 62 | chapter["anchor"] = self._ensure_unique_anchor(anchor) |
| 53 | chapter.setdefault("order", idx * 10) | 63 | chapter.setdefault("order", idx * 10) |
| 54 | if chapter.get("errorPlaceholder"): | 64 | if chapter.get("errorPlaceholder"): |
| @@ -78,6 +88,29 @@ class DocumentComposer: | @@ -78,6 +88,29 @@ class DocumentComposer: | ||
| 78 | self._seen_anchors.add(anchor) | 88 | self._seen_anchors.add(anchor) |
| 79 | return anchor | 89 | return anchor |
| 80 | 90 | ||
| 91 | + def _build_toc_anchor_map(self, metadata: Dict[str, object]) -> Dict[str, str]: | ||
| 92 | + """ | ||
| 93 | + 从metadata.toc.customEntries构建chapterId到anchor的映射。 | ||
| 94 | + | ||
| 95 | + 参数: | ||
| 96 | + metadata: 文档元信息。 | ||
| 97 | + | ||
| 98 | + 返回: | ||
| 99 | + dict: chapterId -> anchor 的映射。 | ||
| 100 | + """ | ||
| 101 | + toc_config = metadata.get("toc") or {} | ||
| 102 | + custom_entries = toc_config.get("customEntries") or [] | ||
| 103 | + anchor_map = {} | ||
| 104 | + | ||
| 105 | + for entry in custom_entries: | ||
| 106 | + if isinstance(entry, dict): | ||
| 107 | + chapter_id = entry.get("chapterId") | ||
| 108 | + anchor = entry.get("anchor") | ||
| 109 | + if chapter_id and anchor: | ||
| 110 | + anchor_map[chapter_id] = anchor | ||
| 111 | + | ||
| 112 | + return anchor_map | ||
| 113 | + | ||
| 81 | def _ensure_heading_block(self, chapter: Dict[str, object]) -> None: | 114 | def _ensure_heading_block(self, chapter: Dict[str, object]) -> None: |
| 82 | """保证占位章节仍然拥有可用于目录的heading block。""" | 115 | """保证占位章节仍然拥有可用于目录的heading block。""" |
| 83 | blocks = chapter.get("blocks") | 116 | blocks = chapter.get("blocks") |
-
Please register or login to post a comment