iosswiftuser-interfaceswiftuitext

How to render an image inside markdown text


I will prefix this by saying I have quite limited Swift and SwiftUI experience, so there might be some obvious things that I have missed.

My problem is split into multiple areas of concern

  1. I want to render a text link using markdown within a Text view in SwiftUI
  2. I want the label for this link to contain an image alongside some text so that the text and image are both clickable
  3. I need this to be done inside a Text view which I can then append to the end of another Text view.

Some context

I have several paragraphs of text, each one coming from a specific source which I want to provide a link to. The link should be inline with the text and at the end of each paragraph, and should be in the format "Source <icon>". I believe SwiftUI's support for markdown is the easiest way to achieve this, as it allows a simple Text view to contain a hyperlink by doing: Text(.init("[Source](https://example.com)")). This has got me quite far, but I am missing the crucial step of including the icon as part of the link label. As of now, I have been forced to add the icon after the actual link text as per the example below.

So my question boils down to: Is there a way to render an image inside a markdown string in SwiftUI?

Simplified example of my code setup

import SwiftUI

struct Paragraph {
  text: String
  url: String
}

struct ParagraphView: View {
  let paragraph: Paragraph

  var body: some View {
    Text(paragraph.text)

    // Less than ideal solution I have currently
    + Text(.init(" [Source](\(paragraph.url)) "))

    + Text(Image(systemName: "star")) // Example icon
  }
}

Ideally, I would like to do something like this

struct ParagraphView: View {
  let paragraph: Paragraph

  var body: some View {
    Text(paragraph.text)

    + Text(.init(" [Source \(IMAGE)](\(paragraph.url))"))
  }
}

I have tried using both AttributedString and NSAttributedString to achieve this

struct ParagraphView: View {
  let paragraph: Paragraph

  var markdown: String {
    let str = NSMutableAttributedString(string: " [Source ")

    let iconAttachment = NSTextAttachment()
    iconAttachment.image = UIImage(systemName: "star")
    let iconText = NSAttributedString(attachment: iconAttachment)

    str.append(iconText)
    str.append(NSAttributedString(string: "](\(paragraph.url))"))

    return str.string
  }

  var body: some View {
    Text(paragraph.text)

    // Link works, but image is not rendered
    + Text(.init(markdown))
  }
}

Solution

  • Currently, it seems that Images still aren't supported by Swift UI.

    Note: Images aren’t supported.

    Source

    There are probably other libraries out there for this, you'll have to pick one if you want to add images in markdown.

    This article also discusses the issue and introduces this package which is compatible with GitHub's Markdown Spec.
    Because of that compatibility, you'll then be able to use all the normal markdown that you're used to:

    ![image](https://httpcats.com/200.jpg)
    

    ↓↓

    image