Skip to content

Commit 2ed7b74

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

3 files changed

Lines changed: 52 additions & 85 deletions

File tree

epub_browser/assets/chapter.css

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,6 @@ body {
149149
display: flex;
150150
}
151151

152-
.iframe-container {
153-
width: 100%;
154-
height: 100%;
155-
}
156-
157152
.toc-floating {
158153
position: fixed;
159154
top: 208px;

epub_browser/assets/chapter.js

Lines changed: 49 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,83 +1508,60 @@ function initScript() {
15081508
}
15091509

15101510

1511-
// iframe 处理
1512-
let iframe = document.getElementById('bookHomeIframe');
1513-
iframe.addEventListener('load', function() {
1514-
loadBookHomeToc();
1515-
iframeAddEvent();
1516-
});
1517-
function loadBookHomeToc() {
1518-
try {
1519-
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
1520-
// 使用 iframeDoc 进行操作
1521-
let bookHomeToc = iframeDoc.querySelector('.chapter-list');
1522-
let iframeBody = iframeDoc.querySelector('body');
1523-
let iframeFooter = iframeDoc.querySelector('footer');
1524-
let iframeContainer = iframeDoc.querySelector('.container');
1525-
let topControls = iframeDoc.querySelector('.top-controls');
1526-
let readingControls = iframeDoc.querySelector('.reading-controls');
1527-
let breadcrumb = iframeDoc.querySelector('.breadcrumb');
1528-
let bookInfoCard = iframeDoc.querySelector('.book-info-card');
1529-
let tocHeader = iframeDoc.querySelector('.toc-header');
1530-
let tocContainer = iframeDoc.querySelector('.toc-container');
1531-
1532-
topControls.style.display = 'none';
1533-
breadcrumb.style.display = 'none';
1534-
bookInfoCard.style.display = 'none';
1535-
iframeFooter.style.display = 'none';
1536-
tocHeader.style.display = 'none';
1537-
readingControls.style.display = 'none';
1538-
bookHomeToc.style.width = "100%";
1539-
bookHomeToc.style.maxHeight = "100%";
1540-
iframeBody.style.padding = 0;
1541-
iframeContainer.style.padding = 0;
1542-
iframeContainer.style.margin = 0;
1543-
tocContainer.style.margin = 0;
1544-
} catch (e) {
1545-
console.log('Can not reach iframe:', e.message);
1546-
}
1547-
}
1548-
1549-
function iframeAddEvent() {
1511+
// 加载书籍目录
1512+
loadBookHomeToc();
1513+
1514+
async function loadBookHomeToc() {
15501515
try {
1551-
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
1552-
// 使用 iframeDoc 进行操作
1553-
let allLinks = iframeDoc.querySelectorAll('a');
1554-
allLinks.forEach( link => {
1555-
link.addEventListener('click', function(event) {
1556-
// 阻止默认行为(在iframe中打开)
1557-
event.preventDefault();
1558-
// 获取链接URL
1559-
var href = this.getAttribute('href');
1560-
// 在主窗口中打开链接
1561-
window.parent.location.href = href;
1562-
return false;
1516+
const bookHomeTocList = document.getElementById('bookHomeTocList');
1517+
const currentPath = window.location.pathname;
1518+
const bookHash = currentPath.split('/book/')[1].split('/')[0];
1519+
const tocJsonPath = `/book/${bookHash}/toc.json`;
1520+
1521+
const response = await fetch(tocJsonPath);
1522+
if (!response.ok) {
1523+
throw new Error(`HTTP error! status: ${response.status}`);
1524+
}
1525+
const tocData = await response.json();
1526+
1527+
bookHomeTocList.innerHTML = '';
1528+
1529+
tocData.forEach(item => {
1530+
const listItem = document.createElement('li');
1531+
listItem.className = `toc-item toc-level-${Math.min(item.level, 3)}`;
1532+
1533+
const link = document.createElement('a');
1534+
let href = `/book/${bookHash}/${item.chapter_file}`;
1535+
if (item.anchor) {
1536+
href += `#${item.anchor}`;
1537+
}
1538+
link.href = href;
1539+
link.textContent = item.title;
1540+
1541+
link.addEventListener('click', function(e) {
1542+
e.preventDefault();
1543+
window.location.href = href;
15631544
});
1545+
1546+
listItem.appendChild(link);
1547+
bookHomeTocList.appendChild(listItem);
15641548
});
1565-
1566-
// 书籍目录锚点滚动
1567-
mobileBookHomeBtn.addEventListener('click', function(){
1568-
scrollBookHomeToc();
1569-
});
1570-
bookHomeToggle.addEventListener('click', function(){
1571-
scrollBookHomeToc();
1572-
});
1573-
1574-
function scrollBookHomeToc() {
1575-
if (anchor != '') { // 后面有 var anchor 的声明和取值
1576-
targetEl = iframeDoc.getElementById(anchor.substr(1));
1577-
if (targetEl) {
1578-
var rect = targetEl.getBoundingClientRect();
1579-
// 滚动到元素位置
1580-
iframe.contentWindow.scrollTo({
1581-
top: rect.top + iframe.contentWindow.pageYOffset,
1582-
});
1583-
}
1584-
}
1549+
1550+
// 滚动到当前章节
1551+
const currentChapter = currentPath.split('/').pop();
1552+
const activeLi = bookHomeTocList.querySelector(`a[href*="${currentChapter}"]`);
1553+
if (activeLi) {
1554+
const listItem = activeLi.parentElement;
1555+
listItem.classList.add('active');
1556+
bookHomeTocList.scrollTop = listItem.offsetTop - 150;
15851557
}
1558+
15861559
} catch (e) {
1587-
console.log('Can not reach iframe:', e.message);
1560+
console.log('Failed to load book home toc:', e.message);
1561+
const bookHomeTocList = document.getElementById('bookHomeTocList');
1562+
if (bookHomeTocList) {
1563+
bookHomeTocList.innerHTML = '<li class="toc-item">Failed to load table of contents</li>';
1564+
}
15881565
}
15891566
}
15901567

@@ -1667,9 +1644,6 @@ function initScript() {
16671644
} else {
16681645
setCookie(book_hash, anchor);
16691646
}
1670-
1671-
let bookHomeIframe = document.querySelector('#bookHomeIframe');
1672-
bookHomeIframe.src += anchor;
16731647
}
16741648

16751649
// 主题切换功能
@@ -1791,7 +1765,6 @@ function initScript() {
17911765
});
17921766
bookHomeToggle.addEventListener('click', function() {
17931767
bookHomeFloating.classList.toggle('active');
1794-
loadBookHomeToc();
17951768
});
17961769

17971770
// 切换目录显示 - 移动端
@@ -1805,7 +1778,6 @@ function initScript() {
18051778
bookHomeFloating.classList.toggle('active');
18061779
// 移动端点击后高亮按钮
18071780
mobileBookHomeBtn.classList.toggle('active');
1808-
loadBookHomeToc();
18091781
});
18101782

18111783
// 关闭目录

epub_browser/processor.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -984,9 +984,9 @@ def create_chapter_template(self, content, style_links, chapter_index, chapter_t
984984
<i class="fas fa-times"></i>
985985
</button>
986986
</div>
987-
<div class="iframe-container">
988-
<iframe id="bookHomeIframe" src="/book/{self.book_hash}/index.html" title="BookHome" sandbox="allow-same-origin allow-scripts allow-forms"></iframe>
989-
</div>
987+
<ul class="toc-list" id="bookHomeTocList">
988+
<!-- 动态生成的书籍目录将放在这里 -->
989+
</ul>
990990
</div>
991991
992992
<div class="toc-floating" id="tocFloating">

0 commit comments

Comments
 (0)