feat(epub): complete wxread parity scope
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import UIKit
|
||||
import CoreText
|
||||
|
||||
#if canImport(DTCoreText)
|
||||
import DTCoreText
|
||||
@@ -27,6 +28,8 @@ enum RDEPUBTextRendererSupport {
|
||||
private static var didLogFootnoteAttachment = false
|
||||
/// 封面附件日志已输出标记(避免重复日志)
|
||||
private static var didLogCoverAttachment = false
|
||||
/// 已注册字体资源,避免重复调用 CTFontManager。
|
||||
private static var registeredFontPaths = Set<String>()
|
||||
|
||||
// MARK: - Fragment 标记注入/提取
|
||||
|
||||
@@ -209,6 +212,11 @@ enum RDEPUBTextRendererSupport {
|
||||
contentLanguageCode: contentLanguageCode,
|
||||
sourceHTML: rawHTML
|
||||
)
|
||||
registerEmbeddedFonts(
|
||||
in: stylesheetHrefReplacements.inlinedCSS + "\n" + inlineStyleCSS(in: normalizedHTML),
|
||||
chapterHref: href,
|
||||
resourceResolver: resourceResolver
|
||||
)
|
||||
let htmlWithBase = injectBaseHref(into: stylesheetHrefReplacements.html, baseURL: baseURL)
|
||||
let htmlWithDefaultLayers = injectStyleTag(
|
||||
into: htmlWithBase,
|
||||
@@ -327,6 +335,58 @@ enum RDEPUBTextRendererSupport {
|
||||
return RDEPUBAssetRepository.string(for: asset)
|
||||
}
|
||||
|
||||
private static func inlineStyleCSS(in html: String) -> String {
|
||||
guard let regex = try? NSRegularExpression(pattern: #"<style\b[^>]*>([\s\S]*?)</style>"#, options: [.caseInsensitive]) else {
|
||||
return ""
|
||||
}
|
||||
let nsHTML = html as NSString
|
||||
return regex.matches(in: html, range: NSRange(location: 0, length: nsHTML.length))
|
||||
.compactMap { match in
|
||||
guard match.numberOfRanges > 1 else { return nil }
|
||||
return nsHTML.substring(with: match.range(at: 1))
|
||||
}
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
|
||||
private static func registerEmbeddedFonts(
|
||||
in css: String,
|
||||
chapterHref: String,
|
||||
resourceResolver: RDEPUBResourceResolver?
|
||||
) {
|
||||
guard let resourceResolver,
|
||||
let faceRegex = try? NSRegularExpression(pattern: #"@font-face\s*\{([\s\S]*?)\}"#, options: [.caseInsensitive]),
|
||||
let urlRegex = try? NSRegularExpression(pattern: #"url\(([^)]+)\)"#, options: [.caseInsensitive]) else {
|
||||
return
|
||||
}
|
||||
|
||||
let nsCSS = css as NSString
|
||||
for faceMatch in faceRegex.matches(in: css, range: NSRange(location: 0, length: nsCSS.length)) {
|
||||
guard faceMatch.numberOfRanges > 1 else { continue }
|
||||
let block = nsCSS.substring(with: faceMatch.range(at: 1))
|
||||
let nsBlock = block as NSString
|
||||
for urlMatch in urlRegex.matches(in: block, range: NSRange(location: 0, length: nsBlock.length)) {
|
||||
guard urlMatch.numberOfRanges > 1 else { continue }
|
||||
let rawReference = nsBlock.substring(with: urlMatch.range(at: 1))
|
||||
.trimmingCharacters(in: CharacterSet(charactersIn: "\"' \n\r\t"))
|
||||
guard !rawReference.isEmpty,
|
||||
!rawReference.hasPrefix("data:"),
|
||||
!rawReference.hasPrefix("http://"),
|
||||
!rawReference.hasPrefix("https://"),
|
||||
let fileURL = resourceResolver.fileURL(forReference: rawReference, relativeToHref: chapterHref) else {
|
||||
continue
|
||||
}
|
||||
registerFontIfNeeded(at: fileURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func registerFontIfNeeded(at fileURL: URL) {
|
||||
let standardizedPath = fileURL.standardizedFileURL.path
|
||||
guard !registeredFontPaths.contains(standardizedPath) else { return }
|
||||
CTFontManagerRegisterFontsForURL(fileURL as CFURL, .process, nil)
|
||||
registeredFontPaths.insert(standardizedPath)
|
||||
}
|
||||
|
||||
private static func normalizeAttachmentHTMLMarkers(in html: String) -> String {
|
||||
var normalized = html
|
||||
|
||||
|
||||
Reference in New Issue
Block a user