clojure - How can one achieve introspection in mustache template engine? -
(def template "{{name}}.{{surname}} {{#data}} * {{.}} {{/data}}") (introspect template) => {:name "" :surname "" :data []}
is there introspect implementation?
if question how build introspect function, instaparse 1 way go:
(require '[instaparse.core :as insta]) (def parse (insta/parser "<moustache> = (tagged-block / word / sp)* <tagged-block> = comment | section | var comment = <tag-open> <'!'> (word | sp)* <tag-close> section = section-block-open (current-item / var / comment / word / sp)* <section-block-close> <section-block-open> = <tag-open> <'#'> name <tag-close> section-block-close = tag-open '/' name tag-close var = <tag-open> name <tag-close> current-item = <tag-open> <'.'> <tag-close> <word> = #'[^\\s{}]+' <sp> = #'[\\s]+' name = #'[^\\s{}]+' tag-open = '{{' tag-close = '}}'")) (def template "{{name}}.{{surname}} {{#data}} * {{.}} {{/data}}") (parse template) ;=> ([:var [:name "name"]] "." [:var [:name "surname"]] "\n " [:var [:name "#data"]] "\n " "*" " " [:var [:name "."]] "\n " [:var [:name "/data"]]) (defn introspect [parsed] (->> (tree-seq sequential? seq parsed) (filter sequential?) (filter #(#{:var :section} (first %))) (map (juxt first (comp keyword last second))) (map #(case (first %) :var [(second %) ""] :section [(second %) []])) (into {}))) (assert (= {:name "" :surname "" :data []} (introspect (parse template))))
i included support comments, other mustache constructs should easy add:
(parse "hello {{people}}!! {{! people world!!}}") ;=> ("hello" " " [:var [:name "people"]] "!!" " " [:comment " " "people" " " "could" " " "be" " " "the" " " "world!!"])
it doesn't cover entire moustache grammar, it's start think.
Comments
Post a Comment