Skip to content

Latest commit

 

History

History
254 lines (198 loc) · 6.28 KB

File metadata and controls

254 lines (198 loc) · 6.28 KB

API Documentation

This document describes the current public API of MarkdownToAttributedString.

Core Types

MarkdownToAttributedString

High-level facade for parsing and converting Markdown.

public class MarkdownToAttributedString {
    public init()
    public init(configuration: MarkdownConfiguration)
    public func convert(_ markdown: String) -> NSAttributedString
    public func parse(_ markdown: String) -> [MarkdownElement]
    public func convert(_ elements: [MarkdownElement]) -> NSAttributedString
}

Use this type when you want one simple entry point for both parsing and rendering.

MarkdownParser

Parses Markdown into block-level MarkdownElement values with richer child metadata.

public class MarkdownParser {
    public init()
    public func parse(_ markdown: String) -> [MarkdownElement]
}

AttributedStringConverter

Converts parsed elements into NSAttributedString.

public class AttributedStringConverter {
    public init(configuration: MarkdownConfiguration = .default)
    public func convert(_ markdown: String) -> NSAttributedString
    public func convert(_ elements: [MarkdownElement]) -> NSAttributedString
}

This class is public and can be used directly when you want to control the parse/render pipeline manually.

Configuration

MarkdownConfiguration

Configuration for all supported Markdown styles.

public struct MarkdownConfiguration {
    public let text: MarkdownStyle
    public let h1: MarkdownStyle
    public let h2: MarkdownStyle
    public let h3: MarkdownStyle
    public let h4: MarkdownStyle
    public let h5: MarkdownStyle
    public let h6: MarkdownStyle
    public let bold: MarkdownStyle
    public let italic: MarkdownStyle
    public let strikethrough: MarkdownStyle
    public let code: MarkdownStyle
    public let codeBlock: MarkdownStyle
    public let link: MarkdownStyle
    public let listPrefix: MarkdownStyle
    public let blockquote: MarkdownStyle

    public init(...)
    public static let `default`: MarkdownConfiguration
}

Default values currently match the implementation in MarkdownElement.swift:

MarkdownConfiguration(
    text: .init(),
    h1: .init(fontSize: 24, fontWeight: .bold),
    h2: .init(fontSize: 18, fontWeight: .bold),
    h3: .init(fontSize: 15, fontWeight: .bold),
    h4: .init(fontSize: 13, fontWeight: .bold),
    h5: .init(fontSize: 11, fontWeight: .bold),
    h6: .init(fontSize: 10, fontWeight: .bold),
    bold: .init(fontWeight: .bold),
    italic: .init(isItalic: true),
    strikethrough: .init(),
    code: .init(),
    codeBlock: .init(),
    link: .init(),
    listPrefix: .init(fontWeight: .semibold),
    blockquote: .init()
)

MarkdownStyle

Style configuration for a single Markdown element class.

public struct MarkdownStyle {
    public let fontSize: CGFloat
    public let fontWeight: FontWeight
    public let isItalic: Bool
    public let foregroundColor: MarkdownColor?

    public init(
        fontSize: CGFloat = 12,
        fontWeight: FontWeight = .regular,
        isItalic: Bool = false,
        foregroundColor: MarkdownColor? = nil
    )
}

FontWeight

public enum FontWeight {
    case regular
    case bold
    case medium
    case semibold
    case light
}

MarkdownColor

MarkdownColor is a platform typealias:

  • UIColor on iOS, tvOS, and watchOS
  • NSColor on macOS

Parsed Data Model

MarkdownElement

public struct MarkdownElement: Equatable {
    public let type: MarkdownElementType
    public let content: String
    public let range: Range<String.Index>?
    public let children: [MarkdownElement]
    public let info: String?
    public let nestingLevel: Int

    public init(
        type: MarkdownElementType,
        content: String,
        range: Range<String.Index>? = nil,
        children: [MarkdownElement] = [],
        info: String? = nil,
        nestingLevel: Int = 0
    )
}

Important fields:

  • content: normalized textual content for the element
  • children: nested inline elements, used for paragraphs, headers, emphasis, and links
  • info: extra metadata, currently used for fenced code block info strings like swift
  • nestingLevel: indentation-derived list or blockquote depth

MarkdownElementType

public enum MarkdownElementType: Equatable {
    case text
    case header(level: Int)
    case bold
    case italic
    case strikethrough
    case code
    case codeBlock
    case link(title: String, url: String)
    case image(title: String, url: String)
    case unorderedList(content: [MarkdownElement])
    case orderedList(number: Int, content: [MarkdownElement])
    case lineBreak
    case paragraph
    case blockquote(content: [MarkdownElement])
    case table(headers: [String], rows: [[String]])
}

table exists in the public model but the current parser does not emit table nodes yet.

String Convenience API

public extension String {
    func toAttributedString(
        configuration: MarkdownConfiguration = .default
    ) -> NSAttributedString
}

Example:

let attributed = "# Title".toAttributedString()

Rendering Notes

Current rendering behavior:

  • links receive the .link attribute when the URL can be converted to URL;
  • images render as text placeholders like 🖼️ Alt text;
  • fenced code blocks render only their body, without the fence markers;
  • nested emphasis is supported for the common cases covered by the tests;
  • block elements are separated with newlines by the converter.

Example Workflow

import MarkdownToAttributedString

let parser = MarkdownParser()
let elements = parser.parse("""
# Title
- One
  - Two
""")

let converter = AttributedStringConverter(configuration: .default)
let attributedString = converter.convert(elements)

Best Practices

  • Cache converted output if the same Markdown is rendered often.
  • Prefer a focused custom MarkdownConfiguration over post-processing attributes later.
  • Add regression tests when changing parser behavior, because Markdown edge cases are easy to break.

Current Scope

Good fit:

  • app knowledge bases;
  • rich text snippets;
  • AI/chat responses with common Markdown;
  • export to plain text or RTF through NSAttributedString.

Not yet implemented:

  • tables;
  • image attachments;
  • full CommonMark or GFM compatibility.