Skip to content

Instantly share code, notes, and snippets.

@Bigigrammer
Last active December 29, 2022 09:00
Show Gist options
  • Save Bigigrammer/abd36aee7457ad7e1e4cc61466221e30 to your computer and use it in GitHub Desktop.
Save Bigigrammer/abd36aee7457ad7e1e4cc61466221e30 to your computer and use it in GitHub Desktop.
This extension convert HTML to NSAttributedString each other. It works on Swift4.
extension String {
func convertAttributedString() -> NSAttributedString?{
let html = self._removePT()
let encoded = html.data(using: String.Encoding.utf8)!
let attributedOptions : [NSAttributedString.DocumentReadingOptionKey : Any] = [
.documentType : NSAttributedString.DocumentType.html,
.characterEncoding : String.Encoding.utf8.rawValue
]
do {
let attributedTxt = try NSAttributedString(data: encoded, options: attributedOptions, documentAttributes: nil)
let lineHeightFixed = _fixLineHeight(attributedString: attributedTxt)
return lineHeightFixed
}catch let error as NSError {
print(error)
return nil
}
}
fileprivate func _removePT() -> String{
let pattern = "<style(.|\n)*style>"
var ranges: [NSRange] = []
_ = self.pregMatche(pattern: pattern, target: nil, ranges: &ranges)
var targets: [NSRange] = []
ranges.forEach{
var ranges: [NSRange] = []
_ = self.pregMatche(pattern: "font\\-size: \\d*.*pt", target: $0, ranges: &ranges)
targets += ranges
}
let result = targets.reduce(self) { (result, range) -> String in
result.pregReplace(pattern: "pt", with: "px", range: range)
}
return result
}
fileprivate func _fixLineHeight(attributedString: NSAttributedString) -> NSAttributedString{
let mutable = NSMutableAttributedString(attributedString: attributedString)
let range = NSRange(location: 0, length: mutable.string.count)
mutable.enumerateAttribute(.paragraphStyle,
in: range,
options: [.longestEffectiveRangeNotRequired])
{ value, range, isStop in
if let style = value as? NSMutableParagraphStyle {
style.maximumLineHeight = 0
style.minimumLineHeight = 0
style.lineHeightMultiple = 0
mutable.addAttributes([NSAttributedStringKey.paragraphStyle: style], range: range)
}
}
return mutable
}
fileprivate func addCSSStyle(style: String) -> String?{
let pattern = "<\\/style>"
var range: [NSRange] = []
_ = self.pregMatche(pattern: pattern, target: nil, ranges: &range)
guard let styleRange = range.first else {return nil}
let index = self.index(self.startIndex, offsetBy: styleRange.location)
let collection = Array(style)
var mutable = self
mutable.insert(contentsOf: collection, at: index)
return mutable
}
}
extension NSAttributedString{
func convertHTML() -> String?{
let newStyle = "br {display: none;}"
let documentAttributes: [NSAttributedString.DocumentAttributeKey : Any] =
[.documentType: NSAttributedString.DocumentType.html]
do {
let htmlData = try self.data(from: NSRange(location: 0, length: self.length),
documentAttributes: documentAttributes)
guard let html = String(data: htmlData, encoding: .utf8) else {return nil}
let removed = html._removePT()
return removed.addCSSStyle(style: newStyle)
}catch let error as NSError {
print(error)
return nil
}
}
}
// Supporting regular expression
extension String {
func pregMatche(pattern: String, target: NSRange?, options: NSRegularExpression.Options = [], ranges: inout [NSRange]) -> Bool {
guard let regex = try? NSRegularExpression(pattern: pattern, options: options) else {
return false
}
let targetStringRange = target ?? NSRange(location: 0, length: self.count)
let results = regex.matches(in: self, options: [], range: targetStringRange)
for i in 0 ..< results.count {
for j in 0 ..< results[i].numberOfRanges {
let range = results[i].range(at: j)
ranges.append(range)
}
}
return results.count > 0
}
func pregReplace(pattern: String, with: String, range: NSRange, options: NSRegularExpression.Options = []) -> String{
let regex = try! NSRegularExpression(pattern: pattern, options: options)
return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: with)
}
}
@meet-m-simformsolutions
Copy link

meet-m-simformsolutions commented Dec 29, 2022

@Bigigrammer do you have any idea how to manage bullet points with sub-bullet points in them?
I have one case where in the text there are a few bullet points with sub-bullet points in it. After converting it from HTML string to NSAttributed sub-bullet point alignment gets changed.

Let me know if you have any solution for that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment