I'm working on a static site generator project and at one point I get a string representation of the site (in hiccup format) that I can manipulate. I convert that string to a map:
(clojure.edn/read-string page)
At which point I'll have my page as something like:
{ :header {
:title "Index"
:meta-desc "Indx Page"}
:page [:div.Page.Home
!!+Do-Math+!! ; This is the core of the question
[:p (do-math 2 2)] ; This is also an option to replace the above line
[:div.Home-primary-image-wrapper]
;More HTML stuff here
]
}
The goal then, as noted in the two lines above is to allow specific code to be executed before the html is rendered later.
My first thought was to embedded specific strings that are then replaced with function values:
(defn do-math []
(str [:p (+ 2 2)]))
(clojure.edn/read-string (clojure.string/replace page "!!+Do-Math+!!" (do-math)))
The issue I have with this is that I'd like to be able to embed values into the strings to do more useful stuff.
A non-working example of what I'd like to accomplish
We have this string !!+Do-Math 2 2++!! which would then go to a modified version of the function above expecting two arguments:
(defn do-math [val val2]
(str [:p (+ val val2)]))
The issuing I'm having is I'm not sure how to reliably replace strings like that, nor have I been able to pass the string values being replaced into the function doing the replacing. I'm not sure if that route is possible.
The other option would be to directly execute the functions in the map that I get back before rendering the html. In the example above I have:
[:p (do-math 2 2)]
Which would give me the same result. Is it possible to look through the map/vector and find instances of these function calls and execute them in the current namespace, and if so is that a better option that the string replace method above?