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))))