I’ve been working on making Apex (my ultimate Markdown processor) easier to integrate into Xcode projects, and I’m excited to share what’s new. The biggest change is full Swift Package Manager (SPM) support, which makes adding Apex to your project as simple as clicking a button in Xcode.
While Apex is still in a 0.x state, I don’t suggest it be used in production, but if developers want to start testing it out in an application scenario, it should be easy to load in a Mac or iOS app. Once it gets to 1.0, it will be a lot less likely to have breaking changes, and the API won’t change in the 1.x series. I don’t foresee many, if any, changes to the API moving forward, but we’ll see how reception goes and what feedback arises.
Swift Package Manager Support
The easiest way to add Apex to your Xcode project now is through Swift Package Manager. Just open your project, go to the Package Dependencies tab, and add the Apex repository. Xcode handles the rest.
import Apex
let markdown = "# Hello World"
let html = markdown.apexHTML()
That’s it. No framework dragging, no manual linking, no build configuration tweaks. SPM takes care of everything.
The package supports both macOS 10.13+ and iOS 11+, so you can use Apex in your iOS apps too. I’ve bundled libyaml as part of the package to make iOS support work seamlessly, with worrying about system library dependencies.
Framework Build Options
If you prefer the traditional framework approach, that still works too. The CMake build now includes a module map in the framework, which means Swift can import the C API directly if you need it. The framework build is still the way to go if you’re integrating with existing CMake projects or need more control over the build process.
cmake -DBUILD_FRAMEWORK=ON ..
make
The framework gets installed to /Library/Frameworks by default, or you can customize the install location.
Better Swift Integration
I’ve improved the Swift API wrapper to make it more idiomatic. The ApexOptions struct now has a public initializer, so you can create options instances directly:
var options = ApexOptions()
options.pretty = true
options.generateHeaderIDs = true
let html = markdown.apexHTML(mode: .gfm, options: options)
The bridging between Swift and Objective-C has been cleaned up too. All the category methods on NSString are now properly accessible from Swift, so you get the full API surface without any awkward workarounds.
Module Map for Direct C Access
If you need to use the C API directly from Swift, there’s now a module map that makes it straightforward:
import Apex
let opts = apex_options_default()
opts.pretty = true
// ... configure options ...
let html = apex_markdown_to_html(markdown, markdown.count, &opts)
This is useful if you need fine-grained control or want to use features that aren’t exposed through the higher-level Swift API yet.
Testing It Out
I’ve included a test script (test_spm.sh) that creates a temporary test project and verifies everything works. It does a clean build each time, so you can be confident the package builds correctly from scratch.
The script tests all the main integration points—basic conversion, different modes, options, and standalone document generation.
One More Thing
While I was working on this, I also enabled emoji autocorrect by default in unified mode. So if you type :rocket: and it doesn’t quite match, Apex will try to find the closest match. It’s a small quality-of-life improvement that makes the emoji syntax a bit more forgiving.
The SPM package is ready to use in the latest release, and I’d love to hear how it works for you. If you run into any issues or have suggestions for improvements, let me know!
Learn more about Apex on the project page and in the Apex wiki. If you’re interested in Xcode integration, there’s a whole page for that.