Home > Blockchain >  Problem in strong tag when Parsing Html in swift 5
Problem in strong tag when Parsing Html in swift 5

Time:02-15

Hi i have a problem when im parsing a Html to NSAtributtedString in a UILabel. The problem is in the strong text, the result is too bold (I guess when parsing the font is changed to "GibsonBold" and I need GibsonSemibold, or even change from Regular to Medium. I tried change tag to < b > or implement an style, but the result is always the same. Also I tried several extensions but I came out whit the same result.

This is the html String:

"<p>First text <strong> this text should be at lest Semibold</strong>. Final text.</p>"

Im using this two extension to parsing:

extension UIColor {
    var hexString:String? {
        if let components = self.cgColor.components {
            let r = components[0]
            let g = components[1]
            let b = components[2]
            return  String(format: "XXX", (Int)(r * 255), (Int)(g * 255), (Int)(b * 255))
        }
        return nil
    }
}

extension String {
    var html2Attributed: NSAttributedString? {
        do {
            guard let data = data(using: String.Encoding.utf8) else {
                return nil
            }
            return try NSAttributedString(data: data,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
    
    var htmlAttributed: (NSAttributedString?, NSDictionary?) {
        do {
            guard let data = data(using: String.Encoding.utf8) else {
                return (nil, nil)
            }

            var dict:NSDictionary?
            dict = NSMutableDictionary()

            return try (NSAttributedString(data: data,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: &dict), dict)
        } catch {
            print("error: ", error)
            return (nil, nil)
        }
    }
    
    func htmlAttributed(using font: UIFont, color: UIColor, lineHeight: CGFloat) -> NSAttributedString? {
        do {
            let htmlCSSString = "<style>"  
                "html *"  
                "{"  
                "font-size: \(font.pointSize * 0.75)pt !important;"  
                "color: #\(color.hexString!) !important;"  
                "font-family: \(font.familyName), Helvetica !important;"  
                "line-height: \(lineHeight * 0.06) !important;"  
                "}</style> \(self)"

            guard let data = htmlCSSString.data(using: String.Encoding.utf8) else {
                return nil
            }

            return try NSAttributedString(data: data,
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
}

And the implementation in label:

descriptionLabelText.attributedText = description.htmlAttributed(using: UIFont.gibsonRegular.withAdjustedSize(16),
                                                                    color: .greyscale800,
                                                                    lineHeight: 20.adjusted)

CodePudding user response:

Currently all the css styling only defines the font to use and the font size, not really the style (bold, italic, regular etc) or the weights (normal, bold, light etc) so these tags pick up the default styles of the tag.

I created the following HTML

let htmlString
            = "<p>Normal text <strong> Strong set to 600 font weight </strong>. <b> Bold set to italic style </b>"

And then I use your code like this

label.attributedText = htmlString.htmlAttributed(using: UIFont(name: "Gibson-Regular",
                                                               size: 16)!,
                                                 color: .red,
                                                 lineHeight: 20)

This gives me the following result as you probably see now

HTML Text iOS Swift html Attributed text label custom style and font

If you added all the fonts (Gibson regular, bold, italic) to your file system properly, you can add specific styles in your CSS.

Small changes to your func htmlAttributed

func htmlAttributed(using font: UIFont,
                    color: UIColor,
                    lineHeight: CGFloat) -> NSAttributedString? {
    do {
        let htmlCSSString = "<style>"  
            "html *"  
            "{"  
            "font-size: \(font.pointSize * 0.75)pt !important;"  
            "color: #\(color.hexString!) !important;"  
            "font-family: \(font.familyName), Helvetica !important;"  
            "line-height: \(lineHeight * 0.06) !important;"  
            "}"  
            
            // customize bold
            "b"  
            "{"  
            "font-size: \(font.pointSize * 0.75)pt !important;"  
            "font-style: italic;"   // I set bold to be italic
            "font-family: \(font.familyName), Helvetica !important;"  
            "line-height: \(lineHeight * 0.06) !important;"  
            "}"  
            
            // customize strong font weight
            // https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight
            "strong"  
            "{"  
            "font-size: \(font.pointSize * 0.75)pt !important;"  
            "font-weight: 600;"   // customize weight to what you want
            "font-family: \(font.familyName), Helvetica !important;"  
            "line-height: \(lineHeight * 0.06) !important;"  
            "}"  
            
            "}</style> \(self)"
        
        guard let data = htmlCSSString.data(using: String.Encoding.utf8) else {
            return nil
        }
        
        return try NSAttributedString(data: data,
                                      options: [.documentType: NSAttributedString.DocumentType.html,
                                                .characterEncoding: String.Encoding.utf8.rawValue],
                                      documentAttributes: nil)
    } catch {
        print("error: ", error)
        return nil
    }
}

With this change you will see some changes to the weight of the strong tag and I made the b tag render as italics

HTML attributed UILabel set font font size font style strong tag bold tag swift iOS

Finally, as far as I know, you cannot set the weight to Semi Bold so if you want to use the Semi Bold font, you have explicitly set this as the font you want to use.

So you can customize the strong tag:

// I set font family to Gibson italic for example
// You can set it to semi bold font
"strong"  
"{"  
"font-size: \(font.pointSize * 0.75)pt !important;"  
"font-family: \(UIFont(name: "Gibson-Italic", size: 16)!), Helvetica !important;"  
"line-height: \(lineHeight * 0.06) !important;"  
"}"  

Html to NSAtributtedString in a UILabel custom style strong bold font iOS swift

I think this should give you some ideas on how to customize to suit your solution

  • Related