Работа с Markdown в Swift (iOS/macOS): библиотеки Down, SwiftMarkdown

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Обработка Markdown в Swift для iOS и macOS: от парсинга до рендеринга

Markdown — один из самых популярных языков разметки для форматирования текста. В экосистеме Swift (iOS/macOS) существует несколько мощных библиотек, которые позволяют парсить, конвертировать и отображать Markdown. В этой статье мы рассмотрим две основные библиотеки: Down (быстрый и гибкий) и SwiftMarkdown (официальная библиотека от Apple). Вы узнаете, как интегрировать их в свои проекты, преобразовывать Markdown в NSAttributedString, HTML и отображать в SwiftUI.

1. Библиотека Down (cmark-based)

Down — это обёртка над популярным C-парсером cmark, написанная на Swift. Она обеспечивает высокую производительность и поддерживает все основные элементы Markdown (заголовки, списки, код, ссылки, изображения, таблицы и т.д.).

Установка

Добавьте пакет через Swift Package Manager:

// Package.swift
dependencies: [
    .package(url: "https://github.com/johnxnguyen/Down.git", from: "0.11.0")
]

Пример: конвертация Markdown в HTML

import Down

let markdownString = "# Привет, мир!\n\nЭто **жирный текст** и *курсив*."
let down = Down(markdownString: markdownString)
let html = try? down.toHTML()
print(html ?? "")
// Вывод: <h1>Привет, мир!</h1>\n<p>Это <strong>жирный текст</strong> и <em>курсив</em>.</p>

Рендеринг в NSAttributedString

Down умеет напрямую создавать NSAttributedString для отображения в UILabel, UITextView или NSTextView:

let attributedString = try? down.toAttributedString()
// Используйте в UITextView:
textView.attributedText = attributedString

Поддержка SwiftUI

Для SwiftUI можно создать обёртку, отображающую AttributedString (iOS 15+):

struct MarkdownView: View {
    let markdown: String

    var body: some View {
        if let nsAttr = try? Down(markdownString: markdown).toAttributedString() {
            Text(AttributedString(nsAttr))
        } else {
            Text(markdown)
        }
    }
}

2. SwiftMarkdown (от Apple)

SwiftMarkdown — это официальная библиотека Apple, входящая в swift-markdown. Она предоставляет полный парсер Markdown с возможностью кастомизации и генерации различных форматов (HTML, CommonMark, AST).

Установка

// Package.swift
dependencies: [
    .package(url: "https://github.com/apple/swift-markdown.git", branch: "main")
]

Парсинг и работа с AST

Библиотека строит абстрактное синтаксическое дерево (AST), которое можно анализировать и модифицировать:

import Markdown

let source = """
# Документация

Список функций:
- `foo()` — первая функция
- `bar()` — вторая функция
"""

let document = Document(parsing: source)
let heading = document.child(at: 0) as? Heading
print(heading?.plainText ?? "") // "Документация"

// Обход всех элементов
for child in document.children {
    if let list = child as? UnorderedList {
        for item in list.children {
            print((item as? ListItem)?.plainText ?? "")
        }
    }
}

Генерация HTML

let html = document.format(options: [.unsafeTags])
print(html)
// Вывод: <h1>Документация</h1>...<ul><li><code>foo()</code> — первая функция</li>...

Рендеринг через AttributedString (iOS 15+)

SwiftMarkdown поддерживает прямое преобразование в AttributedString с использованием стилей:

import Markdown
import SwiftUI

struct ContentView: View {
    let markdown = "**Важно**: нажмите *здесь*."

    var body: some View {
        if let attributed = try? AttributedString(markdown: markdown) {
            Text(attributed)
        }
    }
}

3. Сравнение Down vs SwiftMarkdown

Рекомендаций