refactor: rename RDReaderView -> RDEpubReaderView, update pod config and docs
- Rename source module from RDReaderView to RDEpubReaderView - Move all source files from Sources/RDReaderView/ to Sources/RDEpubReaderView/ - Update podspec: RDReaderView.podspec -> RDEpubReaderView.podspec - Update Podfile, demo project, and CocoaPods config for new pod name - Delete old RDReaderView pod support files from ReadViewDemo/Pods - Add new RDEpubReaderView pod support files - Update documentation (API ref, architecture, UML, conventions, etc.) - Add FixedLayoutRotationTests - Update .gitignore: exclude .DS_Store, manual unpack backups, _ssoft-output
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum RDEPUBLayout: String, Codable {
|
||||
case reflowable
|
||||
case fixed
|
||||
}
|
||||
|
||||
public enum RDEPUBReadingProfile: String, Codable {
|
||||
case webInteractive
|
||||
case webFixedLayout
|
||||
case textReflowable
|
||||
}
|
||||
|
||||
public enum RDEPUBReadingProgression: String, Codable {
|
||||
case ltr
|
||||
case rtl
|
||||
case auto
|
||||
}
|
||||
|
||||
public enum RDEPUBPageSpread: String, Codable {
|
||||
case left
|
||||
case right
|
||||
case center
|
||||
}
|
||||
|
||||
/// EPUB 渲染朝向(rendition:orientation / iBooks display-options)。
|
||||
public enum RDEPUBOrientation: String, Codable {
|
||||
case portrait
|
||||
case landscape
|
||||
case auto
|
||||
}
|
||||
|
||||
public struct RDEPUBMetadata: Codable, Equatable {
|
||||
|
||||
public var identifier: String?
|
||||
|
||||
public var title: String
|
||||
|
||||
public var author: String?
|
||||
|
||||
public var language: String?
|
||||
|
||||
public var version: String?
|
||||
|
||||
public var layout: RDEPUBLayout
|
||||
|
||||
public var spread: String?
|
||||
|
||||
public var readingProgression: RDEPUBReadingProgression
|
||||
|
||||
/// 渲染朝向;nil = 未声明(不锁定,跟随系统)。
|
||||
/// 来源优先级:OPF rendition:orientation > META-INF/com.apple.ibooks.display-options.xml。
|
||||
public var orientation: RDEPUBOrientation?
|
||||
|
||||
public init(
|
||||
identifier: String? = nil,
|
||||
title: String = "",
|
||||
author: String? = nil,
|
||||
language: String? = nil,
|
||||
version: String? = nil,
|
||||
layout: RDEPUBLayout = .reflowable,
|
||||
spread: String? = nil,
|
||||
readingProgression: RDEPUBReadingProgression = .auto,
|
||||
orientation: RDEPUBOrientation? = nil
|
||||
) {
|
||||
self.identifier = identifier
|
||||
self.title = title
|
||||
self.author = author
|
||||
self.language = language
|
||||
self.version = version
|
||||
self.layout = layout
|
||||
self.spread = spread
|
||||
self.readingProgression = readingProgression
|
||||
self.orientation = orientation
|
||||
}
|
||||
}
|
||||
|
||||
public struct RDEPUBManifestItem: Codable, Equatable {
|
||||
|
||||
public var id: String
|
||||
|
||||
public var href: String
|
||||
|
||||
public var mediaType: String
|
||||
|
||||
public var properties: [String]
|
||||
|
||||
public var fallback: String?
|
||||
|
||||
public var mediaOverlay: String?
|
||||
|
||||
public var title: String?
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
href: String,
|
||||
mediaType: String,
|
||||
properties: [String] = [],
|
||||
fallback: String? = nil,
|
||||
mediaOverlay: String? = nil,
|
||||
title: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.href = href
|
||||
self.mediaType = mediaType
|
||||
self.properties = properties
|
||||
self.fallback = fallback
|
||||
self.mediaOverlay = mediaOverlay
|
||||
self.title = title
|
||||
}
|
||||
|
||||
public var isNavigationDocument: Bool {
|
||||
properties.contains("nav")
|
||||
}
|
||||
|
||||
public var isNCX: Bool {
|
||||
mediaType == "application/x-dtbncx+xml"
|
||||
}
|
||||
}
|
||||
|
||||
public struct RDEPUBSpineItem: Codable, Equatable {
|
||||
|
||||
public var idref: String
|
||||
|
||||
public var href: String
|
||||
|
||||
public var mediaType: String
|
||||
|
||||
public var title: String
|
||||
|
||||
public var linear: Bool
|
||||
|
||||
public var properties: [String]
|
||||
|
||||
public var pageSpread: RDEPUBPageSpread?
|
||||
|
||||
public var layout: RDEPUBLayout?
|
||||
|
||||
public init(
|
||||
idref: String,
|
||||
href: String,
|
||||
mediaType: String,
|
||||
title: String,
|
||||
linear: Bool = true,
|
||||
properties: [String] = [],
|
||||
pageSpread: RDEPUBPageSpread? = nil,
|
||||
layout: RDEPUBLayout? = nil
|
||||
) {
|
||||
self.idref = idref
|
||||
self.href = href
|
||||
self.mediaType = mediaType
|
||||
self.title = title
|
||||
self.linear = linear
|
||||
self.properties = properties
|
||||
self.pageSpread = pageSpread
|
||||
self.layout = layout
|
||||
}
|
||||
}
|
||||
|
||||
public struct EPUBTableOfContentsItem: Codable, Equatable {
|
||||
|
||||
public var title: String
|
||||
|
||||
public var href: String
|
||||
|
||||
public var children: [EPUBTableOfContentsItem]
|
||||
|
||||
public init(title: String, href: String, children: [EPUBTableOfContentsItem] = []) {
|
||||
self.title = title
|
||||
self.href = href
|
||||
self.children = children
|
||||
}
|
||||
}
|
||||
|
||||
public enum RDEPUBParserError: LocalizedError {
|
||||
|
||||
case archiveOpenFailed(URL)
|
||||
|
||||
case missingContainerXML
|
||||
|
||||
case missingRootFile
|
||||
|
||||
case invalidRootFilePath(String)
|
||||
|
||||
case invalidXML(URL)
|
||||
|
||||
case missingManifestItem(idref: String)
|
||||
|
||||
case emptySpine
|
||||
|
||||
case invalidArchiveEntryPath(String)
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .archiveOpenFailed(let url):
|
||||
return "无法打开 EPUB 压缩包: \(url.lastPathComponent)"
|
||||
case .missingContainerXML:
|
||||
return "EPUB 缺少 META-INF/container.xml"
|
||||
case .missingRootFile:
|
||||
return "container.xml 中未找到 rootfile"
|
||||
case .invalidRootFilePath(let path):
|
||||
return "OPF 路径无效: \(path)"
|
||||
case .invalidXML(let url):
|
||||
return "XML 解析失败: \(url.lastPathComponent)"
|
||||
case .missingManifestItem(let idref):
|
||||
return "spine itemref 找不到对应 manifest 项: \(idref)"
|
||||
case .emptySpine:
|
||||
return "OPF spine 为空"
|
||||
case .invalidArchiveEntryPath(let path):
|
||||
return "归档条目路径非法: \(path)"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user