Selmerではタグを簡単に作れるので結構便利です。
{% include %}
タグを使えば外部ファイルをテンプレートとして使えますが、ローカルにテンプレートを定義できるタグを作ってみます。
変数を%~~%のように定義できる、以下のようなテンプレートを作れるようにします。
sample.html
{% tmpl row %}
<div class="row">
<div class="col-md-2">%name%</div>
<div class="col-md-4">
%content%
</div>
<div class="col-md-2">%value%</div>
</div>
{% endtmpl %}
{% tmpl text %}
{% use tmpl="row" name="住所" value="abc" %}
<input id="%id%" class="form-control" type="text">
{% enduse %}
{% endtmpl %}
{% use tmpl="text" id="address" %}{% enduse %}
結果としては以下が出力されるようにします。
html
<div class="row">
<div class="col-md-2">住所</div>
<div class="col-md-4">
<input id="address" class="form-control" type="text">
</div>
<div class="col-md-2">abc</div>
</div>
Clojureのコードは以下のとおり。
add-tag!
でtmplタグとuseタグを追加しています。
ちなみに閉じタグが不要なものを作る場合は最後の:endtmpl
や:enduse
のようなものはいりません。
sample.clj
(ns sample
(:require [selmer.parser :as p]
[clojure.string :as s]))
(def tmpl-map (atom {}))
(p/add-tag! :tmpl
(fn [args context-map content]
(when-let [k (first args)]
(swap! tmpl-map assoc k
(get-in content [:tmpl :content]))
nil))
:endtmpl)
(p/add-tag! :use
(fn [args context-map content]
(let [h (->> (mapcat #(let [[k v] (s/split % #"=")] [k (read-string v)]) args)
(apply hash-map)
(into {"content" (get-in content [:use :content])}))]
(when-let [tmpl (get @tmpl-map (get h "tmpl"))]
(reduce-kv (fn [m k v] (s/replace m (str "%" k "%") v)) tmpl h))))
:enduse)