DocC sans Xcode
Swift-DocC is a CLI tool to build HTML rendered documentation. It's goal is more than just reference documentation, but also long-form subjective content: tutorials, overviews, books - indeed, the Swift book itself is built with DocC, and that would be the workflow closest to what I have in mind currently (I want to use DocC to build the HTML for a standalone (to start with) Markdown file).
docc
comes with Xcode. To run, I can just use:
xcrun docc
Links:
-
Swift blog - DocC open-sourced
-
Swift blog - DocC builds the Swift book
Coming back to the workflow. Apple's documentation for Writing
Documentation
covers all sorts of things, but it talks of a "documentation catalog". The
docc
CLI tool also has a lot of juicy commands, however they seem to operate
on this documentation catalog, but how do we create one?
Looking at the source for the Swift Book,
we can see that a documentation catalog is just (I think) a folder with a
.docc
extension. It also seems to have an Info.plist
file (because of course
it does, this is Apple). So maybe it is easier if we create this catalog using
Xcode itself.
In our Xcode project, use the create new file dialog ⌘ N, press tab ⇥ to focus the search field, type "doc", and select the "Documentation Catalog".
It generates a new folder for us, with a single markdown file and an empty
folder. No Info.plist
! So that's not needed for the minimal setup. Maybe we
could've just done mkdir -p My.docc && touch My.docc/Hello.md
too.
So now that we have a documentation catalog, let us preview it:
xcrun docc preview Documentation.docc
Nice, it runs a preview server for us! We can open it at http://localhost:8080/. Right now it displays "An unknown error has occurred", but that's fine, that's better than those Unexpected Exceptions at least.
Now let us add some content. I'll create a minimal markdown, replacing the template because I think the double backticked symbol reference in the autogenerated markdown is making docc unhappy.
With a flourish, if we reopen our preview window in the browser, we see, um, the same error still. So that's a bit of a let down.
Coming back to the Terminal where we ran the docc preview
, we see indeed that
DocC is displeased at us, and is
warning: An article is expected to start with a top-level heading title
Let's add a title then. "My Dear Pony". Hmm, still nothing.
Maybe it doesn't like my juvenile kindergarten, sense of humor.
Let me give it a better title. I'll use the name of the project. But still I see
the same error. Worse, docc has even stopped complaining about anything in the
Terminal, it is just silently ignoring us. Maybe we do need that Info.plist
after all?
Let's copy paste the Info.plist from the Swift Book
into Documentation/Info.plist
. Still nothing.
Let's see if there's a way to get docc
to talk to us about what's wrong.
xcrun docc help preview
There's --diagnostic-level info
, but let's try the --analyze
first:
.../Documentation.docc/Documentation.md: note: You haven't curated \
'doc://org.swift.tspl/documentation/The-Swift-Programming-Language/Documentation'
Maybe it's complaining because we're using the bundle identifier of the Swift
book in the Info.plist
. Let's remove that and try again.
Ha! docc
crashes.
Maybe there isn't a way to build standalone articles using docc
? Or maybe the
way is there, but it is mentioned in some of the WWDC videos I haven't watched?
Think, Manav, think.
If I go back to Xcode, and Product > Build Documentation
action, it builds
documentation for the symbols in my actual code and shows them nicely. So it is
just misconfiguration somewhere.
From the Swift-DocC announcement post on Swift Forums :
At its core, the Swift-DocC compiler accepts two kinds of inputs:
A folder of additional content called the Documentation Catalog, which can include:
- Article files containing free-form Markdown describing a topic conceptually
- ...
- An
Info.plist
file containing metadata such as the name of the documented module. This file is optional and the information it contains can be passed via the command line.
So I think I need to figure out what is the Info.plist
file for me, instead of
just copy pasting randomly.
Let's clone the Swift book, and try to run the preview there:
git clone https://github.com/apple/swift-book.git
cd swift-book
xcrun docc preview TSPL.docc
Oops, this also gives the same error. The README mentions this should work:
Run docc preview TSPL.docc in this repository's root directory.
What am I doing wrong?
I think I need to give in trying to follow the documentation for using DocC, an irony I was trying to avoid, and instead search around on the internet.
Sure enough, I get this result in the Swift forums, someone hitting the similar roadblocks, and this encouraging reply:
Swift-DocC does indeed support building standalone documentation catalogs without an associated Swift module.
And they (the same person it seems who announced Swift-DocC) give a link to an example in the swift-docc repo, under Test fixtures. Let's give it a shot:
git clone https://github.com/apple/swift-docc.git
cd "swift-docc/Tests/SwiftDocCTests/Test Bundles"
xcrun docc preview BundleWithTechnologyRoot.docc
Nope, still the unknown error.
Finally, let me do what I should've done what as the first step - go to StackOverflow. And, indeed, there we find the solution :
DocC does not provide a "template" on its own. It expects it installed at a certain path that you don't have. You need to fetch the template and provide a path to it.
Let's follow the helpful instructions from the rest of the answer:
cd -
git clone https://github.com/apple/swift-docc-render-artifact
export DOCC_HTML_DIR=$(pwd)/swift-docc-render-artifact/dist
cd -
xcrun docc preview BundleWithTechnologyRoot.docc
It didn't work, but the error changed
The page you're looking for can't be found.
When I look more closely, the preview URL that docc
printed on the Terminal
now changed, and now has an additional path component. If I open
http://localhost:8080/documentation/technologyx instead, it works!
Let's try this on our original file too. Let's go back to our project, delete
the Documentation.docc
that we were tinkering with, and recreate it from
scratch.
mkdir Documentation.docc
echo World > Documentation.docc/Hello.md
xcrun docc preview Documentation.docc
Still doesn't work. Looks like we need something in there. After comparing with
BundleWithTechnologyRoot.docc
, I can find that if we create this minimal
Markdown:
# Hello
@Metadata {
@TechnologyRoot
}
World
paste it into a file, and run (remember, we have DOCC_HTML_DIR
defined from
above already):
pbpaste > Documentation.docc/Hello.md
xcrun docc preview Documentation.docc
It works indeed!
Reading around a bit more in the links I gave above, this time a bit more calmly
since I've already gotten it working, I realize it wasn't the DOCC_HTML_DIR
that was giving me trouble – that issue is for folks who're directly running
docc
. I'm running it via xcrun
, so that's not the problem. The problem was
that I was missing the @TechnologyRoot
.
Further, it looks like this problem (requiring @TechnologyRoot
) has already
been fixed on GitHub, just 4 days
ago! But that's on Swift-DocC
mainline, and I'm using the docc that comes with Xcode, so the fix will take a
while to get around to me. The good part is that future people will not to go
about this whole roundabout.
So this post is mostly pointless for posterity. It just stands testament to yet another hour that I just let be.
Jan 2024