Code Monkey home page Code Monkey logo

zmarkupparser's People

Contributors

5anniversary avatar charrondev avatar jackycsie avatar wei18 avatar zhgchgli0718 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

zmarkupparser's Issues

Rendering image tags

Hello @zhgchgli0718
First of all thanks for making this wonderful framework. The framework works great with almost all html tags.
My question is what about Image tags?
Image tags are the most widely used in HTML.

Line breaks issue

In the following HTML example:

<p>First line</p><p>Second line</p><br/><p>One empty line above</p><br/><br/><p>2 empty lines above</p>

should render with a line break after the 'Second line' and before the 'One empty line above' and with two line breaks after the 'One empty line above' and before the '2 empty lines above' is rendered. However, I've noticed when the HTML string is parsed, line breaks are stripped out, so the render ends up like this:
Снимок экрана 2024-02-07 в 16 05 50
instead of this:
Снимок экрана 2024-02-07 в 16 05 30

Looks like a bug because in version 1.7.0 there was a line break after the 'Second line' and before the 'One empty line above'. But after the 'One empty line above' and before the '2 empty lines above' was only one line break instead of two.

base64 images

Hello. Thank you very much for this library! It makes handling HTML so much easier!

One question: Is there any chance that it will get base64-image support? Or could you give me some pointers on how to add an according tag-handling system?

When looking through the source, I noticed that this

let attachment = ZNSTextAttachment(imageURL: srcURL, imageWidth: width, imageHeight: height, placeholderImage: placeholderImage(size: CGSize(width: width ?? 50, height: height ?? 50)))
is using an UIImage for the placeholder. So it should be possible to just replace the ZNSTextAttachment-code somewhere down the line with just something like

let regex = try NSRegularExpression(pattern: "data:image/.+;base64,(.+)")
let result = regex.firstMatch(in: url, options: [], range: NSRange(url.startIndex..., in: url))
let nsString = url as NSString

let data = Data(base64Encoded: nsString.substring(with: result!.range(at: 1)), options: .ignoreUnknownCharacters)
return UIImage(data: data!)

But I cannot figure out where.
I guess I would have to import ZNSTextAttachment and then replicate your code. But I could use some pointers on how to utitilize the ZHTMLParserBuilder.add-method for that

Thanks a lot! :)

Add better table rendering support

I've noticed that table rendering is relatively lackluster.

I'm willing to take a crack at it in the next few months but wanted to open this issue to start getting some ideas down.

Current Limitations

Currently the table implementation creates tries to even things out by making use of whitespace characters to even the columns. This has numerous shortcomings, most notably that

  • It requires the use of a monospaced font to even partially work.
  • It doesn't allow having column or row separators
  • Lines wrap breaking the flow.

Implementation Ideas

My goal would be something like the following:

  • Tables get rendered to exactly the with or their parent container.
    • The can be scrolled horizontally if they are longer than expected.
  • Tables cells can wrap their contents
  • Table cells will have a configurable fixed width
  • The underlying table will have a few styling options:
    • Control column/row separators
    • Allow alternating row colors

To actually accomplish this it will certainly need to be some type of NSTextAttachment, and ZNSTextAttachment seems like a good enough inspiration of something with dynamic, initially unknown height to calculate and render.

`stripper()` function doesn't remove HTML entities

Given the following HTML string <b>Tea &amp; coffee</b>:

when rendered we get:
"Tea & coffee"

when calling the stripper() method and rendered we get:
"Tea &amp; coffee"

I would expect the HTML entities to be decoded, so when rendered:
"Tea & coffee"

I can't see any use case where I would want an NSAttributedString that has been stripped of HTML formatting to show HTML entities which are by definition HTML.

Double line breaks are stripped out

In the following HTML example:
One<br /><b>Two</b><br /><i>Three</i><br /><i><b>Four</b></i><br /><br />New <b>Paragraph</b>!

should render with a line break after the 'Four' and before the 'New Paragraph' is rendered. However, I've noticed when the HTML string is parsed, the second line break is stripped out, so the render ends up like this:

incorrect

instead of this:

correct

Can this functionality be switched off, or is there a bug present?

EDIT: I've found this function in the source code which seems to the be the culprit:

func reduceBreaklineInResultNSAttributedString(_ attributedString: NSAttributedString) -> NSAttributedString

but I can't find anyway of switching it off, or overriding the functionality.

Font Family Support Issue - Always displays bold when root font has a weight

I am using the attributed parser, and initialising with a standard font that has a regular weight - however whenever i try to display this it is converted to a bold font. I have been able to replicate an example below using a system font.

let attributedParser = ZHTMLParserBuilder.initWithDefault()
            .set(rootStyle: MarkupStyle(font: MarkupStyleFont(UIFont.systemFont(ofSize: 12, weight: .regular)),
                                        foregroundColor: MarkupStyleColor(color: .black)))
            .build()
        attributedText = attributedParser.render("Test Message that should be a regular font but is actually bold")

I've been debugging a little bit and I believe the issue lies within MarkupStyleFont - getFont() method line 165. If the font has a weight then it always adds the bold trait.
Screenshot 2023-08-10 at 4 36 31 pm

Screenshot of issue below:
Screenshot 2023-08-10 at 4 39 22 pm

Screenshot 2023-08-10 at 4 39 00 pm

Provide better support for SwiftUI and AttributedString.

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>

"""#

image

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'

针对单个 <p> 标签处理的问题

最近在学习 SwiftUI,尝试开发一个 Hacker News Reader,通过官方 API 返回的 HTML String 里面的 <p> 标签都是独立的,举例:

{
  "by": "joak",
  "id": 34934428,
  "kids": [
    34934473
  ],
  "parent": 34934270,
  "text": "Henry Kissinger will be 100 years old in few weeks. And he is still around giving advice. Amazing.<p>But I don&#x27;t see why his opinion could be relevant on the topic...",
  "time": 1677306778,
  "type": "comment"
}

调用 parser.render(text) 后,会产生空行,如图所示:

CleanShot 2023-03-14 at 15 07 47@2x

我的预期是通过控制 paragraphSpacing 来调整段间距,从而让段落之间有一定的空间。上图中 paragraphSpacing 的值 是 8,但由于中间有空行,让段落间的空隙显得很大。

Support parse `<table>` like `NSAttributedString.DocumentType.html` (by using NSTextTableBlock)

After researching how the 'NSAttributedString.DocumentType.html' renders HTML <table> tag,

I found something interesting. It turns out that 'NSAttributedString.DocumentType.html' uses 'NSTextTableBlock' in 'NSParagraphStyle' to format table results. However, 'NSTextTableBlock' is not a publicly accessible API in iOS, so there isn't anything we can do about it.

ref: https://stackoverflow.com/a/25537864/1093917

sample code:

let data = "what<table><tr><td>1</td><td>2</td></tr><tr><td>a</td><td>b</td></tr></table>test".data(using: String.Encoding.utf8)!
let attributedOptions:[NSAttributedString.DocumentReadingOptionKey: Any] = [
      .documentType :NSAttributedString.DocumentType.html,
      .characterEncoding: String.Encoding.utf8.rawValue
]
let result = try! NSAttributedString(data: data, options: attributedOptions, documentAttributes: nil)

output:

"Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n), DefaultTabInterval 36, Blocks (\n    \"<NSTextTableBlock: 0x60000392d6e0>\"\n), Lists (null), BaseWritingDirection 0, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0 LineBreakStrategy 0 PresentationIntents (\n) ListIntentOrdinal 0 CodeBlockIntentLanguageHint \'(null)\'"

You can see the displayed text above: Blocks (\n "<NSTextTableBlock: 0x60000392d6e0>"\n), but we can't access it through NSParagraphStyle.

I have no idea...

Digging into table rendering

I'm currently exploring markdown rendering (to implement a ChatGPT like app) on iOS and find it's hard to implement a basic table in text view.

However I found it's implemented in an App called 豆包(a ByteDance app, the company who made TikTok) in China mainland & CiCi outside China mainland.

豆包:https://www.doubao.com/
Cici:https://www.ciciai.com/

豆包 table
IMG_0504 IMG_0503

As you mentioned in your article https://medium.com/zrealm-ios-dev/%E6%89%8B%E5%B7%A5%E6%89%93%E9%80%A0-html-%E8%A7%A3%E6%9E%90%E5%99%A8%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B-2724f02f6e7

實測原生的 NSAttributedString.DocumentType.html 是用 Private macOS API NSTextBlock 來完成顯示,因此能完整顯示 HTML 表格樣式及內容。
有點作弊!我們無法用 Private API

Would you like to tell about your thought about how they achieved it?

I've also explored ChatGPT's app. They haven't implement table rendering in their iOS App.

Custom Font

Hello,

It's possible to set a custom font to regular text or to bold tag?
I'm using the MarkupStyle, but it's only changing the size, not the font.

Thanks.

List Formatting

This is an excellent library that meets all our needs except one: list formatting.

For an unordered list like the following:

<ul>
  <li>ZMarkupParser is a pure-Swift library that helps you convert HTML strings into NSAttributedString with customized styles and tags.</li>
  <li>ZMarkupParser is a pure-Swift library that helps you convert HTML strings into NSAttributedString with customized styles and tags.</li>
  <li>ZMarkupParser is a pure-Swift library that helps you convert HTML strings into NSAttributedString with customized styles and tags.</li>
</ul>

The rendered output is:

Screenshot 2024-03-15 at 11 26 14 AM

This falls short of our need in a couple ways:

  1. There is no spacing between the bullet and the text. This makes them very hard to read.
  2. The wrapped text should align with the start of the first line, similar to the following:
Screenshot 2024-03-15 at 11 35 41 AM

It would be great if this could be achieved. Otherwise lists are fairly unusable.

Use ListItemMarkup with NSTextList

I found an attribute called NSTextList in NSMutableParagraphStyle, but after testing, I didn't see any benefit in using it because even when using NSTextList, we still need to manually append list items and padding to NSAttributedString.

sample code:

let attributedText = NSMutableAttributedString()
let paragraphStyle = NSMutableParagraphStyle()
let list = NSTextList(markerFormat: .circle, options: 0)
paragraphStyle.textLists = [list]
attributedText.append(NSAttributedString(string: "test"))
attributedText.append(NSAttributedString(string: "\(list.marker(forItemNumber: 1))testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest", attributes: [.paragraphStyle: paragraphStyle]))
attributedText.append(NSAttributedString(string: "test"))

Is it possible to implement border-radius or padding?

Still this can be marked as a question.

In the app I mentioned in previous issue #54, it can render markdown inline code like a HTML inline-block. I find padding & corner radius is not supported in iOS attributed text.

image

Is it possible to implement custom rendering border-radius or padding?

Proposal: Change various visitor implementations from structs to classes

This project implements various visitor classes that have methods for generating or rendering each type of markup.

I'd like to switch these structs to be classes and add the ability to replace their implementation in the ParserBuilder.

By making them classes they can be extended while preserving most functionality.

For example I have a fair of experimentation I'd like to do with tables in the near future that likely won't be immediately upstreamable and would prefer not to create a full duplicate implementation of all of the other visitor functions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.