feat(07): close native text pagination semantics loop

This commit is contained in:
shen
2026-05-22 20:39:26 +08:00
parent 21c8bbb23a
commit d7339aa255
15 changed files with 722 additions and 22 deletions
@@ -7,6 +7,9 @@ public struct RDEPUBTextChapterPaginationDiagnostic: Equatable {
public var breakReasons: [RDEPUBTextPageBreakReason]
public var attachmentPageCount: Int
public var blockAdjustedPageCount: Int
public var blockKinds: [RDEPUBTextBlockKind]
public var semanticHints: [RDEPUBTextSemanticHint]
public var attachmentPlacements: [RDEPUBTextAttachmentPlacement]
public var sampleNotes: [String]
}
@@ -103,6 +106,29 @@ public final class RDEPUBTextBookBuilder {
self.init(renderer: RDEPUBDTCoreTextRenderer())
}
public func phase7SemanticSummary(title: String? = nil) -> String? {
guard !lastBuildPaginationDiagnostics.isEmpty else { return nil }
let blockKinds = uniqueValues(from: lastBuildPaginationDiagnostics.flatMap(\.blockKinds))
let semanticHints = uniqueValues(from: lastBuildPaginationDiagnostics.flatMap(\.semanticHints))
let attachmentPlacements = uniqueValues(from: lastBuildPaginationDiagnostics.flatMap(\.attachmentPlacements))
let note = lastBuildPaginationDiagnostics
.flatMap(\.sampleNotes)
.first(where: { $0.contains("semantic") || $0.contains("attachment") || $0.contains("block kinds") })
var parts = [
title,
"章节 \(lastBuildPaginationDiagnostics.count)",
blockKinds.isEmpty ? nil : "block kinds [\(blockKinds.map(\.rawValue).joined(separator: ","))]",
semanticHints.isEmpty ? nil : "hints [\(semanticHints.map(\.rawValue).joined(separator: ","))]",
attachmentPlacements.isEmpty ? nil : "placements [\(attachmentPlacements.map(\.rawValue).joined(separator: ","))]"
].compactMap { $0 }
if let note {
parts.append(note)
}
return parts.joined(separator: " · ")
}
public func build(
parser: RDEPUBParser,
publication: RDEPUBPublication,
@@ -150,6 +176,9 @@ public final class RDEPUBTextBookBuilder {
blockRange: nil,
attachmentRanges: [],
attachmentKinds: [],
blockKinds: [],
semanticHints: [],
attachmentPlacements: [],
trailingFragmentID: nil,
diagnostics: [
"page break: chapterEnd",
@@ -197,6 +226,9 @@ public final class RDEPUBTextBookBuilder {
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,
blockKinds: uniqueValues(from: pages.flatMap(\.metadata.blockKinds)),
semanticHints: uniqueValues(from: pages.flatMap(\.metadata.semanticHints)),
attachmentPlacements: uniqueValues(from: pages.flatMap(\.metadata.attachmentPlacements)),
sampleNotes: Array(
pages
.flatMap(\.metadata.diagnostics)
@@ -233,4 +265,12 @@ public final class RDEPUBTextBookBuilder {
}
return false
}
private func uniqueValues<T: Equatable>(from values: [T]) -> [T] {
values.reduce(into: [T]()) { result, value in
if !result.contains(value) {
result.append(value)
}
}
}
}