swift-markdown-ui

2.0.0

Display and customize Markdown text in SwiftUI
gonzalezreal/swift-markdown-ui

What's New

MarkdownUI 2.0.0

2023-01-22T17:05:44Z

Overview

MarkdownUI 2 has been rewritten from scratch and brings a ton of new features and improvements
like:

  • GitHub Flavored Markdown (tables, task lists, strikethrough text, and autolinks)
  • Native SwiftUI rendering
  • Customization support via themes, text styles, and block styles.

These new features come with the cost of a few breaking changes that these notes will help you to
address.

Minimum requirements

You can use MarkdownUI 2 on the following platforms:

  • macOS 12.0+
  • iOS 15.0+
  • tvOS 15.0+
  • watchOS 8.0+

Some features, like displaying tables or multi-image paragraphs, require macOS 13.0+, iOS 16.0+,
tvOS 16.0+, and watchOS 9.0+.

Updated package name

To reflect the Swift community naming conventions, the package has been renamed from MarkdownUI to swift-markdown-ui. So, you may eventually need to update any Xcode projects or Package.swift files that depend on MarkdownUI.

Rendering

MarkdownUI 2 uses SwiftUI primitives to render Markdown and no longer depends on gonzalezreal/AttributedText.

Creating Markdown content

MarkdownUI 2 introduces a new domain-specific language to create Markdown content and no longer
depends on gonzalezreal/SwiftCommonMark.

One significant difference when using MarkdownUI 2 is that MarkdownContent replaces Document
by providing similar functionality.

Another thing to be aware of is the different naming of some of the types you use to compose
Markdown content:

  • Use Blockquote instead of BlockQuote.
  • Use NumberedList instead of OrderedList.
  • Use BulletedList instead of BulletList.
  • Use InlineImage instead of Image.
  • Use InlineLink instead of Link.
  • Use Code instead of InlineCode.

Loading asset images

MarkdownUI 2 introduces the ImageProvider protocol and its conforming types
DefaultImageProvider and AssetImageProvider. These types and the new
markdownImageProvider(_:) modifier replace the MarkdownImageHandler type and
the setImageHandler(_:forURLScheme:) modifier.

The following example shows how to configure the asset image provider to load images from the
main bundle.

Markdown {
  "![A dog](dog)"
  "― Photo by André Spieker"
}
.markdownImageProvider(.asset)

Customizing link behavior

The onOpenMarkdownLink(perform:) modifier in MarkdownUI 1.x was provided to enable link behavior
customization in macOS 11.0, iOS 14.0, and tvOS 14.0. This modifier is no longer available in
MarkdownUI 2 since it does not support those platforms. However, you can customize the link
behavior by setting the openURL environment value with a custom OpenURLAction.

Styling Markdown

MarkdownUI 1.x offered a few options to customize the content appearance. In contrast, MarkdownUI 2
brings the new Theme, TextStyle, and BlockStyle types that let you apply a custom
appearance to blocks and text inlines in a Markdown view.

Consequently, the MarkdownStyle type, all of its subtypes, and the markdownStyle(_:) modifier
are no longer available in MarkdownUI 2.

MarkdownUI

CI contact: @gonzalezreal

Display and customize Markdown text in SwiftUI.

Overview

MarkdownUI is a powerful library for displaying and customizing Markdown text in SwiftUI. It is compatible with the GitHub Flavored Markdown Spec and can display images, headings, lists (including task lists), blockquotes, code blocks, tables, and thematic breaks, besides styled text and links.

MarkdownUI offers comprehensible theming features to customize how it displays Markdown text. You can use the built-in themes, create your own or override specific text and block styles.

Minimum requirements

You can use MarkdownUI 2 on the following platforms:

  • macOS 12.0+
  • iOS 15.0+
  • tvOS 15.0+
  • watchOS 8.0+

Some features, like displaying tables or multi-image paragraphs, require macOS 13.0+, iOS 16.0+, tvOS 16.0+, and watchOS 9.0+.

Getting started

Creating a Markdown view

A Markdown view displays rich structured text using the Markdown syntax. It can display images, headings, lists (including task lists), blockquotes, code blocks, tables, and thematic breaks, besides styled text and links.

The simplest way of creating a Markdown view is to pass a Markdown string to the init(_:baseURL:imageBaseURL:) initializer.

let markdownString = """
  ## Try MarkdownUI

  **MarkdownUI** is a native Markdown renderer for SwiftUI
  compatible with the
  [GitHub Flavored Markdown Spec](https://github.github.com/gfm/).
  """

var body: some View {
  Markdown(markdownString)
}

A more convenient way to create a Markdown view is by using the init(baseURL:imageBaseURL:content:) initializer, which takes a Markdown content builder in which you can compose the view content, either by providing Markdown strings or by using an expressive domain-specific language.

var body: some View {
  Markdown {
    """
    ## Using a Markdown Content Builder
    Use Markdown strings or an expressive domain-specific language
    to build the content.
    """
    Heading(.level2) {
      "Try MarkdownUI"
    }
    Paragraph {
      Strong("MarkdownUI")
      " is a native Markdown renderer for SwiftUI"
      " compatible with the "
      InlineLink(
        "GitHub Flavored Markdown Spec",
        destination: URL(string: "https://github.github.com/gfm/")!
      )
      "."
    }
  }
}

You can also create a MarkdownContent value in your model layer and later create a Markdown view by passing the content value to the init(_:baseURL:imageBaseURL:) initializer. The MarkdownContent value pre-parses the Markdown string preventing the view from doing this step.

// Somewhere in the model layer
let content = MarkdownContent("You can try **CommonMark** [here](https://spec.commonmark.org/dingus/).")

// Later in the view layer
var body: some View {
  Markdown(self.model.content)
}

Styling Markdown

Markdown views use a basic default theme to display the contents. For more information, read about the basic theme.

Markdown {
  """
  You can quote text with a `>`.

  > Outside of a dog, a book is man's best friend. Inside of a
  > dog it's too dark to read.

  – Groucho Marx
  """
}

You can customize the appearance of Markdown content by applying different themes using the markdownTheme(_:) modifier. For example, you can apply one of the built-in themes, like gitHub, to either a Markdown view or a view hierarchy that contains Markdown views.

Markdown {
  """
  You can quote text with a `>`.

  > Outside of a dog, a book is man's best friend. Inside of a
  > dog it's too dark to read.

  – Groucho Marx
  """
}
.markdownTheme(.gitHub)

To override a specific text style from the current theme, use the markdownTextStyle(_:textStyle:) modifier. The following example shows how to override the code text style.

Markdown {
  """
  Use `git status` to list all new or modified files
  that haven't yet been committed.
  """
}
.markdownTextStyle(\.code) {
  FontFamilyVariant(.monospaced)
  FontSize(.em(0.85))
  ForegroundColor(.purple)
  BackgroundColor(.purple.opacity(0.25))
}

You can also use the markdownBlockStyle(_:body:) modifier to override a specific block style. For example, you can override only the blockquote block style, leaving other block styles untouched.

Markdown {
  """
  You can quote text with a `>`.

  > Outside of a dog, a book is man's best friend. Inside of a
  > dog it's too dark to read.

  – Groucho Marx
  """
}
.markdownBlockStyle(\.blockquote) { configuration in
  configuration.label
    .padding()
    .markdownTextStyle {
      FontCapsVariant(.lowercaseSmallCaps)
      FontWeight(.semibold)
      BackgroundColor(nil)
    }
    .overlay(alignment: .leading) {
      Rectangle()
        .fill(Color.teal)
        .frame(width: 4)
    }
    .background(Color.teal.opacity(0.5))
}

Another way to customize the appearance of Markdown content is to create your own theme. To create a theme, start by instantiating an empty Theme and chain together the different text and block styles in a single expression.

extension Theme {
  static let fancy = Theme()
    .code {
      FontFamilyVariant(.monospaced)
      FontSize(.em(0.85))
    }
    .link {
      ForegroundColor(.purple)
    }
    // More text styles...
    .paragraph { label in
      label
        .relativeLineSpacing(.em(0.25))
        .markdownMargin(top: 0, bottom: 16)
    }
    .listItem { label in
      label.markdownMargin(top: .em(0.25))
    }
    // More block styles...
}

Demo

MarkdownUI comes with a few more tricks on the sleeve. You can explore the companion demo project and discover its complete set of capabilities.

Installation

You can add MarkdownUI to an Xcode project as a package dependency.

  1. From the File menu, select Add Packages…
  2. Enter https://github.com/gonzalezreal/swift-markdown-ui into the Search or Enter Package URL search field
  3. Link MarkdownUI to your application target

Description

  • Swift Tools 5.6.0
View More Packages from this Author

Dependencies

Last updated: Sun Feb 05 2023 02:59:53 GMT-0500 (GMT-05:00)