13-day longest streak
CocoaMarkdown Markdown parsing and rendering for iOS and macOS CocoaMarkdown is a cross-platform framework for parsing and rendering Markdown, built on top of the C reference implementation of CommonMark. Why?…
CocoaMarkdown
Markdown parsing and rendering for iOS and macOS
CocoaMarkdown is a cross-platform framework for parsing and rendering Markdown, built on top of the C reference implementation of CommonMark.
Why?
CocoaMarkdown aims to solve two primary problems better than existing libraries:
1. More flexibility. CocoaMarkdown allows you to define custom parsing hooks or even traverse the Markdown AST using the low-level API.
2. Efficient NSAttributedString creation for easy rendering on iOS and macOS. Most existing libraries just generate HTML from the Markdown, which is not a convenient representation to work with in native apps.


Installation
First you will want to add this project as a submodule to your project:
git submodule add https://github.com/indragiek/CocoaMarkdown.git
Then, you need to pull down all of its dependencies.
cd CocoaMarkdown
git submodule update --init --recursive
Next, drag the .xcodeproj file from within CocoaMarkdown into your project. After that, click on the General tab of your target. Select the plus button under "Embedded Binaries" and select the CocoaMarkdown.framework.
API
Traversing the Markdown AST
[CMNode](CocoaMarkdown/CMNode.h) and [CMIterator](CocoaMarkdown/CMIterator.h) wrap CommonMark's C types with an object-oriented interface for traversal of the Markdown AST.
swift
let document = CMDocument(contentsOfFile: path, options: [])
document.rootNode.iterator().enumerateUsingBlock { (node, _, _) in
print("String value: \(node.stringValue)")
}
Building Custom Renderers
The [CMParser](CocoaMarkdown/CMParser.h) class isn't _really_ a parser (it just traverses the AST), but it defines an NSXMLParser-style delegate API that provides handy callbacks for building your own renderers:
objective-c
@protocol CMParserDelegate
@optional
- (void)parserDidStartDocument:(CMParser *)parser;
- (void)parserDidEndDocument:(CMParser *)parser;
...
- (void)parser:(CMParser *)parser foundText:(NSString *)text;
- (void)parserFoundHRule:(CMParser *)parser;
...
@end
[CMAttributedStringRenderer](CocoaMarkdown/CMAttributedStringRenderer.h) is an example of a custom renderer that is built using this API.
Rendering Attributed Strings
[CMAttributedStringRenderer](CocoaMarkdown/CMAttributedStringRenderer.h) is the high level API that will be useful to most apps. It creates an NSAttributedString directly from Markdown, skipping the step of converting it to HTML altogether.
Going from a Markdown document to rendering it on screen is as easy as:
swift
let document = CMDocument(contentsOfFile: path, options: [])
let renderer = CMAttributedStringRenderer(document: document, attributes: CMTextAttributes())
textView.attributedText = renderer.render()
Or, using the convenience method on CMDocument:
swift
textView.attributedText = CMDocument(contentsOfFile: path, options: []).attributedStringWithAttributes(CMTextAttributes())
HTML elements can be supported by implementing [CMHTMLElementTransformer](CocoaMarkdown/CMHTMLElementTransformer.h). The framework includes several transformers for commonly used tags:
- [
CMHTMLStrikethroughTransformer](CocoaMarkdown/CMHTMLStrikethroughTransformer.h) - [
CMHTMLSuperscriptTransformer](CocoaMarkdown/CMHTMLSuperscriptTransformer.h) - [
CMHTMLSubscriptTransformer](CocoaMarkdown/CMHTMLSubscriptTransformer.h)
swift
let document = CMDocument(contentsOfFile: path, options: [])
let renderer = CMAttributedStringRenderer(document: document, attributes: CMTextAttributes())
renderer.registerHTMLElementTransformer(CMHTMLStrikethroughTransformer())
renderer.registerHTMLElementTransformer(CMHTMLSuperscriptTransformer())
textView.attributedText = renderer.render()
Customizing Attributed strings rendering
All attributes used to style the text are customizable using the [CMTextAttributes](CocoaMarkdown/CMTextAttributes.h) class.
Every Markdown element type can be customized using the corresponding CMStyleAttributes property in CMTextAttributes, defining 3 different kinds of attributes:
- String attributes, i.e. regular NSAttributedString attributes
- Font attributes, for easy font setting
- Paragraph attributes, relevant only for block elements
swift
let textAttributes = CMTextAttributes()
textAttributes.linkAttributes.stringAttributes[NSAttributedString.Key.backgroundColor] = UIColor.yellow
A probably better alternative for style customization is to use grouped attributes setting methods available in CMTextAttributes:
swift
let textAttributes = CMTextAttributes()
// Set the text color for all headers
textAttributes.addStringAttributes([ .foregroundColor: UIColor(red: 0.0, green: 0.446, blue: 0.657, alpha: 1.0)],
forElementWithKinds: .anyHeader)
// Set a specific font + font-traits for all headers
let boldItalicTrait: UIFontDescriptor.SymbolicTraits = [.traitBold, .traitItalic]
textAttributes.addFontAttributes([ .family: "Avenir Next" ,
.traits: [ UIFontDescriptor.TraitKey.symbolic: boldItalicTrait.rawValue]],
forElementWithKinds: .anyHeader)
// Set specific font traits for header1 and header2
textAttributes.setFontTraits([.weight: UIFont.Weight.heavy],
forElementWithKinds: [.header1, .header2])
// Center block-quote paragraphs
textAttributes.addParagraphStyleAttributes([ .alignment: NSTextAlignment.center.rawValue],
forElementWithKinds: .blockQuote)
// Set a background color for code elements
textAttributes.addStringAttributes([ .backgroundColor: UIColor(white: 0.9, alpha: 0.5)],
forElementWithKinds: [.inlineCode, .codeBlock])
List styles can be customized using dedicated paragraph style attributes:
swift
// Customize the list bullets
textAttributes.addParagraphStyleAttributes([ .listItemBulletString: "🍏" ],
forElementWithKinds: .unorderedList)
textAttributes.addParagraphStyleAttributes([ .listItemBulletString: "🌼" ],
forElementWithKinds: .unorderedSublist)
// Customize numbered list item labels format and distance between label and paragraph
textAttributes.addParagraphStyleAttributes([ .listItemNumberFormat: "(%02ld)",
.listItemLabelIndent: 30 ],
forElementWithKinds: .orderedList)
Font and paragraph attributes are incremental, meaning that they allow to modify only specific aspects of the default rendering styles.
Additionally on iOS, Markdown elements styled using the font attributes API get automatic Dynamic-Type compliance in the generated attributed string, just like default rendering styles.
Rendering HTML
[CMHTMLRenderer](CocoaMarkdown/CMHTMLRenderer.h) provides the ability to render HTML from Markdown:
swift
let document = CMDocument(contentsOfFile: path, options: [])
let renderer = CMHTMLRenderer(document: document)
let HTML = renderer.render()
Or, using the convenience method on CMDocument:
swift
let HTML = CMDocument(contentsOfFile: path).HTMLString()
Example Apps
The project includes example apps for iOS and macOS to demonstrate rendering attributed strings.
Contact
- Indragie Karunaratne
- @indragie
- http://indragie.com
License
CocoaMarkdown is licensed under the MIT License. See LICENSE for more information.
-
InAppViewDebugger ★ PINNED
A UIView debugger (like Reveal or Xcode) that can be embedded in an app for on-device view debugging
Swift ★ 1.9k 2y agoExplain → -
CocoaMarkdown ★ PINNED
Markdown parsing and rendering for iOS and OS X
Objective-C ★ 1.2k 6y agoExplain → -
INAppStoreWindow ★ PINNED
NSWindow subclass with a highly customizable title bar and traffic lights
Objective-C ★ 1.1k 10y agoExplain → -
DominantColor ★ PINNED
Finding dominant colors of an image using k-means clustering
Swift ★ 986 3y agoExplain → -
SwiftAutoLayout ★ PINNED
Tiny Swift DSL for Autolayout
Swift ★ 655 4y agoExplain → -
Context
Native macOS client for Model Context Protocol (MCP)
Swift ★ 799 5mo agoExplain → -
MarkdownTextView
Rich Markdown editing control for iOS
Swift ★ 704 9y agoExplain → -
uniprof
Universal CPU profiler designed for humans and AI agents
TypeScript ★ 407 4mo agoExplain → -
GHFS
Mount GitHub repositories as a virtual read-only macOS filesystem
Swift ★ 391 3mo agoExplain → -
SNRHUDKit
Code drawn AppKit HUD interface elements
Objective-C ★ 325 14y agoExplain → -
swiftrsrc
Resource code generation tool for Swift
Swift ★ 289 9y agoExplain → -
INDANCSClient
Objective-C Apple Notification Center Service Client
Objective-C ★ 251 12y agoExplain → -
INPopoverController
A customizable popover controller for OS X
Objective-C ★ 197 6y agoExplain → -
SNRSearchIndex
SearchKit backed search for Core Data
Objective-C ★ 191 11y agoExplain → -
Unzip
iOS 8 Action Extension for browsing ZIP files
Objective-C ★ 165 12y agoExplain → -
NSUserNotificationPrivate
Private API showcase for NSUserNotification on OS X
Objective-C ★ 154 12y agoExplain → -
SNRMusicKit
All-in-one framework for browsing and playing music from various sources on iOS and OS X
Objective-C ★ 148 10y agoExplain → -
WWDC-2014
Scholarship submission for WWDC 2014
Objective-C ★ 144 12y agoExplain → -
Ares
Zero-setup P2P file transfer between Macs and iOS devices
Swift ★ 134 10y agoExplain → -
INDockableWindow
A window to which other views can be "docked" to and separated into their own windows
Objective-C ★ 113 11y agoExplain → -
INDLinkLabel
A simple, no frills UILabel subclass with support for links
Swift ★ 82 8y agoExplain → -
SNRFetchedResultsController
Automatic Core Data change tracking for OS X (NSFetchedResultsController port)
Objective-C ★ 79 11y agoExplain → -
INDSequentialTextSelectionManager
Sequential text selection for NSTextViews
Objective-C ★ 76 12y agoExplain → -
OEGridView
High performance Core Animation-based grid view, originally from OpenEmu.
Objective-C ★ 72 3mo agoExplain → -
INDGIFPreviewDownloader
[iOS] Retrieves preview images for GIFs by downloading only the first frame
Objective-C ★ 60 11y agoExplain → -
Chip8
CHIP-8 emulator and disassembler written in Swift
Swift ★ 55 10y agoExplain → -
pdfcat
OS X utility for concatenating PDF files
Swift ★ 49 10y agoExplain → -
ReactiveXPC
Signals across process boundaries
Swift ★ 37 10y agoExplain → -
SwiftTableViews
Type-safe Table Views with Swift
Swift ★ 35 11y agoExplain → -
AlamofireRACExtensions
ReactiveCocoa Swift extensions for Alamofire
Swift ★ 33 11y agoExplain → -
ObjectiveKVDB
Objective-C wrapper for kvdb (https://github.com/dinhviethoa/kvdb)
Objective-C ★ 33 12y agoExplain → -
Dial
The beginnings of a replacement Contacts app for iOS.
Objective-C ★ 30 12y agoExplain → -
ReactiveBLE
ReactiveCocoa wrapper for communicating with BLE devices using CoreBluetooth
Objective-C ★ 29 12y agoExplain → -
INSOCKSServer
SOCKS5 proxy server implementation in Objective-C
Objective-C ★ 28 13y agoExplain → -
LiveWebPreview
Web development tool for automatically refreshing a page when the content changes.
Objective-C ★ 20 13y agoExplain → -
AttributedString.swift
Swift library that adds type safety and string interpolation support to NSAttributedString
Swift ★ 19 7y agoExplain → -
SNRLastFMEngine
[DEPRECATED] A modern block-based Objective-C interface to the Last.fm API
Objective-C ★ 19 14y agoExplain → -
INKeychainAccess
[DEPRECATED] Objective-C Keychain Services Wrapper for OS X and iOS
Objective-C ★ 17 6y agoExplain → -
INTrafficLightsDisabler
SIMBL plugin to hide the traffic lights on Mac OS X
Objective-C ★ 15 14y agoExplain → -
tecs
Projects for The Elements of Computing Systems by Nisan and Schocken
Assembly ★ 15 9y agoExplain → -
indragie.com
My personal website and blog, built with Next.js
TypeScript ★ 11 9mo agoExplain → -
BCCollectionView ⑂
A more versatile, faster and lighter replacement for NSCollectionView
Objective-C ★ 11 14y agoExplain → -
pebble-lifx
Pebble controller for LIFX bulbs. UAlberta CompE Club Hackathon 2014 project.
Objective-C ★ 11 12y agoExplain → -
xcode-themes
Color themes for Xcode 4 and 5
★ 6 13y agoExplain → -
radars
Apple Radars filed for OS X and iOS.
Objective-C ★ 5 6y agoExplain → -
rgen ⑂
Resource code generator for OS X inspired by Android resource handling
Objective-C ★ 4 13y agoExplain → -
arduino-copter
Copter game for Arduino + Adafruit TFT
C++ ★ 3 12y agoExplain → -
SwiftUIViewRecorder ⑂
Efficiently record any SwiftUI View as image or video
★ 3 5y agoExplain → -
Formalist ⑂
Declarative form building framework for iOS
Swift ★ 3 10y agoExplain → -
bootstrap-no-responsive
Compiled Bootstrap with responsive features disabled
★ 2 12y agoExplain → -
advent-of-code-2020
My Rust solutions for https://adventofcode.com
Rust ★ 2 5y agoExplain → -
XMPPFramework ⑂
An XMPP Framework in Objective-C for Mac and iOS
Objective-C ★ 2 11y agoExplain → -
writing
Things that I write
★ 2 11y agoExplain → -
Neon ⑂
A Swift library for efficient, flexible content-based text styling
★ 1 1y agoExplain → -
cache ⑂
Simple cache with expirable values
Go ★ 1 11y agoExplain → -
Alamofire ⑂
Elegant HTTP Networking in Swift
Swift ★ 1 11y agoExplain → -
StackViewController ⑂
A controller that uses a UIStackView and view controller composition to display content in a list
Swift ★ 1 10y agoExplain → -
iOS-messaging-tools ⑂
No description.
★ 1 6y agoExplain → -
ringbuf ⑂
Lock-free ring buffer (MPSC)
C ★ 1 7y agoExplain → -
lz4_stream ⑂
A C++ stream using LZ4 (de)compression
★ 1 6y agoExplain → -
ctak ⑂
A small test for multithreaded C++ stack unwinding on unixes
★ 1 6y agoExplain → -
index-import ⑂
Tool to import swiftc and clang index-store files into Xcode
★ 1 6y agoExplain → -
zstr ⑂
A C++ header-only ZLib wrapper
C++ ★ 1 7y agoExplain → -
swift-concurrency ⑂
Concurrency utilities for Swift
Swift ★ 1 7y agoExplain → -
DDHotKey ⑂
Simple Cocoa global hotkeys
★ 1 6y agoExplain → -
TUSafariActivity ⑂
A UIActivity subclass that opens URLs in Safari
Objective-C ★ 1 7y agoExplain → -
componentkit ⑂
A React-inspired view framework for iOS.
Objective-C++ ★ 1 9y agoExplain → -
OHHTTPStubs ⑂
Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!
Objective-C ★ 1 11y agoExplain → -
cloudapp-sdk ⑂
CloudApp's first-party Objective-C API wrapper
Objective-C ★ 1 13y agoExplain → -
ORCDiscount ⑂
Objective-C framework wrapping the discount library
C ★ 1 11y agoExplain → -
STTextView-Plugin-Neon ⑂
Source Code Syntax Highlighting
C ★ 0 1y agoExplain → -
duckdb ⑂
DuckDB is an in-process SQL OLAP Database Management System
C++ ★ 0 3y agoExplain → -
profilo ⑂
A library for performance traces from production.
★ 0 3y agoExplain → -
Mensa ⑂
Smart, modern table and collection views on iOS.
Objective-C ★ 0 12y agoExplain → -
Commandant ⑂
Type-safe command line argument handling
Swift ★ 0 11y agoExplain → -
ReactiveCocoa ⑂
A framework for composing and transforming streams of values
Objective-C ★ 0 11y agoExplain → -
farbtastic ⑂
jQuery Color Wheel
JavaScript ★ 0 12y agoExplain → -
RMPhoneFormat ⑂
RMPhoneFormat provides a simple to use class for formatting phone numbers in iOS apps. The formatting should replicate what you would see in the Contacts app for the same phone number.
Objective-C ★ 0 12y agoExplain → -
countly-sdk-ios ⑂
Countly Mobile Analytics - iOS SDK
Objective-C ★ 0 12y agoExplain →
No repos match these filters.
More creators on gitmyhub
brunosimon douglascrockford standardgalactic AlexTheAnalyst MorvanZhou