Namespaces
(ns docs-gen.transform
(:require [prone.debug :refer [debug]])
(:use [net.cgrand.enlive-html]
[clygments.core]))
Layout Helpers
Build Drop Down
Builds the site dropdown
(defn build-drop-down [site sites]
(let [websites (list "code" "dissertation")]
;Inorder to maintain site always as the first element in the row
;Alert: Pretty hacky
(clone-for [s (into [site] (remove #(= % site) sites))]
[:a] (if (= s site) (do-> (add-class "active")
(set-attr :href (str "/" s))
(content (clojure.string/capitalize s)))
(do-> (set-attr :href (str "/" s)) (content (clojure.string/capitalize s)))))))
Enlive Helpers
Update Attribute Helper
(defn update-attr [attr f & args]
(fn [node]
(if (get (:attrs node) attr)
(apply update-in node [:attrs attr] f args) node)))
Transform Inline URLs
Attach root site to inline URLs
(defn url-transform [root site url]
(cond
(.startsWith url "/") (str root url)
(.startsWith url "./") (str root "/" site (clojure.string/replace-first url #"." ""))
(.startsWith url "http") url
:else "Malformed"))
(defn attach-root [root site page]
(let [update-fn #(update-attr % (fn [current] (url-transform root site current)))]
(apply str (emit* (at (html-resource (java.io.StringReader. page))
[:a] (update-fn :href)
[:link] (update-fn :href)
[:img] (update-fn :src))))))
Navigation Helpers
(defn matches [k v m] (filter #(= (k %) v) m))
(defn meta-map [k]
(or ({:loc " LOC"
:words " Words"} k) "Unknown Metadata"))
(defn sum-count [m k v coll]
{:pre [(every? #(or (contains? % :loc) (contains? % :words)) coll)]}
(reduce + (map m (matches k v coll))))
(defn build-meta-strings [metadata k v coll]
(let [m (first metadata)]
(if (not-empty metadata)
(html [:span.count (str (sum-count m k v coll) (meta-map m))]) "")))
Check for presence of all
Duct tape functions.
(def clean-numbering #(clojure.string/replace % #"\d+-" ""))
Format Navigation Links
Helper functions to strip all numbers followed by a single hyphen. Used to format the URLs which have Kebab case.
(defn format-nav-links [word]
(clojure.string/join " " (map clojure.string/capitalize (clojure.string/split (clean-numbering word) #"-"))))
(defn rebuild-url [site s]
(let [format #(str "/" site "/" (apply str %) ".html")]
(format (interpose "/" (map clean-numbering ((juxt :category :title :subtitle) s))))))
(defn has-all-keys? [nav-entry]
(let [{:keys [category title subtitle]} nav-entry]
(every? #(not (nil? %)) (list category title subtitle))))
(defn leaf-nodes [nav]
(filter has-all-keys? nav))
Build Subtitles
(defn build-subtitles [titles title current-subtitle site]
(let [subtitles (matches :title title titles)]
(clone-for [s subtitles]
[:li :a.subtitle-link] (do-> (set-attr :href (rebuild-url site s))
(if (= (:subtitle s) current-subtitle)
(update-attr :class
(fn [& args]
(apply str (interpose " " args))) "active") identity)
(content (format-nav-links (:subtitle s))
(html [:span.count (str (:loc s))]))))))
Build Titles
(defn highlight-link [link-title title]
(if (= link-title title) (update-attr :class (fn [& args] (apply str (interpose " " args))) "active") identity))
(defn build-titles [link c metadata titles nav site]
(clone-for [t (distinct titles)]
[:li :a.title-link] (do-> (content (format-nav-links t) (build-meta-strings metadata :title t nav))
(highlight-link (:title link) t))
[:li :ul.subtitles] (build-subtitles nav t (:subtitle link) site)))
Build Categories
Selecting only the valid categories. This means that index.html in the root directory and such other ones without a leaf node will be omitted.
(defn build-categories [link metadata nav site]
(let [leaves (leaf-nodes nav)
categories (map :category leaves)]
(clone-for [c (distinct categories)]
[:header.category-title :h1] (content c (build-meta-strings metadata :category c nav))
[:ul.titles] (build-titles link c metadata (map :title (matches :category c nav)) nav site))))
Layout
Accepts a page with meta data of the structure.
Syntax Highlighting
(defn convert-pre [content] (html-snippet (highlight (apply str content) :clojure :html)))
(defn syntax-highlight [entry]
(at (html-snippet entry) [:pre] (fn [nd] (convert-pre (:content nd)))))
Article
(defsnippet article "templates/article.html" [:article] [entry]
[:article :.content] (content (syntax-highlight entry)))
Sidebar
(defsnippet sidebar "templates/sidebar.html" [:nav] [current-url site metadata sites nav page]
[:img.site-logo] (set-attr :src "./img/logo.svg")
[:ul.docs-site :li] (build-drop-down site sites)
[:div.category] (build-categories current-url metadata nav site))
(deftemplate layout "templates/layout.html" [site metadata sites nav page]
[:title] (content (:title (:meta page)))
[:#sidebar] (content (sidebar (:url page) site metadata sites nav page))
[:#container :#read-area] (content (article (:page page))))
Transform Page
(defn transform-page [root site metadata sites nav page]
(attach-root root site (apply str (layout site metadata sites nav page))))