马一丁

Optimize the Binding of the Catalog

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