Down icon indicating copy to clipboard operation
Down copied to clipboard

Support for the new `AttributedString`

Open liang2kl opened this issue 3 years ago • 5 comments

In WWDC 21 a new AttributedString type was introduced, useful for rendering attributed text in SwiftUI.

It seems that converting the NSAttributedString instance generated by the module to AttributedString using init<S>(_ nsStr: NSAttributedString, including scope: S.Type) throws where S : AttributeScope does not preserve any renderable attribute, as shown in the figure, where the top view is the attributed text:

IMG_7042

The code to generate the attributed string is:

let markdownString = try! Down(markdownString: text).toAttributedString()
let attributedString = try! AttributedString(markdownString, including: \.foundation)

To display:

Text(attributedString)

Maybe some fixes or directly generating the attributed string could help.

liang2kl avatar Jun 14 '21 05:06 liang2kl

Hi @liang2kl , I haven't been able to look at this yet. Is this no longer an issue?

johnxnguyen avatar Jun 18 '21 07:06 johnxnguyen

Hi @liang2kl , I haven't been able to look at this yet. Is this no longer an issue?

Sorry, seems I closed this by mistake.

I have experimented with this for a while, and the reason might be SwiftUI not recognizing the attributes created with UIKit (the AttributedString instance do have the original attributes, though).

So I guess we need a styler for AttributedString?

liang2kl avatar Jun 18 '21 09:06 liang2kl

I'm afraid I haven't yet had a look at the new AttributedString api, so I welcome any input that you have.

johnxnguyen avatar Jun 18 '21 10:06 johnxnguyen

I have a solution after some exploration.

The problem is that, SwiftUI won't recognize any attribute from UIKit. Instead, it use different types, with limited attributing options.

So (it seems) the only solution is to convert the UIKit attributes to the SwiftUI ones, like:

var attrStr: AttributedString = ...

for run in attrStr.runs {
    if let font = run.uiKit.font {
        attrStr[run.range].swiftUI.font = Font(font as CTFont)
    }
}

This method can transform the correspond attribute to any currently supported attribute in SwiftUI, and I works. But as SwiftUI's attributing support is very poor, not every original attribute can be transformed and displayed. So I am afraid that there's no perfect solution to displaying Markdown in SwiftUI currently.

liang2kl avatar Jun 22 '21 13:06 liang2kl

But as SwiftUI's attributing support is very poor, not every original attribute can be transformed and displayed.

@liang2kl I would wait until AttributedString matures enough to be able to support the standard TextKit attributes, otherwise, as you suggest, the experience will be quite poor. In any case, I'll return to this at some point to see how we can take advantage of new TextKit apis.

johnxnguyen avatar Jun 23 '21 06:06 johnxnguyen