Epub阅读器0.0.1
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import Foundation
|
||||
|
||||
public final class RDEPUBResourceResolver {
|
||||
private let parser: RDEPUBParser
|
||||
|
||||
public init(parser: RDEPUBParser) {
|
||||
self.parser = parser
|
||||
}
|
||||
|
||||
public var opfDirectoryURL: URL? {
|
||||
parser.opfDirectoryURL
|
||||
}
|
||||
|
||||
public func fileURL(forRelativePath relativePath: String) -> URL? {
|
||||
parser.fileURL(forRelativePath: relativePath)
|
||||
}
|
||||
|
||||
public func resourceURL(forRelativePath relativePath: String) -> URL? {
|
||||
parser.resourceURL(forRelativePath: relativePath)
|
||||
}
|
||||
|
||||
public func fileURL(forResourceURL resourceURL: URL) -> URL? {
|
||||
parser.fileURL(forResourceURL: resourceURL)
|
||||
}
|
||||
|
||||
public func normalizedHref(_ href: String, relativeToSpineIndex spineIndex: Int? = nil) -> String? {
|
||||
guard let opfDirectoryURL else {
|
||||
return href.components(separatedBy: "#").first
|
||||
}
|
||||
|
||||
let pathPart = href.components(separatedBy: "#").first ?? href
|
||||
if pathPart.isEmpty {
|
||||
guard let spineIndex, parser.spine.indices.contains(spineIndex) else {
|
||||
return nil
|
||||
}
|
||||
return parser.spine[spineIndex].href.components(separatedBy: "#").first
|
||||
}
|
||||
|
||||
let baseURL: URL
|
||||
if let spineIndex, parser.spine.indices.contains(spineIndex) {
|
||||
baseURL = opfDirectoryURL
|
||||
.appendingPathComponent(parser.spine[spineIndex].href)
|
||||
.deletingLastPathComponent()
|
||||
} else {
|
||||
baseURL = opfDirectoryURL
|
||||
}
|
||||
|
||||
guard let resolvedURL = URL(string: pathPart, relativeTo: baseURL)?.standardizedFileURL else {
|
||||
return pathPart
|
||||
}
|
||||
|
||||
let opfPath = opfDirectoryURL.standardizedFileURL.path + "/"
|
||||
let resolvedPath = resolvedURL.path
|
||||
if resolvedPath.hasPrefix(opfPath) {
|
||||
return String(resolvedPath.dropFirst(opfPath.count))
|
||||
}
|
||||
return pathPart
|
||||
}
|
||||
|
||||
public func normalizedLocation(
|
||||
_ location: RDEPUBLocation,
|
||||
relativeToSpineIndex spineIndex: Int? = nil,
|
||||
bookIdentifier: String?
|
||||
) -> RDEPUBLocation? {
|
||||
let rawHref = location.href
|
||||
let hrefParts = rawHref.split(separator: "#", maxSplits: 1, omittingEmptySubsequences: false)
|
||||
let pathPart = hrefParts.first.map(String.init) ?? rawHref
|
||||
let fragment = location.fragment ?? (hrefParts.count > 1 ? String(hrefParts[1]) : nil)
|
||||
|
||||
let normalizedTargetHref: String
|
||||
if pathPart.isEmpty {
|
||||
guard let spineIndex, parser.spine.indices.contains(spineIndex) else {
|
||||
return nil
|
||||
}
|
||||
normalizedTargetHref = parser.spine[spineIndex].href.components(separatedBy: "#").first ?? parser.spine[spineIndex].href
|
||||
} else {
|
||||
guard let href = normalizedHref(pathPart, relativeToSpineIndex: spineIndex) else {
|
||||
return nil
|
||||
}
|
||||
normalizedTargetHref = href
|
||||
}
|
||||
|
||||
return RDEPUBLocation(
|
||||
bookIdentifier: bookIdentifier,
|
||||
href: normalizedTargetHref,
|
||||
progression: location.progression,
|
||||
lastProgression: location.lastProgression,
|
||||
fragment: fragment
|
||||
)
|
||||
}
|
||||
|
||||
public func spineIndex(forNormalizedHref normalizedHref: String) -> Int? {
|
||||
parser.spine.firstIndex { item in
|
||||
self.normalizedHref(item.href) == normalizedHref
|
||||
}
|
||||
}
|
||||
|
||||
public func spineIndex(for location: RDEPUBLocation) -> Int? {
|
||||
guard let normalizedHref = normalizedHref(location.href) else {
|
||||
return nil
|
||||
}
|
||||
return spineIndex(forNormalizedHref: normalizedHref)
|
||||
}
|
||||
|
||||
public func href(forSpineIndex spineIndex: Int) -> String? {
|
||||
guard parser.spine.indices.contains(spineIndex) else {
|
||||
return nil
|
||||
}
|
||||
return parser.spine[spineIndex].href
|
||||
}
|
||||
|
||||
public func title(forSpineIndex spineIndex: Int) -> String? {
|
||||
guard parser.spine.indices.contains(spineIndex) else {
|
||||
return nil
|
||||
}
|
||||
return parser.spine[spineIndex].title
|
||||
}
|
||||
|
||||
public func manifestItem(forHref href: String) -> RDEPUBManifestItem? {
|
||||
let targetHref = normalizedHref(href) ?? href.components(separatedBy: "#").first ?? href
|
||||
return parser.manifest.values.first {
|
||||
normalizedHref($0.href) == targetHref
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user