HTML string to NSAttributed string, Bullet point with sub bullet point issue Swift
Asked Answered
S

0

10

I am converting an HTML string to an NSAttributedstring to set in TextView, while in text, there are bullet points with sub-bullet points. Bullet points are coming correctly but sub-bullet point alignment is changed.

My actual HTML Text is this HTML String

And after converting it to an NSAttributed string it looks something like this After Converting to NSAttributed String

All bullet points are coming with the same indentation.

I have created a String extension to convert an HTML string to an NSAttributed String.

var htmlToAttributedString: NSAttributedString {
        var attributedString = NSMutableAttributedString()
        guard !self.isBlank, let data = data(using: .utf8) else {
            return NSAttributedString(string: "-", attributes: [NSAttributedString.Key.font: AppFonts.sfProTextRegular(size: 14) as Any]) as? NSMutableAttributedString ?? NSMutableAttributedString()
        }
        do {
            attributedString = try NSMutableAttributedString(data: data,
                                                             options: [.documentType: NSAttributedString.DocumentType.html,
                                                                       .characterEncoding:String.Encoding.utf8.rawValue],
                                                             documentAttributes: nil)
            let range = NSRange(location: 0, length: attributedString.length)
            attributedString.enumerateAttribute(NSAttributedString.Key.font, in: range, options: .longestEffectiveRangeNotRequired) { value, range, _ in
                let currentFont: UIFont = value as! UIFont
                var replacementFont: UIFont? = nil
                if currentFont.fontName.contains("bold") || currentFont.fontName.contains("Bold") {
                    replacementFont = AppFonts.sfProTextBold(size: 14)
                } else if currentFont.fontName.contains("italic") || currentFont.fontName.contains("Italic") {
                    replacementFont = AppFonts.sfProTextRegularItalic(size: 14)
                } else {
                    replacementFont = AppFonts.sfProTextRegular(size: 14)
                }
                let replacementAttribute = [NSAttributedString.Key.font:replacementFont!]
                attributedString.addAttributes(replacementAttribute, range: range)
                attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: AppColors.darkTextColor() as Any, range: NSRange(location: 0, length: attributedString.length))
            }
        } catch {
            return NSAttributedString(string: "-", attributes: [NSAttributedString.Key.font: AppFonts.sfProTextRegular(size: 14) as Any]) as? NSMutableAttributedString ?? NSMutableAttributedString()
        }
        return attributedString
    }

This is the HTML string that I am converting to NSAttributed string

" <p>CUSTOMER / PM:</p>
<p>
  <strong style=\"color: rgb(47, 84, 150);\">Abigail Weighell&nbsp;</strong>
  <strong style=\"color: rgb(31, 73, 125);\">|&nbsp;</strong>
  <strong style=\"color: rgb(47, 84, 150);\">Resource Analyst</strong>
</p>
<p>
  <span style=\"color: rgb(47, 84, 150);\">Email:&nbsp;</span>
  <span style=\"color: rgb(5, 99, 193);\">[email protected]</span>
</p>
<p>
  <span style=\"color: rgb(47, 84, 150);\">C: 978-907-4648</span>
</p>
<p>
  <br>
</p>
<p>SITE HOURS:</p>
<ul>
  <li>9:00 AM</li>
  <li>
    <strong>MUST</strong> print out the attached \"Room is under maintenance\" sign before arrival - See notes below
  </li>
  <li class=\"ql-indent-1\">test layer 1</li>
  <li class=\"ql-indent-1\">test layer 1 double</li>
  <li class=\"ql-indent-2\">test layer 2</li>
  <li class=\"ql-indent-3\">test layer 3</li>
</ul>
<p>
  <br>
</p>

I just want my bullet point to be the same as the first image. Could you guys help me out?

Thanks in advance

Surefire answered 29/12, 2022 at 6:16 Comment(12)
Can you show the html ?Jadwiga
@PtitXav I have added HTML code, you can checkSurefire
In fact you do not have sub items. Just items with different style. Do you include the CSS in the string when converting the html to NSAttributedString ?Jadwiga
I have added HTML code which is what I am getting from the API. And I am simply converting it.Surefire
You need to add a style tag in your html to specify how you want the specific classes to be handled by NSAttributedString. As the class (ql-indent-1 ,…) are not specified the frame does not know how to handle the ul tagsJadwiga
The conversion of that HTML to an NSAttributedString is correct since your HTML doesn't actually have nested lists nor do you provide the needed CSS for the style class being referenced. Why not setup your HTML to properly use nested <ul> lists?Mitzimitzie
@PtitXav Okay got it i need to specify HTML ul tags properly.Surefire
@Mitzimitzie Yes i will check with it. Thank you for your answerSurefire
"<p>SITE HOURS:</p><ul><li>9:00 AM</li><li>MUST print out the attached Room is under maintenance sign before arrival - See notes below<ul><li>test layer 1</li><li>test layer 1 double<ul><li>test layer 2<ul><li>test layer 3</li></ul></li></ul></li></ul></li></ul>" I have updated HTML code and added proper nested ul tag, but it not converted after first two bullet point @MitzimitzieSurefire
@Surefire It's working for me. That exact HTML converted to an NSAttributedString and displayed in a UITextView looks just as you would expect it to. You should update your question with sufficient code to demonstrate your issue.Mitzimitzie
@Mitzimitzie I don't know if my current code which I have mentioned in the question is correct. Do I need to add anything else for converting HTML to an NSAttributed string?Surefire
I used your htmlToAttributedString extension (but I commented out the Font enumeration since there is no font in your HTML and I don't have your AppFonts code). Update your question with your latest HTML and your text view code. In other words, post something that someone can copy as-is into a Playground and replicate your issue.Mitzimitzie

© 2022 - 2025 — McMap. All rights reserved.