feat: EPUB阅读器搜索、注释、CFI模块及大书远距跳转优化
- 实现EPUB阅读器搜索功能及选中注释功能 - 优化CFI模块,修复代码审查发现的11个问题 - 实现大书远距目录跳转与后台补全优化方案 - 优化设置面板与章节运行时联动 - 重构及大量改进优化
This commit is contained in:
@@ -1,71 +1,45 @@
|
||||
//
|
||||
// RDEPUBModels.swift
|
||||
// RDReaderView
|
||||
//
|
||||
// EPUBCore 层核心数据模型定义文件。
|
||||
// 包含 EPUB 解析过程中所需的全部基础枚举和数据结构:
|
||||
// 布局类型、阅读方向、页面分布、元数据、清单项、Spine 项、目录项及解析错误类型。
|
||||
// 这些模型由 RDEPUBParser 解析后填充,并由 RDEPUBPublication 聚合对外暴露。
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// EPUB 版面布局类型
|
||||
/// - reflowable: 可重排布局,内容根据屏幕尺寸和字号自动分页(小说类 EPUB)
|
||||
/// - fixed: 固定版式布局,页面尺寸固定不变(漫画、绘本类 EPUB)
|
||||
public enum RDEPUBLayout: String, Codable {
|
||||
case reflowable
|
||||
case fixed
|
||||
}
|
||||
|
||||
/// 阅读配置文件类型,决定使用哪种渲染路径
|
||||
/// - webInteractive: 可重排 + 含交互脚本,使用 WKWebView 渲染
|
||||
/// - webFixedLayout: 固定版式 EPUB(漫画、绘本),使用 WKWebView 渲染
|
||||
/// - textReflowable: 纯文本可重排 EPUB,使用 DTCoreText 渲染(性能更优)
|
||||
public enum RDEPUBReadingProfile: String, Codable {
|
||||
case webInteractive
|
||||
case webFixedLayout
|
||||
case textReflowable
|
||||
}
|
||||
|
||||
/// 阅读方向(文字排版方向)
|
||||
/// - ltr: 从左到右(英文、中文横排)
|
||||
/// - rtl: 从右到左(日文竖排、阿拉伯文)
|
||||
/// - auto: 根据语言自动判断
|
||||
public enum RDEPUBReadingProgression: String, Codable {
|
||||
case ltr
|
||||
case rtl
|
||||
case auto
|
||||
}
|
||||
|
||||
/// 固定版式页面在 spread(双页展开)中的位置
|
||||
/// - left: 左页
|
||||
/// - right: 右页
|
||||
/// - center: 居中(跨页或单页居中)
|
||||
public enum RDEPUBPageSpread: String, Codable {
|
||||
case left
|
||||
case right
|
||||
case center
|
||||
}
|
||||
|
||||
/// EPUB 出版物元数据,对应 OPF 文档中 <metadata> 节点的内容
|
||||
/// 包含书籍的基本信息:标识符、标题、作者、语言、版本、布局类型等
|
||||
public struct RDEPUBMetadata: Codable, Equatable {
|
||||
/// 书籍唯一标识符(对应 <dc:identifier>)
|
||||
|
||||
public var identifier: String?
|
||||
/// 书名(对应 <dc:title>)
|
||||
|
||||
public var title: String
|
||||
/// 作者(对应 <dc:creator>)
|
||||
|
||||
public var author: String?
|
||||
/// 语言代码(对应 <dc:language>,如 "zh"、"en")
|
||||
|
||||
public var language: String?
|
||||
/// EPUB 版本号(如 "2.0"、"3.0")
|
||||
|
||||
public var version: String?
|
||||
/// 版面布局类型(reflowable 或 fixed)
|
||||
|
||||
public var layout: RDEPUBLayout
|
||||
/// spread 模式设置(对应 <meta property="rendition:spread">)
|
||||
|
||||
public var spread: String?
|
||||
/// 阅读方向(ltr / rtl / auto)
|
||||
|
||||
public var readingProgression: RDEPUBReadingProgression
|
||||
|
||||
public init(
|
||||
@@ -89,22 +63,20 @@ public struct RDEPUBMetadata: Codable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// EPUB 清单项,对应 OPF 文档 <manifest> 中的每个 <item>
|
||||
/// 描述一个资源文件的 ID、路径、MIME 类型和附加属性
|
||||
public struct RDEPUBManifestItem: Codable, Equatable {
|
||||
/// 清单项的唯一标识符(对应 <item id="...">)
|
||||
|
||||
public var id: String
|
||||
/// 资源文件路径,相对于 OPF 文件所在目录
|
||||
|
||||
public var href: String
|
||||
/// MIME 类型(如 "application/xhtml+xml"、"image/jpeg"、"text/css")
|
||||
|
||||
public var mediaType: String
|
||||
/// 属性列表(如 "nav" 表示导航文档、"scripted" 表示含脚本、"cover-image" 表示封面)
|
||||
|
||||
public var properties: [String]
|
||||
/// 回退项 ID(对应 <item fallback="...">)
|
||||
|
||||
public var fallback: String?
|
||||
/// 媒体叠加文件 ID(EPUB 3 有声书功能)
|
||||
|
||||
public var mediaOverlay: String?
|
||||
/// 资源标题(用于搜索结果展示等辅助用途)
|
||||
|
||||
public var title: String?
|
||||
|
||||
public init(
|
||||
@@ -125,37 +97,31 @@ public struct RDEPUBManifestItem: Codable, Equatable {
|
||||
self.title = title
|
||||
}
|
||||
|
||||
/// 是否为 EPUB 3 导航文档(Nav Document)
|
||||
/// 通过检查 properties 中是否包含 "nav" 标记判断
|
||||
public var isNavigationDocument: Bool {
|
||||
properties.contains("nav")
|
||||
}
|
||||
|
||||
/// 是否为 NCX 目录文件(EPUB 2 格式)
|
||||
/// 通过 MIME 类型 "application/x-dtbncx+xml" 判断
|
||||
public var isNCX: Bool {
|
||||
mediaType == "application/x-dtbncx+xml"
|
||||
}
|
||||
}
|
||||
|
||||
/// EPUB Spine 项,对应 OPF 文档 <spine> 中的每个 <itemref>
|
||||
/// Spine 定义了阅读器中章节内容的线性阅读顺序
|
||||
public struct RDEPUBSpineItem: Codable, Equatable {
|
||||
/// 对应 manifest 中的 item id(用于关联资源)
|
||||
|
||||
public var idref: String
|
||||
/// 标准化后的资源路径(相对于 OPF 文件所在目录)
|
||||
|
||||
public var href: String
|
||||
/// MIME 类型
|
||||
|
||||
public var mediaType: String
|
||||
/// 章节标题(从目录或 manifest 推断)
|
||||
|
||||
public var title: String
|
||||
/// 是否为线性内容("no" 表示补充材料,不影响主线阅读进度)
|
||||
|
||||
public var linear: Bool
|
||||
/// 属性列表(如 rendition:layout-* 用于单页布局覆盖)
|
||||
|
||||
public var properties: [String]
|
||||
/// 页面在 spread 中的位置偏好(左页/右页/居中)
|
||||
|
||||
public var pageSpread: RDEPUBPageSpread?
|
||||
/// 单页布局覆盖(显式属性可覆盖出版级别的 layout 设置)
|
||||
|
||||
public var layout: RDEPUBLayout?
|
||||
|
||||
public init(
|
||||
@@ -179,14 +145,12 @@ public struct RDEPUBSpineItem: Codable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// EPUB 目录项,支持树形层级结构
|
||||
/// 来源于 NCX 文件(EPUB 2)或 Nav Document(EPUB 3)的解析结果
|
||||
public struct EPUBTableOfContentsItem: Codable, Equatable {
|
||||
/// 目录项标题(显示在目录面板中)
|
||||
|
||||
public var title: String
|
||||
/// 目标资源路径(含可能的 fragment 锚点)
|
||||
|
||||
public var href: String
|
||||
/// 子目录项列表(递归结构,支持多级目录)
|
||||
|
||||
public var children: [EPUBTableOfContentsItem]
|
||||
|
||||
public init(title: String, href: String, children: [EPUBTableOfContentsItem] = []) {
|
||||
@@ -196,23 +160,22 @@ public struct EPUBTableOfContentsItem: Codable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
/// EPUB 解析器错误类型,涵盖从 ZIP 解压到 OPF 解析全链路的异常情况
|
||||
public enum RDEPUBParserError: LocalizedError {
|
||||
/// ZIP 文件无法打开(文件损坏或格式不支持)
|
||||
|
||||
case archiveOpenFailed(URL)
|
||||
/// 缺少 META-INF/container.xml 文件(EPUB 格式不合规)
|
||||
|
||||
case missingContainerXML
|
||||
/// container.xml 中未找到 <rootfile> 元素
|
||||
|
||||
case missingRootFile
|
||||
/// OPF 根文件路径无效(文件不存在)
|
||||
|
||||
case invalidRootFilePath(String)
|
||||
/// XML 解析失败(格式错误或编码问题)
|
||||
|
||||
case invalidXML(URL)
|
||||
/// spine 中引用的 manifest 项不存在(idref 不匹配)
|
||||
|
||||
case missingManifestItem(idref: String)
|
||||
/// 构建完成的 spine 为空(无可阅读的内容)
|
||||
|
||||
case emptySpine
|
||||
/// 归档条目路径包含路径穿越或非法字符
|
||||
|
||||
case invalidArchiveEntryPath(String)
|
||||
|
||||
public var errorDescription: String? {
|
||||
|
||||
Reference in New Issue
Block a user