ReadKeep/readeck/Domain/Model/FontFamily.swift
Ilyas Hallak 997d740597 fix: Replace local() with url() for WKWebView font loading
Fix custom fonts not displaying in WKWebView by replacing CSS `src: local()`
with `src: url()` using bundle file paths. WKWebView cannot resolve fonts via
local() even when registered in Info.plist UIAppFonts.

Changes:
- Add fontFileNames and cssFontFamily properties to FontFamily enum
- Implement generateFontFaceCSS() helper in WebView.swift and NativeWebView.swift
- Generate @font-face CSS with file:// URLs for all 12 font files
- Fonts are now dynamically loaded from FontFamily enum (single source of truth)

Affected fonts:
- Literata (Regular, Bold)
- Merriweather (Regular, Bold)
- Source Serif 4 (Regular, Bold)
- Lato (Regular, Bold)
- Montserrat (Regular, Bold)
- Source Sans 3 (Regular, Bold)
2025-12-19 21:31:01 +01:00

133 lines
3.8 KiB
Swift

//
// FontFamily.swift
// readeck
//
// Created by Ilyas Hallak on 06.11.25.
//
enum FontFamily: String, CaseIterable {
// Apple System Fonts
case system = "system" // SF Pro
case newYork = "newYork" // New York
case avenirNext = "avenirNext" // Avenir Next
case monospace = "monospace" // SF Mono
// Google Serif Fonts
case literata = "literata"
case merriweather = "merriweather"
case sourceSerif = "sourceSerif"
// Google Sans Serif Fonts
case lato = "lato"
case montserrat = "montserrat"
case sourceSans = "sourceSans"
// Legacy (for backwards compatibility)
case serif = "serif"
case sansSerif = "sansSerif"
var displayName: String {
switch self {
// Apple
case .system: return "SF Pro"
case .newYork: return "New York"
case .avenirNext: return "Avenir Next"
case .monospace: return "SF Mono"
// Serif
case .literata: return "Literata *"
case .merriweather: return "Merriweather *"
case .sourceSerif: return "Source Serif *"
// Sans Serif
case .lato: return "Lato"
case .montserrat: return "Montserrat"
case .sourceSans: return "Source Sans *"
// Legacy
case .serif: return "Serif (Legacy)"
case .sansSerif: return "Sans Serif (Legacy)"
}
}
var category: FontCategory {
switch self {
case .system, .avenirNext, .lato, .montserrat, .sourceSans, .sansSerif:
return .sansSerif
case .newYork, .literata, .merriweather, .sourceSerif, .serif:
return .serif
case .monospace:
return .monospace
}
}
var isReadeckWebMatch: Bool {
switch self {
case .literata, .merriweather, .sourceSerif, .sourceSans:
return true
default:
return false
}
}
/// Returns the font file names (without extension) for this font family
/// These correspond to the files listed in Info.plist under UIAppFonts
var fontFileNames: [(fileName: String, weight: String)]? {
switch self {
case .literata:
return [
("Literata-Regular", "normal"),
("Literata-Bold", "bold")
]
case .merriweather:
return [
("Merriweather-Regular", "normal"),
("Merriweather-Bold", "bold")
]
case .sourceSerif:
return [
("SourceSerif4-Regular", "normal"),
("SourceSerif4-Bold", "bold")
]
case .lato:
return [
("Lato-Regular", "normal"),
("Lato-Bold", "bold")
]
case .montserrat:
return [
("Montserrat-Regular", "normal"),
("Montserrat-Bold", "bold")
]
case .sourceSans:
return [
("SourceSans3-Regular", "normal"),
("SourceSans3-Bold", "bold")
]
// System fonts don't need to be loaded via @font-face
case .system, .newYork, .avenirNext, .monospace, .serif, .sansSerif:
return nil
}
}
/// Returns the CSS font-family name used in @font-face declarations
var cssFontFamily: String? {
switch self {
case .literata: return "Literata"
case .merriweather: return "Merriweather"
case .sourceSerif: return "Source Serif 4"
case .lato: return "Lato"
case .montserrat: return "Montserrat"
case .sourceSans: return "Source Sans 3"
// System fonts don't need CSS font-family names
case .system, .newYork, .avenirNext, .monospace, .serif, .sansSerif:
return nil
}
}
}
enum FontCategory {
case serif
case sansSerif
case monospace
}