Tiny Enlive Transformer Implements update-in

Useful little enlive snippet. Implements the behaviour of clojure's update-in function for use inside enlive/at

Crispin Wellington
Jan 23, 2020 · 3 min read
unsplash-logoDean Brierley

Modifying Markdown Document Links

I have some markdown in a project on github. And it contains relative links. These relative link take you to other markdown files in the github repo. When you click the links on github the browser navigates to doc/tutorial.md and shows it in the github styling. All good.

Now I wan't to render these markdown documents onto my own server, with my own styling, for the project's home page. This site is comprised of static files generated with bootleg. All the links in the documents look like: doc/tutorial.md. But I need them to look like this: tutorial.html. I need an a-tag-url-modifier. One takes in the *.md href string, and transforms it to the equivalent *.html string.

What would be even more useful is a transformer that can modify any part of the element, like clojure's assoc-in or an update-in.

It's very simple. Here is the implementation of an update-in transformer from my bootleg file:

(defn el-update-in [path func & func-args]
  (fn [el]
    (apply update-in el path func func-args)))

I could append a html file extension to all the <a> tags with:

[:section
 [:div.container
  (-> (markdown "body.md")
      (enlive/at [:a] (el-update-in [:attrs :href] str ".html")))]]

The el-update-in function returns the transformer. The transformer operates on a hickory element. These elements have the keys :type, :tag, :attrs and :content. Here I run the str function on the contents of the path [:attrs :href]. You could access any attr this way, like [:attrs :class] or even run on sub elements, with something like [:content 0]!

Here is my solution to my path transformation problem.

[:section
 [:div.container
  (-> (markdown "body.md")
      (enlive/at
       [:a] (el-update-in [:attrs :href] #(-> %
                                              (string/split #"/" -1)
                                              last
                                              (string/split #"\." -1)
                                              butlast
                                              (->> (string/join "."))
                                              (str ".html")))))]]

I split the string up by / and take the last segment. Then hackishly remove the file extension. Then add the html extension. This turns doc/tutorial.md to tutorial.html.

About Crispin Wellington

Crispin Wellington is a Software Developer and System Operations expert with over 25 years of professional experience. As well as being the founder of Epic Castle he is the founder and developer of backgammonbuddy.com. He is based in Perth, Australia and is a husband and father. As Epic Castle's principal consultant he is available to assist you in solving your software, operations and service problems.