psharanda / Atributika

Convert text with HTML tags, links, hashtags, mentions into NSAttributedString. Make them clickable with UILabel drop-in replacement.
MIT License
1.45k stars 155 forks source link

How to handle nested tags? #96

Closed photos closed 5 years ago

photos commented 5 years ago

I have the following nested html string:

<a href=\"https://en.wikipedia.org/wiki/World_of_Dance_(TV_series)\" target=\"_blank\"><strong><em>World of Dance</em></strong></a>

Expected result:

World of Dance

This is an italicized bold link. How would I handle formatting this? It seems like Style only applies to one tag, but I may be wrong.

psharanda commented 5 years ago

Yeah you can't composite font styles using different tags. You need to define font completely in one Style. For example:

func stringWithBoldItalic() -> NSAttributedString {

    let baseFont = UIFont.systemFont(ofSize: 12)
    let descriptor = baseFont.fontDescriptor.withSymbolicTraits([.traitItalic, .traitBold])
    let font = descriptor.map { UIFont(descriptor: $0, size: baseFont.pointSize) } ?? baseFont

    let a = Style("a").font(font).foregroundColor(.blue)
    let str = "<a href=\"https://en.wikipedia.org/wiki/World_of_Dance_(TV_series)\" target=\"_blank\">World of Dance</a>".style(tags: a)
        .attributedString
    return str
}
photos commented 5 years ago

Is there a way or strategy to support multiple styles such as Style([“b”,”em”])? If not, this may be a useful feature.

psharanda commented 5 years ago

You can create new style from other style using Style("em", style: otherStyle) or otherStyle.named("em")

photos commented 5 years ago

I have created all possible styles for nested HTML tags and have applied it to a string with string.style(tags:[Style]). But, when applying these styles, the string is getting overridden and does not respect each style.

For example, given this HTML snippet:

<li><a href=\"https://www.youtube.com/watch?v=I_izvAbhExY\" target=\"_blank\"><em>Staying Alive</em></a></li> <li><a href=\"https://www.youtube.com/watch?v=yca6UsllwYs\" target=\"_blank\"><strong><em>Around the World</em></strong></a></li>

Expected Result:

_Staying Alive Around the World_

Here is my code. Is this supported or is there a workaround to support nested tags?

// <a><em> let LinkEmphasisStyle = Style("a", style: Style("em")).font(ItalicFont).foregroundColor(.blue,.normal).foregroundColor(.blue,.highlighted)

// <a><strong><em> let LinkStrongEmphasisStyle = Style("a", style: Style("strong", style: Style("em"))).font(ItalicBoldFont).foregroundColor(.blue,.normal).foregroundColor(.blue,.highlighted)

label.attributedText = htmlStr.style(tags: [LinkEmphasisStyle, LinkStrongEmphasisStyle])

psharanda commented 5 years ago

Yeah, I understand your problem, but for the moment Atributika doesn't support fonts composition. Instead of strong and em styles you need to create strongAndEm style with clearly defined bold italic font.