2014-12-05 15:56:40 +00:00
|
|
|
(ns cryogen-core.toc
|
2015-07-08 20:34:39 +00:00
|
|
|
(:require [crouton.html :as html]
|
|
|
|
[hiccup.core :as hiccup]))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-14 14:07:25 +00:00
|
|
|
(def _h [:h1 :h2 :h3 :h4 :h5 :h6])
|
2015-09-14 10:06:35 +00:00
|
|
|
(defn- compare_index [i1 i2] (- (.indexOf ^clojure.lang.APersistentVector _h i2) (.indexOf ^clojure.lang.APersistentVector _h i1)))
|
2014-12-14 14:07:25 +00:00
|
|
|
|
2015-01-09 12:13:35 +00:00
|
|
|
(defn- get-headings
|
|
|
|
"Turn a body of html content into a vector of elements whose tags are
|
|
|
|
headings."
|
|
|
|
[content]
|
2014-12-04 16:38:48 +00:00
|
|
|
(reduce
|
|
|
|
(fn [headings {:keys [tag attrs content] :as elm}]
|
2014-12-14 14:07:25 +00:00
|
|
|
(if (some #{tag} _h)
|
2014-12-04 16:38:48 +00:00
|
|
|
(conj headings elm)
|
|
|
|
(if-let [more-headings (get-headings content)]
|
|
|
|
(into headings more-headings)
|
|
|
|
headings)))
|
|
|
|
[] content))
|
|
|
|
|
2015-01-09 12:16:22 +00:00
|
|
|
(defn make-links
|
|
|
|
"Create a table of contents from the given headings. This function will look
|
|
|
|
for either:
|
|
|
|
(1) headings with a child anchor with a non-nil name attribute, e.g.
|
|
|
|
<h1><a name=\"reference\">Reference Title</a></h1>
|
|
|
|
or
|
|
|
|
(2) headings with an id attribute, e.g. <h1 id=\"reference\">Reference Title</h1>
|
|
|
|
In both cases above, the anchor reference becomes \"#reference\" and the
|
|
|
|
anchor text is \"Reference Title\"."
|
|
|
|
[headings]
|
2014-12-14 14:07:25 +00:00
|
|
|
(loop [items headings acc nil _last nil]
|
2015-01-09 12:16:22 +00:00
|
|
|
(if-let [{tag :tag {id :id} :attrs [{{name :name} :attrs} title :as htext] :content} (first items)]
|
|
|
|
(let [anchor (or id name)]
|
2015-07-08 20:34:39 +00:00
|
|
|
(if (nil? anchor)
|
|
|
|
(recur (rest items) acc nil)
|
|
|
|
(let [entry [:li [:a {:href (str "#" anchor)} (or title (first htext))]]
|
|
|
|
jump (compare_index _last tag)]
|
|
|
|
(cond (> jump 0) (recur (rest items) (str acc "<ol>" (hiccup/html entry)) tag)
|
|
|
|
(= jump 0) (recur (rest items) (str acc (hiccup/html entry)) tag)
|
|
|
|
(< jump 0) (recur (rest items) (str acc (apply str (repeat (* -1 jump) "</ol>"))
|
|
|
|
(hiccup/html entry)) tag)))))
|
2014-12-14 14:07:25 +00:00
|
|
|
(str acc "</ol>"))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2015-09-14 10:06:35 +00:00
|
|
|
(defn generate-toc [^String html]
|
2014-12-04 16:38:48 +00:00
|
|
|
(-> html
|
2015-01-28 14:43:32 +00:00
|
|
|
(.getBytes "UTF-8")
|
2014-12-04 16:38:48 +00:00
|
|
|
(java.io.ByteArrayInputStream.)
|
|
|
|
(html/parse)
|
|
|
|
:content
|
|
|
|
(get-headings)
|
|
|
|
(make-links)
|
2014-12-14 14:07:25 +00:00
|
|
|
(clojure.string/replace-first #"ol" "ol class=\"contents\"")))
|