feat: chapter runtime refactoring and related updates
- Refactor chapter runtime: replace window coordinator/snapshot with warmup orchestrator - Update EPUB core: parser, reading session, JS bridge, navigator layout - Update reader controller: data source, location resolution, persistence - Update chapter runtime: data cache, loader, runtime store, disk cache, warmup orchestrator - Remove deprecated navigation state machine and pagination state - Update text rendering: book cache, HTML normalizer - Update UI: text content view, dark image adjuster, text selection controller - Update settings and reader configuration - Add CODE_REVIEW.md and AUDIT_FINAL.md documentation - Update pod dependencies (remove SSAlertSwift, SnapKit) - Update podspec and pod configuration files Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -104,7 +104,7 @@ final class ChapterPaginationArchive: NSObject, NSSecureCoding {
|
||||
|
||||
public final class RDEPUBTextBookCache {
|
||||
|
||||
public var schemaVersion: Int = 13
|
||||
public var schemaVersion: Int = 14
|
||||
|
||||
private let queue = DispatchQueue(label: "com.rdreader.textbookcache", qos: .utility)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ struct RDEPUBHTMLNormalizer: RDEPUBTypesettingStage {
|
||||
}
|
||||
|
||||
cleanedHTML = normalizeAttachmentHTMLMarkers(in: cleanedHTML)
|
||||
cleanedHTML = normalizeBodyLeadingSpacing(in: cleanedHTML)
|
||||
return cleanedHTML
|
||||
}
|
||||
|
||||
@@ -129,6 +130,64 @@ struct RDEPUBHTMLNormalizer: RDEPUBTypesettingStage {
|
||||
return normalized
|
||||
}
|
||||
|
||||
private static func normalizeBodyLeadingSpacing(in html: String) -> String {
|
||||
var normalized = html
|
||||
|
||||
if let bodyStartRegex = try? NSRegularExpression(
|
||||
pattern: #"(<body\b[^>]*>)\s+"#,
|
||||
options: [.caseInsensitive]
|
||||
) {
|
||||
normalized = bodyStartRegex.stringByReplacingMatches(
|
||||
in: normalized,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: (normalized as NSString).length),
|
||||
withTemplate: "$1"
|
||||
)
|
||||
}
|
||||
|
||||
if let bodyEndRegex = try? NSRegularExpression(
|
||||
pattern: #"\s+(</body>)"#,
|
||||
options: [.caseInsensitive]
|
||||
) {
|
||||
normalized = bodyEndRegex.stringByReplacingMatches(
|
||||
in: normalized,
|
||||
options: [],
|
||||
range: NSRange(location: 0, length: (normalized as NSString).length),
|
||||
withTemplate: "$1"
|
||||
)
|
||||
}
|
||||
|
||||
guard let firstBlockRegex = try? NSRegularExpression(
|
||||
pattern: #"(<body\b[^>]*>)(\s*)(<(?<tag>h[1-6]|p|div|blockquote|section|article|ul|ol)\b[^>]*>)"#,
|
||||
options: [.caseInsensitive]
|
||||
) else {
|
||||
return normalized
|
||||
}
|
||||
|
||||
let nsNormalized = normalized as NSString
|
||||
let fullRange = NSRange(location: 0, length: nsNormalized.length)
|
||||
guard let match = firstBlockRegex.firstMatch(in: normalized, options: [], range: fullRange),
|
||||
match.numberOfRanges >= 4,
|
||||
let bodyRange = Range(match.range(at: 1), in: normalized),
|
||||
let blockRange = Range(match.range(at: 3), in: normalized) else {
|
||||
return normalized
|
||||
}
|
||||
|
||||
let prefix = String(normalized[..<bodyRange.lowerBound])
|
||||
let bodyTag = String(normalized[bodyRange])
|
||||
let blockTag = String(normalized[blockRange])
|
||||
let normalizedBlockTag = mergeHTMLAttributes(
|
||||
into: blockTag,
|
||||
requiredClass: nil,
|
||||
styleFragments: [
|
||||
"margin-top:0 !important",
|
||||
"-webkit-margin-before:0 !important",
|
||||
"padding-top:0 !important"
|
||||
]
|
||||
)
|
||||
return prefix + bodyTag + normalizedBlockTag + String(normalized[blockRange.upperBound...])
|
||||
}
|
||||
|
||||
static func replaceMatches(
|
||||
using regex: NSRegularExpression,
|
||||
in source: String,
|
||||
|
||||
Reference in New Issue
Block a user