refactor: 添加中文注释 + 优化模块结构
- 给全部 78 个 Swift 源文件添加详细的中文注释(文件级、类级、方法级) - 删除 LegacyRDReaderController/ 死代码目录(16 文件 4592 行) - 根目录翻页容器文件移入 ReaderView/ 目录 - Resources/ 移入 EPUBCore/Resources/(与使用者归属一致) - RDEPUBTextIndexTable.swift 移入 EPUBTextRendering/(消除反向依赖) - RDURLReaderController.swift 移入 EPUBUI/(入口控制器归入 UI 层) - 更新 podspec 资源路径
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
// RDEPUBParser+TOC.swift
|
||||
// EPUB 目录解析
|
||||
// 支持两种目录格式:NCX(EPUB 2)和 Navigation Document(EPUB 3),
|
||||
// 优先使用 NCX,其次 Nav Document,最终回退到 spine 列表。
|
||||
// 内部使用 TOCTreeBuilder 构建树状目录结构。
|
||||
|
||||
import Foundation
|
||||
|
||||
extension RDEPUBParser {
|
||||
/// 从 OPF 解析结果中解析目录
|
||||
/// 优先尝试 NCX,再尝试 Nav Document,两者都失败则回退到 spine 列表
|
||||
func parseTOC(from packageDocument: OPFPackageDocument, opfURL: URL) -> [EPUBTableOfContentsItem] {
|
||||
let opfDirectoryURL = opfURL.deletingLastPathComponent()
|
||||
|
||||
@@ -23,6 +31,7 @@ extension RDEPUBParser {
|
||||
return spine.map { EPUBTableOfContentsItem(title: $0.title, href: $0.href) }
|
||||
}
|
||||
|
||||
/// 解析 NCX(EPUB 2)目录文件
|
||||
func parseNCXDocumentItems(at ncxURL: URL) -> [EPUBTableOfContentsItem] {
|
||||
guard FileManager.default.fileExists(atPath: ncxURL.path),
|
||||
let parser = XMLParser(contentsOf: ncxURL) else {
|
||||
@@ -40,6 +49,7 @@ extension RDEPUBParser {
|
||||
return delegate.items
|
||||
}
|
||||
|
||||
/// 解析 Navigation Document(EPUB 3)目录文件
|
||||
func parseNavDocumentItems(at navURL: URL, baseURL: URL) -> [EPUBTableOfContentsItem] {
|
||||
guard FileManager.default.fileExists(atPath: navURL.path),
|
||||
let parser = XMLParser(contentsOf: navURL) else {
|
||||
@@ -57,6 +67,7 @@ extension RDEPUBParser {
|
||||
return delegate.items
|
||||
}
|
||||
|
||||
/// 标准化目录 href(拆分路径和 fragment,对路径部分做相对路径解析)
|
||||
func normalizeTOCHref(_ href: String, relativeTo baseURL: URL) -> String? {
|
||||
let components = href.split(separator: "#", maxSplits: 1, omittingEmptySubsequences: false)
|
||||
let pathPart = components.first.map(String.init) ?? href
|
||||
@@ -80,11 +91,13 @@ extension RDEPUBParser {
|
||||
}
|
||||
}
|
||||
|
||||
/// 目录树节点,存储标题、href 和子节点,最终转换为 EPUBTableOfContentsItem
|
||||
private final class TOCNode {
|
||||
var title = ""
|
||||
var href: String?
|
||||
var children: [TOCNode] = []
|
||||
|
||||
/// 将节点及其子节点递归转换为目录项
|
||||
func asItem() -> EPUBTableOfContentsItem? {
|
||||
let trimmedTitle = title.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard let href, !href.isEmpty else {
|
||||
@@ -98,10 +111,14 @@ private final class TOCNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// 目录树构建器:通过 beginNode/endNode 操作维护节点栈,构建嵌套目录结构
|
||||
private final class TOCTreeBuilder {
|
||||
/// 当前嵌套路径上的节点栈
|
||||
private var nodeStack: [TOCNode] = []
|
||||
/// 顶层根节点列表
|
||||
private var rootNodes: [TOCNode] = []
|
||||
|
||||
/// 获取构建完成的目录项列表
|
||||
var items: [EPUBTableOfContentsItem] {
|
||||
rootNodes.compactMap { $0.asItem() }
|
||||
}
|
||||
@@ -134,6 +151,7 @@ private final class TOCTreeBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// NCX 文档的 SAX 解析代理,解析 <navPoint>、<content>、<text> 元素
|
||||
private final class NCXParserDelegate: NSObject, XMLParserDelegate {
|
||||
private let baseURL: URL
|
||||
private let hrefNormalizer: (String, URL) -> String?
|
||||
@@ -198,6 +216,7 @@ private final class NCXParserDelegate: NSObject, XMLParserDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/// Navigation Document 的 SAX 解析代理,解析含 epub:type="toc" 的 <nav> 元素
|
||||
private final class NavDocumentParserDelegate: NSObject, XMLParserDelegate {
|
||||
private let baseURL: URL
|
||||
private let hrefNormalizer: (String, URL) -> String?
|
||||
@@ -284,6 +303,7 @@ private final class NavDocumentParserDelegate: NSObject, XMLParserDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
/// 判断 <nav> 元素是否为 TOC 导航(检查 epub:type、type、role 属性)
|
||||
private func isTOCNav(attributes: [String: String]) -> Bool {
|
||||
if let epubType = attributes["epub:type"]?.lowercased(), epubType.contains("toc") {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user