Skip to content

Instantly share code, notes, and snippets.

@crofty
Created October 2, 2018 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crofty/6d13ed6be38d547a2a355039de828a15 to your computer and use it in GitHub Desktop.
Save crofty/6d13ed6be38d547a2a355039de828a15 to your computer and use it in GitHub Desktop.
Document serialization
(ns doc-serialization.core)
(def block-tags
{"h2" :h2
"h3" :h3
"h4" :h4
"p" :p})
(defn serialize-leaf [leaf]
[:span (:text leaf)])
(def serialization-rules
[(fn [{:keys [object] :as node} children]
(if (= "document" object)
children))
(fn [{:keys [object leaves]} _]
(if (= "text" object)
(map serialize-leaf leaves)))
(fn [{:keys [object]} children]
(if (= "inline" object)
`([:span ~@children])))
(fn [{:keys [object type data]} children]
(let [tag (get block-tags type)]
(if (and (= "block" object) tag)
`([~tag
~@(if-let [c (:count data)] [[:span (str c ". ")]])
~@children]))))
(fn [{:keys [object type]} children]
(if (= "block" object)
`([:div ~@children])))])
(defn serialize-node-to-hiccup [node]
(let [flat-children (mapcat identity (:nodes node))]
(some #(% node flat-children) serialization-rules)))
(defn prewalk-node [f node]
(update (f node) :nodes (partial map (partial prewalk-node f))))
(defn postwalk-node [f node]
(f (update node :nodes (partial map (partial postwalk-node f)))))
(defn increment-counter-at-depth [depth counts]
(->> (update counts (dec depth) inc)
(map-indexed #(if (> %1 (dec depth)) 0 %2))
vec))
(defn add-count-to-node [node]
(let [counts (volatile! [0 0 0])]
(prewalk-node
(fn [n]
(if-let [k (-> n :data :numbered)]
(let [depth (count (clojure.string/split k #"-"))]
(vreset! counts (increment-counter-at-depth depth @counts))
(let [count-str (clojure.string/join "." (take depth @counts))]
(assoc-in n [:data :count] count-str)))
n))
node)))
(defn serialize-document-to-hiccup [document]
(->> document
add-count-to-node
(postwalk-node serialize-node-to-hiccup)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment