The renderer is responsible for converting parsed contents into html files. It uses clostache templates from a selectable theme folder to create them.
(ns sidenotes.renderer
(:require
[sidenotes.fs :as fs]
[markdown.core :as md]
[clojure.edn :as edn]
[clojure.string :as string]
[clostache.parser :as mustache]))
The folder where internal themes can be found.
(def theme-base "themes/")
The list of internal themes. It would be much nicer if this could be automatically read from the resources of the jar, but so far I have no idea how that could be done.
(def internal-themes ["marginalia" "sidenotes"])
Check that itm is not in itms.
(defn in? [itm itms] (not (false? (nil? (some #(= itm %) itms)))))
Check if an external theme is sane. It needs to have theme.edn, toc.html and ns.html files.
(defn external-theme-valid?
[theme-name]
(and
(fs/dir? theme-name)
(fs/file? (str theme-name "/theme.edn"))
(fs/file? (str theme-name "/toc.html"))
(fs/file? (str theme-name "/ns.html"))))
(def message-theme-invalid "The theme you have provided is not valid. Make sure that it contains the following files: theme.edn toc.html ns.html")
Check if the provided theme is external.
(defn external-theme? [theme-name] (in? theme-name internal-themes))
Find the path to the used theme.
(defn find-theme
[theme-name]
(if (external-theme? theme-name)
theme-name
(str theme-base theme-name)))
Transform a dependency so mustache can handle it.
(defn transform-dependency
[dep]
{:name (first dep)
:is-mvn (not (nil? (:mvn/version (second dep))))
:version (:mvn/version (second dep))
:is-git (not (nil? (:git/url (second dep))))
:url (:git/url (second dep))
:sha (:sha (second dep))})
Transform the list of dependencies for mustache.
(defn transform-dependencies [deps] (map transform-dependency deps))
Get markdown for an error.
(defn error-md [section] (str "###ERROR\\n" (:error section)))
Convert stacktrace to code.
(defn stacktrace-code [exception] (string/join "\\n" (map str (.getStackTrace exception))))
Transform the comments and parse contained markdown.
(defn transform-section
[section]
(case (:type section)
:error (assoc section :docstring (md/md-to-html-string (error-md section)) :raw (stacktrace-code (:exception section)))
:code (assoc section :docstring (md/md-to-html-string (:docstring section)) :span false)
:comment (assoc section :docstring (md/md-to-html-string (:raw section)) :raw "" :span true)))
Transform the comments and parse contained markdown.
(defn transform-parsed-source
[parsed-source]
(assoc parsed-source
:sections (map transform-section (:sections parsed-source))
:is-cljs (= "cljs" (:type parsed-source))
:is-cljc (= "cljc" (:type parsed-source))
:is-clj (= "clj" (:type parsed-source))))
Check if a readme exists and contains markdown. If so convert it to html.
(defn transform-readme
[readme]
(if (and (:has-readme readme) (= "md" (:type readme)))
(assoc readme :html (md/md-to-html-string (:content readme)))
readme))
Build the parameters for the mustache templates.
(defn toc-template-parameters
[parsed-sources project settings readme]
{:settings settings
:dependencies (transform-dependencies (:deps project))
:readme (transform-readme readme)
:sources (map transform-parsed-source parsed-sources)})
Build the parameters for the mustache templates.
(defn ns-template-parameters
[parsed-source project settings]
{:settings settings
:dependencies (transform-dependencies (:deps project))
:source (transform-parsed-source parsed-source)})
Render the table of contents.
(defn render-toc
[parsed-sources project settings readme theme external]
(let [toc-file (str theme "/toc.html")
toc-template (if external (slurp toc-file) (fs/slurp-resource toc-file))
filename (str (:output-to settings) "/" (:toc-filename settings))
tmp (dorun (println (str "Creating table of contents: " filename)))
params (toc-template-parameters parsed-sources project settings readme)]
(spit filename (mustache/render toc-template params))))
Render the page for one namespace.
(defn render-ns
[parsed-source project settings theme external]
(let [ns-file (str theme "/ns.html")
ns-template (if external (slurp ns-file) (fs/slurp-resource ns-file))
filename (str (:output-to settings) "/" (:ns parsed-source) ".html")
tmp (dorun (println (str " ... rendering to " filename)))
params (ns-template-parameters parsed-source project settings)]
(spit filename (mustache/render ns-template params))))
Copy resources from theme to docs folder.
(defn copy-resources
[settings theme external]
(dorun (println "Copying resources:"))
(dorun
(map #(fs/spit-resource % theme (:output-to settings))
(:resources
(edn/read-string
(fs/slurp-resource (str theme "/theme.edn")))))))
Copy files from theme to docs folder.
(defn copy-files
[settings theme external]
(dorun (println "Copying resources:"))
(dorun
(map #(fs/copy-file % theme (:output-to settings))
(:resources
(edn/read-string
(slurp (str theme "/theme.edn")))))))
Render the documentation.
(defn render
[parsed-sources project settings readme]
(let [theme (find-theme (:theme settings))
external (external-theme? (:theme settings))]
(dorun (map #(render-ns % project settings theme external) parsed-sources))
(render-toc parsed-sources project settings readme theme external)
(if external
(copy-files settings theme external)
(copy-resources settings theme external))))