Files
ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBParser+ReadingProfile.swift
T
shenandshen 54798ba578 refactor: 添加中文注释 + 优化模块结构
- 给全部 78 个 Swift 源文件添加详细的中文注释(文件级、类级、方法级)
- 删除 LegacyRDReaderController/ 死代码目录(16 文件 4592 行)
- 根目录翻页容器文件移入 ReaderView/ 目录
- Resources/ 移入 EPUBCore/Resources/(与使用者归属一致)
- RDEPUBTextIndexTable.swift 移入 EPUBTextRendering/(消除反向依赖)
- RDURLReaderController.swift 移入 EPUBUI/(入口控制器归入 UI 层)
- 更新 podspec 资源路径
2026-05-25 10:19:14 +08:00

46 lines
1.9 KiB
Swift

// RDEPUBParser+ReadingProfile.swift
// EPUB 阅读配置文件判断
// 根据 metadata 的 layout 属性和 manifest/spine 内容,
// 将出版物分类为 webFixedLayout(固定版式)、webInteractive(含脚本/多媒体)或 textReflowable(纯文本重排)。
import Foundation
extension RDEPUBParser {
/// 判断出版物的阅读配置文件
/// 优先判断固定版式,其次检测交互内容(脚本/iframe/视频等),默认为文本重排
public func readingProfile() -> RDEPUBReadingProfile {
if metadata.layout == .fixed {
return .webFixedLayout
}
return hasInteractiveContent() ? .webInteractive : .textReflowable
}
/// 检测出版物是否包含交互内容
/// 通过 manifest 中的脚本媒体类型和 "scripted" 属性,
/// 以及扫描 HTML 中的 script/iframe/video/audio/canvas/svg/form 等标签
public func hasInteractiveContent() -> Bool {
let interactiveMediaTypes = [
"application/javascript",
"text/javascript",
"application/ecmascript"
]
if manifest.values.contains(where: { item in
interactiveMediaTypes.contains(item.mediaType.lowercased()) || item.properties.contains("scripted")
}) {
return true
}
let interactivePattern = #"<(script|iframe|video|audio|canvas|svg|form)\b|\bon(load|click|touchstart|touchend|mouseover)=|hype_generated_script|swiper|webview"#
for item in spine where item.linear && (item.mediaType.contains("html") || item.mediaType.contains("xhtml")) {
guard let html = htmlString(forRelativePath: item.href) else {
continue
}
if html.range(of: interactivePattern, options: [.regularExpression, .caseInsensitive]) != nil {
return true
}
}
return false
}
}