Skip to content

Commit

Permalink
generate templates now 2x faster
Browse files Browse the repository at this point in the history
  • Loading branch information
shenfeng committed Dec 17, 2012
1 parent db974bd commit 2acd0b0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 43 deletions.
7 changes: 3 additions & 4 deletions README.md
Expand Up @@ -61,7 +61,6 @@ I initally write it for my part time project: [Rssminer](http://rssminer.net)
</ul>
```


### Generate functions from templates folder

templates folder:
Expand All @@ -80,15 +79,15 @@ templates
```

```clj
(mktmpls-from-folder "templates" [".tpl"]) ; generates the clojure fn
(gen-tmpls-from-folder "templates" [".tpl"]) ; generates the clojure fn

; now you can write something like this
(admin {:key "str" :array [1 2 3 5]})
```

### Generate functions from classpath resources

`mktmpls-from-resouces` just like mktmpls-from-folder, except find templates files from classpath
`gen-tmpls-from-resources` just like mktmpls-from-folder, except find templates files from classpath

### Transform template data before apply it to the template

Expand All @@ -102,7 +101,7 @@ You can pass a function (optional) to `deftemplate`, `mktmpls-from-folder`, `mkt
;; other data, like different data based on local => for i18n
))

(mktmpls-from-folder "templates" [".tpl"] add-gloal-data)
(gen-tmpls-from-folder "templates" [".tpl"] add-gloal-data)
```

## Performance
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -6,7 +6,7 @@ end
desc "Install in local repository"
task :install_local => :test do
sh 'lein install'
sh 'cd ~/workspace/rssminer && lein deps'
# sh 'cd ~/workspace/rssminer && lein deps'
end

desc "Install in clojars repository"
Expand Down
72 changes: 39 additions & 33 deletions src/me/shenfeng/mustache.clj
Expand Up @@ -2,6 +2,7 @@
(:require [clojure.string :as str]
[clojure.java.io :as io])
(:import [me.shenfeng.mustache ResourceList Mustache Context]
clojure.lang.Keyword
java.io.File))

(defn mk-template [template]
Expand All @@ -20,13 +21,9 @@
(defmacro deftemplate [name template & [partials tran]]
`(let [tmpl# (Mustache/preprocess ~template)
f# (or ~tran identity)]
(defn ~name
([]
(.render tmpl# (Context. (f# {})) ~partials))
([data#]
(.render tmpl# (Context. (f# data#)) ~partials))
([data# partial#]
(.render tmpl# (Context. (f# data#)) (or partial# ~partials))))))
(defn ~name [& [data# partials#]]
(let [cxt# (Context. (f# (or data# {})))]
(.render tmpl# cxt# (or partials# ~partials))))))

(defn- get-content [file]
(slurp (or (io/resource file)
Expand All @@ -39,32 +36,41 @@
(keyword (.substring remain 0
(.lastIndexOf remain (int \.))))))

(defn deftemplates [tmpls & [tran]]
(doseq [[^clojure.lang.Keyword name template] tmpls]
(let [name (str/replace (str (.sym name)) #"_|/" "-")]
(eval `(deftemplate ~(symbol name) ~template ~tmpls ~tran)))))
(defn- get-tmpls [files folder]
(reduce (fn [m f]
(assoc m
(get-name f folder) (get-content f)))
{} files))

(defn- gen-vars [folder files tran]
(let [tmpls (reduce (fn [m f]
(assoc m
(get-name f folder) (get-content f)))
{} files)]
(deftemplates tmpls tran)))

;;; clear? to prent OOM when development => clears partials cache
;;; tempalte get constantly modified and reloaded
(defn mktmpls-from-folder [folder extentions & [tran clear?]]
(when clear? (.clear Mustache/CACHE))
(defn- tmpls-from-rerouces [folder extentions]
(let [^File dir (if (instance? File folder) folder (File. ^String folder))]
(gen-vars (.getName dir)
(map str (filter
(fn [^File f]
(and (.isFile f)
(some (fn [e]
(.endsWith (.getName f) e)) extentions)))
(file-seq dir)))
tran)))
(get-tmpls (map str
(filter
(fn [^File f]
(and (.isFile f)
(some (fn [e]
(.endsWith (.getName f) e)) extentions)))
(file-seq dir)))
(.getName dir))))

(defn- tmpls-from-folder [folder extentions]
(get-tmpls (ResourceList/getResources folder extentions) folder))

(defn- fn-name [name] ; app/search_result => app-search-result
(symbol (str/replace (str (.sym ^Keyword name)) #"_|/" "-")))

(defmacro gen-tmpls-from-folder [folder extentions & [tran]]
(.clear Mustache/CACHE) ; clear paritials cache
(let [tmpls (tmpls-from-folder folder extentions)
defs (map (fn [[name template]]
`(deftemplate ~(fn-name name) ~template ~tmpls ~tran))
tmpls)]
`(do ~@defs)))

(defn mktmpls-from-resouces [folder extentions & [tran clear?]]
(when clear? (.clear Mustache/CACHE))
(gen-vars folder (ResourceList/getResources folder extentions) tran))
(defmacro gen-tmpls-from-resources [folder extentions & [tran]]
(.clear Mustache/CACHE) ; clear paritials cache
(let [tmpls ^:const (tmpls-from-rerouces folder extentions)
defs (map (fn [[name template]]
`(deftemplate ~(fn-name name) ~template ~tmpls ~tran))
tmpls)]
`(do ~@defs)))
10 changes: 5 additions & 5 deletions test/me/shenfeng/mustache_test.clj
Expand Up @@ -46,12 +46,12 @@
(dotimes [i 100000] ; warm up
(template data))

(deftemplates {:name_one "{{name}}"
:name_two "Hello {{name}}, {{>name_one}}"})
;; (deftemplates {:name_one "{{name}}"
;; :name_two "Hello {{name}}, {{>name_one}}"})

(deftest test-deftemplates
(is (= (name-one {:name "abc"}) "abc"))
(is (= (name-two {:name "abc"}) "Hello abc, abc")))
;; (deftest test-deftemplates
;; (is (= (name-one {:name "abc"}) "abc"))
;; (is (= (name-two {:name "abc"}) "Hello abc, abc")))

(println "Perf test: Render 100k Times\n"
(slurp "test/tpl.tpl")
Expand Down

0 comments on commit 2acd0b0

Please sign in to comment.