chore: checkpoint current milestone work
This commit is contained in:
@@ -1,5 +1,15 @@
|
||||
import UIKit
|
||||
|
||||
public struct RDEPUBTextChapterPaginationDiagnostic: Equatable {
|
||||
public var href: String
|
||||
public var title: String
|
||||
public var pageCount: Int
|
||||
public var breakReasons: [RDEPUBTextPageBreakReason]
|
||||
public var attachmentPageCount: Int
|
||||
public var blockAdjustedPageCount: Int
|
||||
public var sampleNotes: [String]
|
||||
}
|
||||
|
||||
public struct RDEPUBTextPage: Equatable {
|
||||
public var absolutePageIndex: Int
|
||||
public var chapterIndex: Int
|
||||
@@ -12,6 +22,7 @@ public struct RDEPUBTextPage: Equatable {
|
||||
public var contentRange: NSRange
|
||||
public var pageStartOffset: Int
|
||||
public var pageEndOffset: Int
|
||||
public var metadata: RDEPUBTextPageMetadata
|
||||
}
|
||||
|
||||
public struct RDEPUBTextChapter: Equatable {
|
||||
@@ -21,6 +32,7 @@ public struct RDEPUBTextChapter: Equatable {
|
||||
public var title: String
|
||||
public var attributedContent: NSAttributedString
|
||||
public var fragmentOffsets: [String: Int]
|
||||
public var pageBreakReasons: [RDEPUBTextPageBreakReason]
|
||||
public var pages: [RDEPUBTextPage]
|
||||
}
|
||||
|
||||
@@ -80,6 +92,8 @@ public struct RDEPUBTextBook: Equatable {
|
||||
|
||||
public final class RDEPUBTextBookBuilder {
|
||||
private let renderer: RDEPUBTextRenderer
|
||||
public private(set) var lastBuildResourceDiagnostics: [RDEPUBTextResourceReferenceDiagnostic] = []
|
||||
public private(set) var lastBuildPaginationDiagnostics: [RDEPUBTextChapterPaginationDiagnostic] = []
|
||||
|
||||
public init(renderer: RDEPUBTextRenderer) {
|
||||
self.renderer = renderer
|
||||
@@ -97,6 +111,8 @@ public final class RDEPUBTextBookBuilder {
|
||||
) throws -> RDEPUBTextBook {
|
||||
var chapters: [RDEPUBTextChapter] = []
|
||||
var flatPages: [RDEPUBTextPage] = []
|
||||
lastBuildResourceDiagnostics = []
|
||||
lastBuildPaginationDiagnostics = []
|
||||
|
||||
for (spineIndex, item) in publication.spine.enumerated() where item.linear {
|
||||
guard item.mediaType.contains("html") || item.mediaType.contains("xhtml"),
|
||||
@@ -105,12 +121,16 @@ public final class RDEPUBTextBookBuilder {
|
||||
}
|
||||
|
||||
let chapterTitle = resolvedChapterTitle(for: item, toc: publication.tableOfContents)
|
||||
let normalizedHTML = normalizeHTML(rawHTML)
|
||||
let rendered = try renderer.renderChapter(
|
||||
html: normalizedHTML,
|
||||
let request = RDEPUBTextRendererSupport.makeChapterRenderRequest(
|
||||
href: item.href,
|
||||
title: chapterTitle,
|
||||
rawHTML: rawHTML,
|
||||
baseURL: parser.fileURL(forRelativePath: item.href)?.deletingLastPathComponent(),
|
||||
style: style
|
||||
style: style,
|
||||
resourceResolver: publication.resourceResolver
|
||||
)
|
||||
let rendered = try renderer.renderChapter(request: request)
|
||||
lastBuildResourceDiagnostics.append(contentsOf: rendered.resourceDiagnostics)
|
||||
|
||||
let plainText = rendered.attributedString.string.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if shouldSkipChapter(item: item, text: plainText) {
|
||||
@@ -119,24 +139,41 @@ public final class RDEPUBTextBookBuilder {
|
||||
|
||||
let chapterIndex = chapters.count
|
||||
let content = NSMutableAttributedString(attributedString: rendered.attributedString)
|
||||
let pageRanges = content.length > 0 ? content.ss_pageRanges(size: pageSize) : []
|
||||
let effectivePageRanges = pageRanges.isEmpty && content.length > 0
|
||||
? [NSRange(location: 0, length: content.length)]
|
||||
: pageRanges
|
||||
let layoutFrames = content.length > 0
|
||||
? content.rd_paginatedFrames(size: pageSize, fragmentOffsets: rendered.fragmentOffsets)
|
||||
: []
|
||||
let effectiveFrames = layoutFrames.isEmpty && content.length > 0
|
||||
? [
|
||||
RDEPUBTextLayoutFrame(
|
||||
contentRange: NSRange(location: 0, length: content.length),
|
||||
breakReason: .chapterEnd,
|
||||
blockRange: nil,
|
||||
attachmentRanges: [],
|
||||
attachmentKinds: [],
|
||||
trailingFragmentID: nil,
|
||||
diagnostics: [
|
||||
"page break: chapterEnd",
|
||||
"page range: \(NSStringFromRange(NSRange(location: 0, length: content.length)))"
|
||||
]
|
||||
)
|
||||
]
|
||||
: layoutFrames
|
||||
|
||||
let pages = effectivePageRanges.enumerated().map { localPageIndex, range in
|
||||
RDEPUBTextPage(
|
||||
let pages = effectiveFrames.enumerated().map { localPageIndex, frame in
|
||||
let range = frame.contentRange
|
||||
return RDEPUBTextPage(
|
||||
absolutePageIndex: flatPages.count + localPageIndex,
|
||||
chapterIndex: chapterIndex,
|
||||
spineIndex: spineIndex,
|
||||
href: item.href,
|
||||
chapterTitle: chapterTitle,
|
||||
pageIndexInChapter: localPageIndex,
|
||||
totalPagesInChapter: effectivePageRanges.count,
|
||||
totalPagesInChapter: effectiveFrames.count,
|
||||
content: content.attributedSubstring(from: range),
|
||||
contentRange: range,
|
||||
pageStartOffset: range.location,
|
||||
pageEndOffset: range.location + max(range.length - 1, 0)
|
||||
pageEndOffset: range.location + max(range.length - 1, 0),
|
||||
metadata: frame.metadata
|
||||
)
|
||||
}
|
||||
|
||||
@@ -148,9 +185,25 @@ public final class RDEPUBTextBookBuilder {
|
||||
title: chapterTitle,
|
||||
attributedContent: content.copy() as! NSAttributedString,
|
||||
fragmentOffsets: rendered.fragmentOffsets,
|
||||
pageBreakReasons: pages.map(\.metadata.breakReason),
|
||||
pages: pages
|
||||
)
|
||||
)
|
||||
lastBuildPaginationDiagnostics.append(
|
||||
RDEPUBTextChapterPaginationDiagnostic(
|
||||
href: item.href,
|
||||
title: chapterTitle,
|
||||
pageCount: pages.count,
|
||||
breakReasons: pages.map(\.metadata.breakReason),
|
||||
attachmentPageCount: pages.filter { !$0.metadata.attachmentKinds.isEmpty }.count,
|
||||
blockAdjustedPageCount: pages.filter { $0.metadata.breakReason == .blockBoundary || $0.metadata.breakReason == .attachmentBoundary }.count,
|
||||
sampleNotes: Array(
|
||||
pages
|
||||
.flatMap(\.metadata.diagnostics)
|
||||
.prefix(4)
|
||||
)
|
||||
)
|
||||
)
|
||||
flatPages.append(contentsOf: pages)
|
||||
}
|
||||
|
||||
@@ -180,26 +233,4 @@ public final class RDEPUBTextBookBuilder {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func normalizeHTML(_ html: String) -> String {
|
||||
var cleanedHTML = html
|
||||
let replacements: [(pattern: String, template: String)] = [
|
||||
(#"<hr\s+lang="zh-CN">分页符</hr>"#, ""),
|
||||
(#"\r"#, "\n"),
|
||||
(#"\n+"#, "\n")
|
||||
]
|
||||
|
||||
for replacement in replacements {
|
||||
if let regex = try? NSRegularExpression(pattern: replacement.pattern, options: [.caseInsensitive]) {
|
||||
cleanedHTML = regex.stringByReplacingMatches(
|
||||
in: cleanedHTML,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: cleanedHTML.utf16.count),
|
||||
withTemplate: replacement.template
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return cleanedHTML
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user