Cljdoc offers a centralized hosted library of docs which are:
-
Easy to publish
-
Automatically stay up to date
-
Discoverable by users
-
Look good
If you publish your library to Clojars, its docs should already be available (or available to build) on cljdoc.org.
Default handling:
-
API automatically documented
-
Articles include
README
,CHANGELOG
and articles underdoc/
(elsedocs/
), see auto-inferred articles
When cljdoc is triggered to build your library’s documentation, it:
-
Downloads your library’s release jar from Clojars
-
Analyzes your library’s sources on git
-
Analyzes your library’s jar to discover its public API.
After building your docs, they are available at cljdoc.org for online and offline browsing.
See also: System Overview.
Cljdoc supports two markup formats:
-
Markdown for API docstrings and
.md
articles-
We use flexmark-java to render a GitHub flavored CommonMark dialect.
-
-
AsciiDoc for
.adoc
articles-
We use AsciidoctorJ to render AsciiDoc.
-
Important
|
The following examples use |
-
Badge URL:
https://cljdoc.org/badge/metosin/malli
-
Docs homepage URL:
https://cljdoc.org/d/metosin/malli
Expressed in Markdown:
[![cljdoc badge](https://cljdoc.org/badge/metosin/malli)](https://cljdoc.org/d/metosin/malli)
and AsciiDoc:
https://cljdoc.org/d/metosin/malli[image:https://cljdoc.org/badge/metosin/malli[cljdoc badge]]
Cljdoc starts with the release jar downloaded from Clojars.
A jar is associated with its specific git revision of sources via the <scm>
entry in the jar’s pom
.
This allows cljdoc to consult git hosted:
-
cljdoc config - options on how cljdoc should process your docs
-
articles - to include and present as part of your docs
-
sources files - to allows cljdoc to intelligently link back to articles, API source code, and your git repo
Tip
|
a valid pom <scm> also allows other services like Clojars to point back to your release’s sources.
|
Note
|
|
An example <scm>
entry from metosin/malli
:
<scm>
<url>https://github.com/metosin/malli</url>
<connection>scm:git:git://github.com/metosin/malli.git</connection>
<developerConnection>scm:git:ssh://[email protected]/metosin/malli.git</developerConnection>
<tag>0.8.4</tag>
</scm>
Another from juxt/bidi
:
<scm>
<url>https://github.com/juxt/bidi</url>
<connection>scm:git:git://github.com/juxt/bidi.git</connection>
<developerConnection>scm:git:ssh://[email protected]/juxt/bidi.git</developerConnection>
<tag>d1bfcc9c4fe247b8ada19cd7ee25acd81dd93f26</tag>
</scm>
Cljdoc will look at the <url>
and the <tag>
:
-
<url>
points to your hosted git repo -
<tag>
is a valid pointer to the git commit of your release’s sources. It can be a git tag, or commit sha.
Here are some common ways folks set <scm>
values:
-
By hand. You can edit a
pom.xml
manually when cutting a release, but this can be error-prone. -
Clojure tools build can be asked to populate the
<scm>
value. Cybermonday provides a good example of doing just that. -
Leiningen will automatically create the
<scm>
entry for you if you set the:scm
in yourproject.clj
. For example::scm {:name "git" :url "https://github.com/your-github-org/your-project"}
-
Boot also has support, pass the
:scm
option to thepom
task, an example.
Whatever method you choose, take care to ensure that your jar’s pom points back to the exact revision of its sources on git.
When building your docs, cljdoc will look under the doc
(else docs
) directory for a cljdoc.edn
file in your library’s git repo.
You can use this configuration file to tell cljdoc more about your documentation.
-
:cljdoc.doc/tree
- Tells cljdoc what articles to present and in what hierarchy.
By default, cljdoc will automatically infer articles. -
:cljdoc/languages
- Tells cljdoc which languages your API uses.
By default, cljdoc will automatically detect languages based on the sources it finds in your jar. -
:cljdoc/include-namespaces-from-dependencies
- Tells cljdoc to amalgamate API docs from multiple modules.
Rarely used, but very useful when your project is made up of modules.
As an example, a version of honeysql's cljdoc.edn
{:cljdoc.doc/tree
[["Readme" {:file "README.md"}]
["Changes" {:file "CHANGELOG.md"}]
["Getting Started" {:file "doc/getting-started.md"}
["General Reference" {:file "doc/general-reference.md"}]
["SQL Clause Reference" {:file "doc/clause-reference.md"}]
["SQL Operator Reference" {:file "doc/operator-reference.md"}]
["SQL 'Special Syntax'" {:file "doc/special-syntax.md"}]
["PostgreSQL Support" {:file "doc/postgresql.md"}]
["Extending HoneySQL" {:file "doc/extending-honeysql.md"}]]
["Differences from 1.x" {:file "doc/differences-from-1-x.md"}]]}
See also: badges.
-
When linking from article to article, use relative or root-relative links. Cljdoc will rewrite built article to article links automatically. Markdown examples:
-
[root relative link](/doc/some-doc.md)
-
[relative link](other-doc.md)
-
-
When linking from docstring to article, use root relative links. Markdown example:
-
[root relative link](/doc/some-doc.md)
-
-
When linking from outside your git repo:
-
doc home page
-
a specific doc in the current release, uses article slugs
-
a specific doc for release
0.7.5
, uses article slugs
-
-
When linking from docstring to API docs, use the
[[wikilink]]
-
When linking from article to API docs, or from outside your git repo:
-
link to var
malli.core/explain
in current release -
link to namespace
malli.core
in release 0.7.5
-
Cljdoc will document all namespaces and public vars it finds.
To exclude namespaces and/or vars from API documentation, annotate them with :no-doc
metadata:
(defn ^:no-doc hidden "Won't see me on cljdoc.org!" [x])
(ns ^:no-doc namespace.hidden
"This ns shouldn't show in the docs.")
(ns namespace.hidden
"This ns shouldn't show in the docs."
{:no-doc true})
Cljdoc will auto-detect which languages your library supports based on the types of source files it finds.
You can choose to override this auto-detection in your doc/cljdoc.edn
file via the :cljdoc/languages
option.
Example :cljdoc/languages value |
API Analysis run for |
---|---|
|
Clojure only |
|
ClojureScript only |
|
Both Clojure and ClojureScript |
|
Dependent upon source files found in your library, the default behavior. |
Example usage:
{:cljdoc/languages ["clj"]}
Cljdoc discovers your API via dynamic runtime analysis. It will try to load all namespaces found in your jar. If a dependency is not found, the load, and therefore API analysis, will fail.
If you include namespaces that require additional/optional dependencies, make sure you declare them in your pom.xml
.
If these dependencies are expected to be provided by, for example, some container or JVM, mark them with a scope
of "provided"
in our pom.xml
.
Provided dependencies are skipped at runtime, but inform cljdoc they are required for API analysis.
Tip
|
You can express provided in a project.clj , for example.
The deps.edn file does not support scoping, you’ll have to express these directly in your pom.xml .
|
Docstrings are rendered as Markdown. Consider these recommendations when writing your docstrings:
-
Backtick-Quote
`
function arguments & special keywords tomake
themstand
outmore
-
Link to other functions using
[[wikilink]]
syntax -
Include small examples using markdown fenced
```Clojure … ```
code blocks -
Use Markdown tables to describe complex options maps
-
You can include images and links to articles, just be sure to use git repo root-relative links (links that start with a
/
):-
![my image](/dir1/dir2/image1.png)
-
[my article](/dir1/dir2/article.adoc)
-
Any HTML embedded within docstrings is escaped.
You can link to other namespaces and functions from your docstrings using the [[wikilink]]
syntax.
Note that if you want to link to vars outside the current namespace you need to either fully qualify those vars or specify them relative to the current namespace. An example: if you want to link to compojure.core/GET
from compojure.route
you’ll need to provide the wiki in one of the two forms below:
[[compojure.core/GET]] [[core/GET]]
Libraries often include additional guides and tutorials in markup files. Cljdoc calls these articles.
For cljdoc to find your articles:
-
They must be stored inside your project’s git repository
-
Your git repository must be properly linked to your git sources
This allows cljdoc to retrieve article files at the revision/commit of the release.
Cljdoc hosted articles will have their links rewritten to link back to cljdoc. All links that work on GitHub should also work on cljdoc.
If your git repository does not contain a doc tree configuration, cljdoc will automatically include:
-
README.md
elseREADME.adoc
- filename search is case insensitive-
Title is
Readme
-
-
CHANGELOG.md
elseCHANGELOG.adoc
- filename search is case insensitive-
Title is
Changelog
-
-
Markup articles from your
doc/
elsedocs/
folder-
The title is read from the file’s first heading. There will be no nesting and articles will be ordered alphabetically by filename.
-
Tip
|
Use filenames prefixed with digits like 01-intro.md to define the order of articles.
|
If you need more control, use a doc/cljdoc.edn
file to specify a tree of articles.
Assuming you have a directory doc/
in your repository as follows:
doc/ getting-started.md installation.md configuration.md
You can explicitly add these articles to your cljdoc build by with the following doc/cljdoc.edn
file:
{:cljdoc.doc/tree [["Readme" {:file "README.md"}]
["Getting Started" {:file "doc/getting-started.md"}
["Installation" {:file "doc/installation.md"}]]
["Configuration" {:file "doc/configuration.md"}]]}
Your articles will be presented with the following hierarchy and titles:
├── Readme ├── Getting Started │ └── Installation └── Configuration
Important
|
The resulting URLs for those articles will be based on the title provided in the cljdoc.edn file and not on the filename or title within the article file.
|
See also: verifying articles
Slugs for articles are currently based on the article title. Titles can be explicitly configured or inferred.
Similar to env-github
on GitHub, cljdoc will set an env-cljdoc
attribute when
rendering your AsciiDoc file. This allows you to hide or show sections
of your document or set configuration parameters.
As an example, this AsciiDoctor snippet:
ifdef::env-cljdoc[]
THIS WILL BE SHOWN ON CLJDOC
endif::[]
ifndef::env-cljdoc[]
THIS WILL BE SHOWN EVERYWHERE ELSE
endif::[]
will render as so:
THIS WILL BE SHOWN EVERYWHERE ELSE
You can preview what your docs will look like before a Clojars release by running cljdoc locally.
If you are already publishing SNAPSHOT
releases to Clojars, this can also be a useful way to experiment/preview on cljdoc.
A SNAPSHOT
release will use master
as the git revision as they usually have no tag in your repo nor sha/tag in a pom
scm
.
Sometimes people forget to update the paths after moving files around, we recommend you add the following to your CI setup:
curl -fsSL https://raw.githubusercontent.com/cljdoc/cljdoc/master/script/verify-cljdoc-edn | bash -s doc/cljdoc.edn
We have a Cljdoc check action you can incorporate into your CI workflows.
-
Automatically
-
Every 60 seconds, cljdoc reaches out to clojars to discover new releases.
-
Every 10 minutes, it queues new releases to build
-
-
By request at cljdoc.org
-
If cljdoc has not already built a requested version of a library, you are given the option to build it from cljdoc.org.
-
-
By rebuild request at cljdoc.org
-
If your docs have already been built, you can request a rebuild via the barely visible rebuild hover link on the top right corner of your library docs page.
-
-
By REST request
-
An automated release process can trigger a build via rest trigger a cljdoc build via REST.
-
Some libraries are made up of submodules. Cljdoc provides some support amalgamating docs for these types of libraries.
To include API documentation for some or all of a projects submodules, specify their maven coordinates under :cljdoc/include-namespaces-from-dependencies
:
{:cljdoc/include-namespaces-from-dependencies
[metosin/reitit
metosin/reitit-core
metosin/reitit-ring
metosin/reitit-spec
metosin/reitit-schema
metosin/reitit-swagger
metosin/reitit-swagger-ui]}
Note
|
To be included, each dependency must also be specified as a maven dependency of the project itself (in the project’s deps.edn , project.clj , etc).
The project’s resulting POM file will be used to load API information for the correct version.
|
Tip
|
Reitit is a great example reference for a project with submodules. |
Warning
|
If analysis for a specified dependency has failed or hasn’t been run, its API documentation will not appear on cljdoc. |
The following example shows how to provide a different doc tree for project metosin/reitit
via cljdoc.edn
:
{
;; used for metosin/reitit
;; when building docs for metosin/reitit this will be used as if
;; the doc/cljdoc.edn file contained just the value of this key
metosin/reitit {:cljdoc.doc/tree [["Introduction" {:file "intro.md"}]]}
;; used for any project except metosin/reitit
;; could contain an overview about all modules and a pointer
;; to the overarching documentation for metosin/reitit
:cljdoc.doc/tree [["Overview" {:file "modules/README.md"}]]
}
Note
|
We haven’t found an example usage of this in the wild yet. |