Swift Markdown Kit · DOCS
Reference
Reference
Views and controllers
| Type | Use |
|---|---|
MarkdownRenderView | SwiftUI, one document. |
MarkdownRenderViewController | UIKit, one document. |
MarkdownChatRenderView | SwiftUI, a whole conversation. |
MarkdownChatRenderViewController | UIKit, a whole conversation. |
MarkdownChatRenderProxy | Imperative control of a SwiftUI chat view. |
MarkdownRenderKit | version, bridgeVersion, licenseDiagnostics(). |
Document methods
render(_:) · renderStream(_:) · startStreaming() ·
appendChunk(_:isFinal:) · finishStreaming() · clear() · reload() ·
contentHeight · licenseStatus
Conversation methods
setMessages(_:) · appendMessage(_:) · updateMessage(_:) ·
appendChunk(_:to:isFinal:) · appendReasoningChunk(_:to:isFinal:) ·
finishReasoning(for:) · setReasoningExpanded(_:for:) ·
finishMessage(_:) · removeMessage(_:) · clear() ·
scrollToBottom(animated:) · contentHeight · licenseStatus
MarkdownRenderOptions
| Option | Default | Meaning |
|---|---|---|
colorScheme | .auto | .auto, .light, .dark. |
theme | .system | .system or .github, plus token overrides. |
extensions | [] | Custom inline syntax. |
interaction | .automatic | Who handles link and image taps. |
isScrollEnabled | true | Off when embedding inside your own scroll view. |
backgroundColor | .clear | Renderer background. |
contentPadding | 16pt all round | Inset between content and edges. |
bottomGap | 0 | Extra space under the last block, for an overlaying composer. |
markdown | see below | Parser capabilities. |
streamingMode | .incremental | .fullRerender re-renders everything on each flush. |
longBlockStreaming | .throttled | .deferred holds a long block until it completes. |
longBlockThreshold | 512 | Characters before the strategy applies. |
baseFontSize | 16 | Before Dynamic Type scaling. |
respectsDynamicType | true | Follow the system text size. |
minFontScale / maxFontScale | 0.85 / 1.6 | Clamp on the Dynamic Type multiplier. |
heightChangeDebounceInterval | 0.08 | Debounce on height reporting while streaming. |
copyText / copiedText / copyFailedText | localized | Code block copy button labels. Default to the reader's language — see Localization. |
MarkdownRenderLocalization
The language the SDK draws its own strings in, and the strings themselves. Full detail in Localization.
| Member | Meaning |
|---|---|
language | .automatic (default, follows the device), .english, .simplifiedChinese, .custom(_:). |
availableLanguages | Localization codes this build ships, e.g. ["en", "zh-Hans"]. |
codeCopy / codeCopied / codeCopyFailed | Code block copy button, resolved. |
messageCopy / messageCopied / messageRetry / messageEdit | Message action accessibility labels, resolved. |
reasoningThinking / reasoningCompleted / reasoningDuration | Reasoning fold headers, resolved. |
MarkdownRenderOptions.MarkdownConfig
| Option | Default |
|---|---|
allowRawHTML | false |
linkify | true |
typographer | true |
breaks | false |
taskLists | true |
emoji | true |
math | true |
reasoning | enabled |
MarkdownChatRenderOptions
| Option | Default | Meaning |
|---|---|---|
renderOptions | — | The document options above, applied to every message. |
interaction | .automatic | Shorthand for renderOptions.interaction. |
reasoning | enabled | The reasoning fold. |
messageActions | copy only | Per-message toolbar. |
streamingPresentation | .smooth | .immediate shows each chunk as it lands. |
autoScrollBehavior | .nearBottom | .always, .never. |
preservesUserScroll | true | Stop following once the reader scrolls up. |
bottomThreshold | 96 | Points from the bottom that still count as "at the bottom". |
messageSpacing | 14 | Points between messages. |
maxMessageWidth | .full | Width of the reading column. |
userMessageMaxWidth | .fraction(0.82) | Width of the user's own bubbles. |
chunkCoalescingInterval | 1/30 s | Gather tokens before crossing into the web view; 0 disables. |
Events
MarkdownRenderEvent for documents, MarkdownChatRenderEvent for
conversations. The chat variant adds viewportChanged and messageAction, and
wraps actions with the message id they came from.
| Event | Fires when |
|---|---|
.ready | The renderer finished loading and queued commands start running. |
.rendered(height:) | Exactly twice per content cycle: first paint, and the final flush. |
.heightChanged(_) | Height changed in between — streaming, image loads, Dynamic Type. Debounced while streaming. |
.viewportChanged(_) | Scroll position and whether the reader is near the bottom. |
.messageAction(_) | Copy, retry or edit tapped on a message. |
.action(_) | Everything below. |
.error(_) | A structured failure carrying a stable code. |
Actions
Requests — nothing happens unless you act:
| Action | Meaning |
|---|---|
.linkTapped(URL) | A link was tapped and interaction.links is .handledByHost. |
.imageTapped(URL?) | An image was tapped and interaction.images is .handledByHost. |
.extensionTapped(name:action:value:) | A custom inline extension was tapped. |
.custom(name:payload:) | An unrecognised bridge message. |
Notifications — the SDK already acted:
| Action | Meaning |
|---|---|
.didOpenLink(URL) | Opened in the in-app browser, or handed to the system for mailto/tel. |
.didPresentImage(URL) | The built-in viewer was presented. |
.linkBlocked(url:scheme:) | The scheme is not in allowedLinkSchemes; nothing was opened. |
.codeCopied(text:language:) | Copied to the pasteboard. |
.codeCopyFailed(text:language:error:) | Copy failed. |
.reasoningToggled(isExpanded:) | The reader opened or closed a reasoning fold. |
.taskToggled(isChecked:text:) | A task list checkbox changed. |
Errors
MarkdownRenderError carries reason, a human-readable message, and a stable
code suitable for logging.
| code | Meaning |
|---|---|
licenseMissing | No .smklicense in Copy Bundle Resources. |
licenseInvalid | Wrong envelope format, bad signature, or malformed payload. |
licenseUnknownSigningKey | Signed by a key this SDK does not trust — usually a test license paired with a production build. |
licenseWrongIssuerEnvironment | Issued by the sandbox issuer; a production SDK accepts production only. |
licenseUnauthorizedTeamId | The app's signing team does not match the license. |
licenseTeamIdentifierUnavailable | The Team ID could not be read — expected on the Simulator. |
licenseUnauthorizedBundleId | The bundle identifier is not covered by the license. |
expiredTrialLicense | A trial license past its validUntil. |
sdkReleaseNotCovered | This SDK build was released after the license's updatesUntil; renew to use it. |
releaseMetadataMissing | The framework is missing its release metadata — a broken build. |
resourceMissing / resourceInvalid / resourceKeyInvalid / resourceDecryptionFailed | The bundled render core could not be loaded. |
webViewLoadFailed | The web view failed to load the renderer. |
webContentProcessTerminated | WebKit reclaimed the content process; the SDK reloads and replays automatically. |
renderFailed / serializationFailed / copyFailed | A runtime operation failed. |
Every license* code is a diagnostic, not a failure. Rendering continues;
the build is badged. See Licensing.
Versioning
MarkdownRenderKit.version // SDK version, e.g. "0.0.10"
MarkdownRenderKit.bridgeVersion // native ↔ web message contract version
The framework ships with library evolution enabled. Within a major version, public declarations are only ever added — an app compiled against an earlier build keeps linking against a later one without being rebuilt.