Following up on @plexus’s autodoc presentation at the ClojureBerlin december meetup (great work!), Arne also briefly touched upon Elixir having a central documentation website, namely hexdocs.pm and whether we could accomplish the same for Clojure.
Over the holidays I thought I start hacking on it, it can’t be that difficult, right? Turns out, it probably is or I am missing something (which is equally likely). Spoiler: I didn’t get very far and thought it might be useful to collect some thoughts from more experienced Clojurists (= you) first before proceeding.
Hexdocs
The basic gist of hexdocs.pm is this:
- You release a new version of your library to hex.pm (the Elixir package repository), example: Ecto
- It automatically builds your docs and puts them up on hexdocs.pm, example: Ecto Docs where the “root” directory always points to the docs of the latest release
- Docs for old versions are archived in a directory with the name of the version, example: Ecto v2.2.4
- Yes, it’s that simple.
Clojure Sketch
So my basic sketch for Clojure was this:
- Get all packages from clojars
- Generate docs for all packages with codox
- Put them up on S3 or so.
Sounds naive? It is. Here are the nitty-gritty details:
-
(easy) Scrape clojars.org and get packages with version numbers
- Clojars has easy-to-process data available.
-
(hard) Run all packages through codox
-
We can’t rely on the source code being in the jar file, we therefore have to head over to the source repository as seen on clojars (mostly some GitHub link) and grab the source.Not all packages have GitHub links. Update: The.jars
from clojars actually include Clojure source code (99% of them), so that’s good news - After we’ve grabbed the source, we could in theory call
codox.main/generate-docs
with an options map which points to the directory. This will however fail for the following (obvious, but not to me initially) reasons:- codox expects the package for which the docs are to be generated to be on the classpath! Why? It
require
s each namespace as prerequisite for parsing it -
require
-ing a namespace assumes all dependencies are available and on the classpath
- codox expects the package for which the docs are to be generated to be on the classpath! Why? It
- I see three workarounds for this, all suboptimal in their own way:
- Write a complete codox alternative which parses the source files on a lower level without
require
-ing them (lots of work, doesn’t sound like a good idea). This would allow us to generate docs without having the dependencies available. My best guess is that marginalia does this. - Dynamically load a package and its dependencies via pomegranate before generating the docs: May not work for some packages. How to unload packages before we start loading the next package for the next doc generation cycle? In playing around with it, I couldn’t get it to work but it could totally be caused by eating too many leftover christmas cookies…
- Read the (leiningen) project.clj,
assoc
some codox options to it if missing and calllein codox
via the shell (clojure.java.shell/sh
), find the generated files, copy them somewhere and throw everything else away again (ugh).
- Write a complete codox alternative which parses the source files on a lower level without
-
I’m totally at a loss here and would appreciate your thoughts!
In short: How can we efficiently run codox (or something similar) on some random package without going through leiningen and / or having to download all its dependencies?
Some more random ideas
- We could not generate static html like all other doc sites do, but instead create a repository of “raw” codox maps which include all needed information (namespaces, functions, doc strings, lines, etc.). We could then archive these codox maps for each package version.
- (This would save space)
- We could then create a super-slim single-page app which queries this repository of “doc maps”, parses and displays them (parsing markdown etc).
- This would in theory allow for some super-neat features, like search queries over all functions of all libraries (because we have the data available somewhere), saving “favorites” and caching docs for offline usage (because it’s a SPA). We could also add some klipse in-browser-evaluation voodoo to the mix.