Last active
March 11, 2022 06:37
-
-
Save lalkrishna/5157819288933eddf48465bb1a12d37c to your computer and use it in GitHub Desktop.
Build AttributedString from HTML String content. Fonts can be linked locally.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// HTMLBuilder.swift | |
// HTMLBuilder | |
// | |
// Created by Lal Krishna on 11/03/22. | |
// Copyright © 2022 Lal Krishna. All rights reserved. | |
// | |
import Foundation | |
import UIKit | |
extension HTMLBuilder { | |
static func `default`() -> Self { | |
let font = UIFont.appFont(style: .regular, ofSize: 22) | |
let fontFaces = [ | |
font.fontName: font.fontName + ".ttf" | |
] | |
let builder = HTMLBuilder(defaultFontName: font.fontName, fontFaces: fontFaces) | |
return builder | |
} | |
} | |
struct HTMLBuilder { | |
let css: String | |
typealias FontName = String | |
typealias FontFileName = String | |
/// Key-value pair | |
/// Example: `[ "Arial-Bold": "Arial_Bold.ttf"` | |
var fontFaces: [FontName: FontFileName] | |
private var bodyContent: String = "" | |
init(defaultFontName: String, fontFaces: [FontName: FontFileName]? = nil, css: String? = nil) { | |
self.fontFaces = fontFaces ?? [:] | |
self.css = css ?? Self.defaultCSS(defaultFontName: defaultFontName) | |
} | |
private var attributedText: NSAttributedString? { | |
let htmlContent = html | |
let htmlData = NSString(string: htmlContent).data(using: String.Encoding.unicode.rawValue) | |
let options = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html] | |
let attributedString = try? NSAttributedString(data: htmlData!, options: options, documentAttributes: nil) | |
return attributedString | |
} | |
mutating func buildAttributedString(_ htmlContent: String, color: UIColor? = nil) -> NSAttributedString? { | |
self.bodyContent = htmlContent | |
guard let attributed = attributedText else { return nil } | |
guard let color = color else { return attributed } | |
let mutable = NSMutableAttributedString(attributedString: attributed) | |
mutable.addAttributes([.foregroundColor: color], range: .init(location: 0, length: attributed.length)) | |
return mutable | |
} | |
var html: String { | |
""" | |
<html> | |
\(head) | |
<body> | |
\(bodyContent) | |
</body> | |
</html> | |
""" | |
} | |
var head: String { | |
""" | |
</head> | |
\(style) | |
</head> | |
""" | |
} | |
var style: String { | |
""" | |
<style> | |
\(fontFacesCSS) | |
\(css) | |
</style> | |
""" | |
} | |
private static func defaultCSS(defaultFontName: String) -> String { | |
""" | |
body { | |
font-family: '\(defaultFontName)'; | |
line-height: 1.6; | |
} | |
""" | |
} | |
// var css = buildFontFaces() | |
// let linkCSS = #"<link rel="stylesheet" type="text/css" href="productDescriptionStyle.css">"# | |
var fontFacesCSS: String { | |
fontFaces.reduce("") { $0 + "\n" + Self.fontFace(name: $1.key, path: $1.value) } | |
} | |
mutating func addFontFace(name: String, path: String) { | |
fontFaces[name] = path | |
} | |
private static func fontFace(name: String, path: String) -> String { | |
""" | |
@font-face { | |
font-family: '\(name)'; | |
src: local('\(name)'),url('\(path)')'); | |
} | |
""" | |
} | |
} | |
// Usage | |
// HTMLBuilder.default().buildAttributedString(htmlContentString, color: UIColor.red) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment