feat(epub): complete wxread parity scope

This commit is contained in:
shen
2026-05-26 09:19:37 +08:00
parent 23182e8b5a
commit 0e7d952fe5
31 changed files with 2619 additions and 1533 deletions
@@ -0,0 +1,75 @@
import Foundation
/// WXRead `WREpubPositionConverter`
///
///
/// - `(fileIndex, row, column)`
/// -
/// -
/// - / `RDEPUBLocation`
public struct RDEPUBTextPositionConverter {
public let book: RDEPUBTextBook
public init(book: RDEPUBTextBook) {
self.book = book
}
public var totalCharacterCount: Int {
book.indexTable.totalCharacterCount
}
public func globalIndex(for anchor: RDEPUBTextAnchor) -> Int {
book.indexTable.globalIndex(for: anchor)
}
public func globalRange(for rangeAnchor: RDEPUBTextRangeAnchor) -> NSRange {
book.indexTable.globalRange(for: rangeAnchor)
}
public func fileIndex(forCharacterPosition index: Int) -> Int? {
book.indexTable.fileIndex(forCharacterPosition: index)
}
public func localOffsetInFile(at fileIndex: Int, forGlobalPosition index: Int) -> Int? {
book.indexTable.localOffsetInFile(at: fileIndex, forGlobalPosition: index)
}
public func anchor(forCharacterPosition index: Int) -> RDEPUBTextAnchor? {
book.indexTable.anchor(forGlobalIndex: index)
}
public func anchor(for location: RDEPUBLocation) -> RDEPUBTextAnchor? {
book.indexTable.anchor(for: location)
}
public func pageNumber(for anchor: RDEPUBTextAnchor) -> Int? {
book.indexTable.pageNumber(for: anchor, in: book).map { $0 + 1 }
}
public func pageNumber(forCharacterPosition index: Int) -> Int? {
guard let anchor = anchor(forCharacterPosition: index) else {
return nil
}
return pageNumber(for: anchor)
}
public func location(
for anchor: RDEPUBTextAnchor,
bookIdentifier: String?
) -> RDEPUBLocation? {
guard let chapter = book.chapters.first(where: { $0.spineIndex == anchor.fileIndex }) else {
return nil
}
return book.indexTable.location(for: anchor, in: chapter, bookIdentifier: bookIdentifier)
}
public func location(
for rangeAnchor: RDEPUBTextRangeAnchor,
bookIdentifier: String?
) -> RDEPUBLocation? {
guard let chapter = book.chapters.first(where: { $0.spineIndex == rangeAnchor.start.fileIndex }) else {
return nil
}
return book.indexTable.location(for: rangeAnchor, in: chapter, bookIdentifier: bookIdentifier)
}
}