import Foundation enum RDEPUBAsset: String { case rangyCoreScript = "rangy-core" case rangySerializerScript = "rangy-serializer" case cssInjectorScript = "cssInjector" case weReadAPIScript = "WeReadApi" case bridgeScript = "epub-bridge" case fixedLayoutTemplate = "epub-fixed-layout" case wxReadDefaultCSS = "wxread-default" case wxReadReplaceCSS = "wxread-replace" case wxReadDarkCSS = "wxread-dark" case wxReadLatinReplaceCSS = "wxread-replace-latin" var fileExtension: String { switch self { case .rangyCoreScript, .rangySerializerScript, .cssInjectorScript, .weReadAPIScript, .bridgeScript: return "js" case .fixedLayoutTemplate: return "html" case .wxReadDefaultCSS, .wxReadReplaceCSS, .wxReadDarkCSS, .wxReadLatinReplaceCSS: return "css" } } } enum RDEPUBAssetRepository { static func string(for asset: RDEPUBAsset, replacements: [String: String] = [:]) -> String { guard let url = resourceBundle.url(forResource: asset.rawValue, withExtension: asset.fileExtension), var content = try? String(contentsOf: url, encoding: .utf8) else { assertionFailure("Missing EPUB asset: \(asset.rawValue).\(asset.fileExtension)") return "" } for (token, value) in replacements { content = content.replacingOccurrences(of: "{{\(token)}}", with: value) } return content } private static var resourceBundle: Bundle { if let bundle = resolvedBundle { return bundle } return Bundle(for: RDEPUBAssetBundleToken.self) } private static var resolvedBundle: Bundle? = { let hostBundles = [Bundle(for: RDEPUBAssetBundleToken.self), Bundle.main] + Bundle.allFrameworks + Bundle.allBundles for hostBundle in hostBundles { for bundleName in ["RDEpubReaderViewAssets", "RDReaderViewAssets"] { if let url = hostBundle.url(forResource: bundleName, withExtension: "bundle"), let bundle = Bundle(url: url) { return bundle } } } return nil }() } private final class RDEPUBAssetBundleToken {}