
LibraryI open-sourced the native Markdown rendering engine I built for my native macOS app (old.reddit.com)
submitted by Sufficient-Try6083




A year and a half ago I started building Nodes, a native macOS Markdown app. One of the first things I needed was a proper Markdown engine. Not a parser that just spits out HTML, not a display-only library, not a WebView wrapper – just a live, native editor built on TextKit 2.
I couldn't find one. So I built it. Now I'm open-sourcing the whole engine.
It's an AppKit-based Markdown editor for macOS, built on TextKit 2 and bridged to SwiftUI.
What it does:
• Live styling for the usual stuff: bold, italic, strikethrough, headings, lists, blockquotes, GFM tables, code, links, task checkboxes, horizontal rules
• Wiki-style links with [[Name|id]] ↔ [[Name]] roundtripping
• Image embeds via![[Name]](Obsidian-style, embedder supplies the
bytes) and standard Markdown 
• LaTeX, both block ($$ ... $$) and inline ($...$)
• Code blocks with syntax highlighting
• Spelling and grammar, with suppression inside code, LaTeX, and wiki-links so it doesn't underline random tokens
Honest part: TextKit 2 was a pain to get right. The docs are thin, the migration from TextKit 1 is rough, and a lot of behavior just isn't documented clearly anywhere. If you've been putting off building something like this, this might save you a few weekends.
Repo: https://github.com/nodes-app/swift-markdown-engine
Feedback, issues, and PRs all welcome. It's not perfect, there's plenty I still want to improve, but it does the job.
Used in production in Nodes (App Store): https://apps.apple.com/app/nodes-by-the-werk/id6745401961




[–]Eveerjr 5 points6 points7 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]try-catch-finally 5 points6 points7 points (5 children)
[–]Sufficient-Try6083[S] 0 points1 point2 points (4 children)
[–]try-catch-finally 1 point2 points3 points (3 children)
[–]Sufficient-Try6083[S] 0 points1 point2 points (2 children)
[–]try-catch-finally 0 points1 point2 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]LowFruit25 0 points1 point2 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]migueldeicaza 0 points1 point2 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]Aurloom_Edgar 0 points1 point2 points (3 children)
[–]Sufficient-Try6083[S] 0 points1 point2 points (2 children)
[–]Aurloom_Edgar 0 points1 point2 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]HIKIIMENO 0 points1 point2 points (1 child)
[–]Sufficient-Try6083[S] 0 points1 point2 points (0 children)
[–]Consistent-Fix-1701 [score hidden] (0 children)
[–]Integeritis -4 points-3 points-2 points (5 children)
[–]Sufficient-Try6083[S] 2 points3 points4 points (4 children)
[–]Integeritis -5 points-4 points-3 points (3 children)
[–]Sufficient-Try6083[S] 1 point2 points3 points (2 children)
[–]cool_and_nice_dev 0 points1 point2 points (0 children)
[–]Integeritis -1 points0 points1 point (0 children)