feat: EPUB阅读器搜索、注释、CFI模块及大书远距跳转优化
- 实现EPUB阅读器搜索功能及选中注释功能 - 优化CFI模块,修复代码审查发现的11个问题 - 实现大书远距目录跳转与后台补全优化方案 - 优化设置面板与章节运行时联动 - 重构及大量改进优化
This commit is contained in:
@@ -1,37 +1,23 @@
|
||||
// RDEPUBSearchEngine.swift
|
||||
// EPUB 全文搜索引擎
|
||||
// 遍历 spine 中的线性 HTML/XHTML 资源,提取纯文本后执行大小写不敏感的关键词搜索,
|
||||
// 返回匹配项列表(含 href、progression、previewText 等)。
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
/// 搜索引擎协议,定义全文搜索接口
|
||||
protocol RDEPUBSearchEngine {
|
||||
/// 执行全文搜索
|
||||
/// - Parameter keyword: 搜索关键词
|
||||
/// - Returns: 匹配结果列表
|
||||
|
||||
func search(keyword: String) -> [RDEPUBSearchMatch]
|
||||
}
|
||||
|
||||
/// HTML 全文搜索引擎实现
|
||||
/// 通过解析 HTML 为纯文本,逐章执行关键词匹配
|
||||
final class RDEPUBHTMLSearchEngine: RDEPUBSearchEngine {
|
||||
/// EPUB 解析器(用于读取 HTML 内容)
|
||||
|
||||
private let parser: RDEPUBParser
|
||||
/// EPUB 出版物(用于遍历 spine 和规范化 href)
|
||||
|
||||
private let publication: RDEPUBPublication
|
||||
|
||||
/// 创建 HTML 全文搜索引擎
|
||||
/// - Parameters:
|
||||
/// - parser: EPUB 解析器(用于读取 HTML 内容)
|
||||
/// - publication: EPUB 出版物(用于遍历 spine 和规范化 href)
|
||||
init(parser: RDEPUBParser, publication: RDEPUBPublication) {
|
||||
self.parser = parser
|
||||
self.publication = publication
|
||||
}
|
||||
|
||||
/// 执行全文搜索:遍历所有线性 spine 项,提取纯文本后匹配关键词
|
||||
func search(keyword: String) -> [RDEPUBSearchMatch] {
|
||||
let normalizedKeyword = keyword.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !normalizedKeyword.isEmpty else {
|
||||
@@ -53,7 +39,6 @@ final class RDEPUBHTMLSearchEngine: RDEPUBSearchEngine {
|
||||
return searchMatches
|
||||
}
|
||||
|
||||
/// 将 HTML 转换为纯文本(优先使用 NSAttributedString,失败时用正则兜底)
|
||||
private func plainText(fromHTML html: String, baseURL: URL?) -> String {
|
||||
guard let data = html.data(using: .utf8) else {
|
||||
return fallbackPlainText(fromHTML: html)
|
||||
@@ -73,7 +58,6 @@ final class RDEPUBHTMLSearchEngine: RDEPUBSearchEngine {
|
||||
return fallbackPlainText(fromHTML: html)
|
||||
}
|
||||
|
||||
/// 兜底方案:用正则去除 HTML 标签并解码 HTML 实体
|
||||
private func fallbackPlainText(fromHTML html: String) -> String {
|
||||
let stripped = html.replacingOccurrences(of: "<[^>]+>", with: " ", options: .regularExpression)
|
||||
return stripped
|
||||
@@ -85,7 +69,6 @@ final class RDEPUBHTMLSearchEngine: RDEPUBSearchEngine {
|
||||
.replacingOccurrences(of: """, with: "\"")
|
||||
}
|
||||
|
||||
/// 在纯文本中查找所有关键词匹配项(大小写不敏感)
|
||||
private func matches(in text: String, href: String, keyword: String) -> [RDEPUBSearchMatch] {
|
||||
let source = text as NSString
|
||||
let fullLength = source.length
|
||||
@@ -127,7 +110,6 @@ final class RDEPUBHTMLSearchEngine: RDEPUBSearchEngine {
|
||||
return results
|
||||
}
|
||||
|
||||
/// 截取匹配位置前后的文本作为预览(前后各 12 个字符)
|
||||
private func previewText(in text: NSString, matchRange: NSRange) -> String {
|
||||
let previewRadius = 12
|
||||
let start = max(matchRange.location - previewRadius, 0)
|
||||
|
||||
Reference in New Issue
Block a user