Extensible micro template engine for Clojure.
Add following dependency to your profject.clj
.
require [cuma.core :refer [render]]
(render "hello $(x)" {:x "world"})
;=> hello world
Replace escaped variable.
(render "$(x)" {:x "<h1>"})
;=> <h1>
Replace unescaped variable.
(render "$(raw x)" {:x "<h1>"})
;=> <h1>
Include another template.
(render "$(include tmpl)" {:tmpl "hello $(x)" :x "world"})
;=> hello world
Apply custom function to variable. Function detail is explained at following.
(render "$(upper x)" {:upper (fn [data s] (.toUpperCase s)) :x "hello")
;=> HELLO
Chain custom functions.
(let [f (fn [_ arg] (str "foo " arg))
g (fn [_ arg] (str "bar " arg))]
(render "$(-> x g f)" {:f f :g g :x "baz"}))
;=> "foo bar baz"
(render "@(if flg) foo @(end)" {:flg true})
;=> foo
(render "@(if flg) foo @(end)" {:flg false})
;=>
Implicit variable $(.)
is binded in if
section.
(render "@(if x) $(.) @(end)" {:x "hello"})
;=> hello
Map data is expanded to variable in if
section.
(render "@(if m) $(n) @(end)" {:m {:n "foo"}})
;=> foo
Implicit variable $(.)
is binded in for
section.
(render "@(for arr) $(.) @(end)" {:arr [1 2 3]})
;=> 1 2 3
Map data is expanded to variable in for
section.
(render "@(for arr) $(n) @(end)" {:arr [{:n 1} {:n 2} {:n 3}]})
;=> 1 2 3
(render "@(for arr1) @(for arr2) $(a)$(b) @(end) @(end)"
{:arr1 [{:a 1} {:a 2}] :arr2 [{:b 3} {:b 4}]})
;=> 13 14 23 24
(render "@(let :x \"foo\" :y 123) $(x) $(y) @(end)" {})
;=> foo 123
layout with implicit variable .
- layout.tpl
hello $(.)
- your code
(render "@(layout-file \"layout.tpl\")world@(end)" {})
;=> helo world
layout with block
section (block
section can be used only in layout-file
section)
- layout.tpl
a = $(a), b = $(b)
- your code
(render "@(layout-file \"layout.pl\") @(block :a)hello@(end) @(block :b)world@(end) @(end)" {})
;=> a = hello, b = world
(render "@(foo) world @(end)" {:foo (fn [data body] (str "hello " body))})
;=> hello world
(render "@(foo x) world @(end)"
{:foo (fn [data body arg] (str arg " " body)) :x "hello"})
;=> hello world
(render "$(a.b.c)" {:a {:b {:c "hello"}}})
;=> hello
; NOT SUPPORTED: nested variable
(render "$(f (g x))" {...})
Replacing variable and section are allowd to use custom function, and cuma allows you to make custon function as extension.
Cuma searches cuma.extension.*
namespaces, and load all public functions as extension.
raw
, ->
, include
, if
, for
are also extension.
https://github.com/liquidz/cuma/blob/master/src/cuma/extension/core.clj
(render "$(f x y z)" {:x 1 :y 2 :z 3 :foo "bar"})
(ns cuma.extension.YOUR_EXTENSION_NAME)
(defn f
"@data => {:x 1 :y 2 :z 3 :foo "bar" :render #'cuma.core/render, OTHER_EXTENSIONS}
@args => [1 2 3]"
[data & args]
(apply + args))
(render "@(f x y z) world @(end)" {:x 1 :y 2 :z 3 :foo "bar"})
(ns cuma.extension.YOUR_EXTENSION_NAME)
(defn f
"@data => {:x 1 :y 2 :z 3 :foo "bar" :render #'cuma.core/render, OTHER_EXTENSIONS}
@body => " hello "
@args => [1 2 3]"
[data body & args]
((:render data) (str "hello" body)))
Benchmarking is powered by criterium. Test code is here.
Copyright (C) 2015 Masashi Iizuka(@uochan)
Distributed under the Eclipse Public License, the same as Clojure.