Skip to content

Commit 479c411

Browse files
committed
feat: code by Trae: opt book toc
1 parent b2fb896 commit 479c411

1 file changed

Lines changed: 90 additions & 27 deletions

File tree

epub_browser/processor.py

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -480,40 +480,15 @@ def create_index_page(self):
480480

481481
# 如果有详细的toc信息,使用toc生成目录
482482
if self.toc:
483-
# 创建章节路径到索引的映射(支持多种路径格式)
484-
chapter_index_map = {}
485-
chapter_filename_map = {} # 用于文件名匹配
486-
for i, chapter in enumerate(self.chapters):
487-
# 原始路径
488-
chapter_index_map[chapter['path']] = i
489-
# 规范化路径(去除 ./ 前缀)
490-
normalized_path = chapter['path'].lstrip('./').lstrip('/')
491-
chapter_index_map[normalized_path] = i
492-
# 文件名匹配
493-
chapter_filename = os.path.basename(chapter['path'])
494-
chapter_filename_map[chapter_filename] = i
495-
496-
# print(f"Chapter index mapping: {chapter_index_map}")
497-
# print(f"Chapter filename mapping: {chapter_filename_map}")
483+
chapter_index_map, chapter_filename_map = self._build_chapter_index_maps()
498484

499485
# 根据toc生成目录
500486
for toc_item in self.toc:
501487
level_class = f"toc-level-{min(toc_item.get('level', 0), 3)}"
502488
chapter_anchor = toc_item.get('anchor', None)
503489
toc_src = toc_item['src']
504490

505-
# 尝试多种方式匹配章节索引
506-
chapter_index = None
507-
508-
# 1. 直接匹配
509-
if toc_src in chapter_index_map:
510-
chapter_index = chapter_index_map[toc_src]
511-
# 2. 规范化路径匹配(去除 ./ 前缀)
512-
elif toc_src.lstrip('./').lstrip('/') in chapter_index_map:
513-
chapter_index = chapter_index_map[toc_src.lstrip('./').lstrip('/')]
514-
# 3. 文件名匹配
515-
elif os.path.basename(toc_src) in chapter_filename_map:
516-
chapter_index = chapter_filename_map[os.path.basename(toc_src)]
491+
chapter_index = self._find_chapter_index(toc_src, chapter_index_map, chapter_filename_map)
517492

518493
if chapter_index is not None:
519494
if chapter_anchor is not None:
@@ -622,6 +597,94 @@ def create_index_page(self):
622597
index_html = minify_html.minify(index_html, minify_css=False, minify_js=False)
623598
with open(os.path.join(self.web_dir, 'index.html'), 'w', encoding='utf-8') as f:
624599
f.write(index_html)
600+
601+
# 生成目录 JSON 文件
602+
self.create_toc_json()
603+
604+
def _build_chapter_index_maps(self):
605+
"""构建章节路径到索引的映射(支持多种路径格式)
606+
607+
Returns:
608+
tuple: (chapter_index_map, chapter_filename_map)
609+
"""
610+
chapter_index_map = {}
611+
chapter_filename_map = {}
612+
for i, chapter in enumerate(self.chapters):
613+
# 原始路径
614+
chapter_index_map[chapter['path']] = i
615+
# 规范化路径(去除 ./ 前缀)
616+
normalized_path = chapter['path'].lstrip('./').lstrip('/')
617+
chapter_index_map[normalized_path] = i
618+
# 文件名匹配
619+
chapter_filename = os.path.basename(chapter['path'])
620+
chapter_filename_map[chapter_filename] = i
621+
return chapter_index_map, chapter_filename_map
622+
623+
def _find_chapter_index(self, toc_src, chapter_index_map, chapter_filename_map):
624+
"""根据toc_src查找章节索引
625+
626+
Args:
627+
toc_src: 目录项的src路径
628+
chapter_index_map: 章节路径到索引的映射
629+
chapter_filename_map: 章节文件名到索引的映射
630+
631+
Returns:
632+
int or None: 章节索引,未找到则返回None
633+
"""
634+
# 1. 直接匹配
635+
if toc_src in chapter_index_map:
636+
return chapter_index_map[toc_src]
637+
# 2. 规范化路径匹配(去除 ./ 前缀)
638+
elif toc_src.lstrip('./').lstrip('/') in chapter_index_map:
639+
return chapter_index_map[toc_src.lstrip('./').lstrip('/')]
640+
# 3. 文件名匹配
641+
elif os.path.basename(toc_src) in chapter_filename_map:
642+
return chapter_filename_map[os.path.basename(toc_src)]
643+
return None
644+
645+
def create_toc_json(self):
646+
"""生成目录 JSON 文件到书籍自己的文件夹下"""
647+
toc_data = []
648+
649+
# 如果有详细的toc信息,使用toc生成目录
650+
if self.toc:
651+
chapter_index_map, chapter_filename_map = self._build_chapter_index_maps()
652+
653+
# 根据toc生成目录
654+
for toc_item in self.toc:
655+
chapter_anchor = toc_item.get('anchor', None)
656+
toc_src = toc_item['src']
657+
658+
chapter_index = self._find_chapter_index(toc_src, chapter_index_map, chapter_filename_map)
659+
660+
if chapter_index is not None:
661+
chapter_data = {
662+
'title': toc_item['title'],
663+
'level': toc_item.get('level', 0),
664+
'chapter_index': chapter_index,
665+
'chapter_file': f'chapter_{chapter_index}.html'
666+
}
667+
if chapter_anchor is not None:
668+
chapter_data['anchor'] = chapter_anchor
669+
toc_data.append(chapter_data)
670+
else:
671+
print(f"Chapter index not found for toc item: {toc_item['title']} (src: {toc_src})")
672+
else:
673+
# 回退到简单章节列表
674+
for i, chapter in enumerate(self.chapters):
675+
toc_data.append({
676+
'title': chapter['title'],
677+
'level': 0,
678+
'chapter_index': i,
679+
'chapter_file': f'chapter_{i}.html'
680+
})
681+
682+
# 保存为 JSON 文件到书籍自己的文件夹下
683+
toc_json_path = os.path.join(self.web_dir, 'toc.json')
684+
with open(toc_json_path, 'w', encoding='utf-8') as f:
685+
json.dump(toc_data, f, ensure_ascii=False, indent=2)
686+
687+
print(f"TOC JSON file created: {toc_json_path} with {len(toc_data)} items")
625688

626689
def create_chapter_pages(self):
627690
"""创建章节页面"""

0 commit comments

Comments
 (0)