Provide better support for SwiftUI and AttributedString.
makhocheung opened this issue · 5 comments
Here is the example.
import Combine
import SwiftUI
import ZMarkupParser
struct MainView: View {
@State var content = AttributedString("None")
var body: some View {
ScrollView {
VStack {
Text(content)
}
}
.onAppear {
content = AttributedString(parser.render(html))
}
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView()
}
}
let parser = ZHTMLParserBuilder.initWithDefault().set(rootStyle: MarkupStyle(font: MarkupStyleFont(size: 13))).build()
let html = #"""
Powered by ZhgChgLi. <br/>
<img src="https://user-images.githubusercontent.com/33706588/219608966-20e0c017-d05c-433a-9a52-091bc0cfd403.jpg"/>
🎄🎄🎄 <Hottest> <b>Christmas gi<u>fts</b> are here</u>! Give you more gift-giving inspiration~<br />
The <u>final <del>countdown</del></u> on 12/9, NT$100 discount for all purchases over NT$1,000, plus a 12/12 one-day limited free shipping coupon<br />
<zhgchgli>Top 10 Popular <b><span style="color:green">Christmas</span> Gift</b> Recommendations 👉</zhgchgli><br>
<ol>
<li><a href="https://zhgchg.li">Christmas Mini Diffuser Gift Box</a>|The first choice for exchanging gifts</li>
<li><a href="https://zhgchg.li">German design hair remover</a>|<strong>500</strong> yuan practical gift like this</li>
<li><a href="https://zhgchg.li">Drink cup</a>|Fund-raising and praise exceeded 10 million</li>
</ol>
<hr/>
<p>Before 12/26, place an order and draw a round-trip ticket for two to Japan!</p>
你好你好<span style="background-color:red">你好你好</span>你好你好 <br />
안녕하세요안녕하세<span style="color:red">요안녕하세</span>요안녕하세요안녕하세요안녕하세요 <br />
<span style="color:red">こんにちは</span>こんにちはこんにちは <br />
<h1>不支持</h1>
<h2>不支持</h2>
<h3>不支持</h3>
<h4>不支持</h4>
<h5>不支持</h5>
<h6>不支持</h6>
"""#
Here is the error printed by console.
2023-03-13 16:46:54.445491+0800 Demo[41916:3803493] [Demo] CGImageDestinationCreateWithData:4044: *** ERROR: CGImageDestinationCreateWithData: invalid capacity (0)
2023-03-13 16:46:54.445856+0800 Demo[41916:3803493] [Demo] finalizeDestination:3205: *** ERROR: CGImageDestinationFinalize was called, but there were no images added
2023-03-13 16:46:54.445881+0800 Demo[41916:3803493] CGImageDestinationFinalize failed for output type 'public.tiff'
Hi, @makhocheung thank you for using and providing feedback.
From the content of your issue, I have identified three problems that need to be resolved:
- Easy - Support h1~h6. This is not a bug, but an extension is needed to support H tags.
- Easy - I saw a log message that says "failed for output type 'public.tiff'" on macOS, which means I have a misunderstanding of AppKit's NSImage. This issue is also related to ZNSTextAttachment.
- Need research - Make AttributedString support ZNSTextAttachment. Currently, we use ZNSTextAttachment to represent images.
I'll resolve it as soon as possible.
Thank you again for your feedback, I have not fully tested on macOS or using SwiftUI yet.
After conducting research, I have concluded that AttributedString and NSAttributedString are not small objects and do not share the same inheritance.
Therefore, I believe that using NSAttributedString in AttributedString or SwiftUI is not a good idea.
Instead, we should create a new mapper to map ZMarkupParser.Markup objects to SwiftUI Kit (Text/Image) components, rather than using NSAttributedString directly in AttributedString.
Unfortunately, it may not be implemented quickly.
A temporary dirty solution would be to find ZNSTextAttachment for each AttributedString and manually trigger startDownload() and handle delegate for it.
content.compactMap({ $0.attachment as? ZNSTextAttachment }).forEach { attachment in
attachment.delegate = self
attachment.startDownlaod()
})
// handler delegate
func zNSTextAttachment(didLoad textAttachment: ZNSTextAttachment, to: ZResizableNSTextAttachment) {
//
replace textAttachment to to in AttributedString
}
I know it's very dirty, but as I mentioned earlier, it's not recommended to use it in SwiftUI currently.
Please let me know if there is anything I have misunderstood, as I am not very familiar with SwiftUI.
Currently,AttributedString supports markdown natively except ![]()
,so it's normal that AttributedString can't load remote images. Maybe Apple will add this feature in the future.
we should create a new mapper to map ZMarkupParser.Markup objects to SwiftUI Kit (Text/Image) components, rather than using NSAttributedString directly in AttributedString.
This is a good idea. Developers may hope ZMarkupParser supports SwiftUI.
Actually, I'm appreciate that you have added support of h1~h6. ZMarkupParser currently satisfies my project. I will give more feedback later. Thank you.
I'll add on here that this is really more of a failing of a failing of SwiftUI's Text()
than of this library. It is very simple to convert between the 2 nowadays.
let nsAttr = parser.render(html)
let attr = AttributedString(nsAttr)
The real issue is that AttributedString
and Text()
are missing a lot of functionality, most notably support for NSParagraphStyle
which you need to do paragraph level alignment, spacing, lineSpacing, justification, etc.
For my own projects I use a UIViewRepresentable
wrapping a UITextView
to get the maximum flexibility.