mlem icon indicating copy to clipboard operation
mlem copied to clipboard

[2.0] Tappable links

Open Sjmarf opened this issue 1 year ago • 0 comments

In v1.0, we extracted these using Regex. For 2.0, I've implemented the link extraction logic in LemmyMarkdownUI. This has several advantages:

  • It won't look for links inside of code blocks.
  • We can choose not to render links inside of spoilers.
  • We can extract the title of each link as a series of nodes, allowing the tappable link titles to be rendered in the same markdown format as the links in the original text.
  • It's about 8-10x faster than our regex solution (tested on the markdown in the Profile tab), because it simply traverses an existing markdown tree.

LemmyMarkdownUI implementation

Get the links contained within some markdown like so:

let blocks: [BlockNode] = .init(markdown: string)
let links = blocks.links

links is an array of LinkData, which is defined as follows:

struct LinkData {
   let title: [InlineNode]
   let url: URL
   var insideSpoiler: Bool
}

Using this in Mlem

LemmyMarkdownUI's Markdown view has an initialiser that accepts [BlockNode]. This means that we can create the markdown tree in Mlem, extract the links from it, then pass the tree to Markdown to render it. This should be pretty performant.

Notice that LinkData.title is an array of inline nodes. When rendering the title of each tappable link, we can pass this array to LemmyMarkdownUI's MarkdownText view to render the title with markdown features. Or, you can use title.stringLiteral to get the raw string with markdown delimiters removed.

We should probably not include links that are inside spoilers in the tappable links list. To exclude these, we can use something like links.filter { !$0.insideSpoiler }.

Sjmarf avatar May 26 '24 20:05 Sjmarf