diff --git a/src/clj_jtwig/core.clj b/src/clj_jtwig/core.clj index 1c8893e..fe29a83 100644 --- a/src/clj_jtwig/core.clj +++ b/src/clj_jtwig/core.clj @@ -1,13 +1,10 @@ (ns clj-jtwig.core "wrapper functions for working with JTwig from clojure" - (:require [clojure.walk :refer [stringify-keys]] - [clj-jtwig.convert :refer [java->clojure clojure->java]]) (:import (com.lyncode.jtwig JtwigTemplate JtwigContext JtwigModelMap) - (com.lyncode.jtwig.functions.exceptions FunctionNotFoundException) - (com.lyncode.jtwig.functions.repository DefaultFunctionRepository) - (com.lyncode.jtwig.functions JtwigFunction) (com.lyncode.jtwig.tree.api Content) - (java.io File FileNotFoundException ByteArrayOutputStream))) + (java.io File FileNotFoundException ByteArrayOutputStream)) + (:require [clojure.walk :refer [stringify-keys]]) + (:use [clj-jtwig.functions])) ; global options (defonce options (atom {; true/false to enable/disable compiled template caching when using templates from @@ -131,47 +128,6 @@ [] (reset! compiled-templates {})) -(defn- create-function-repository [] - (new DefaultFunctionRepository (make-array JtwigFunction 0))) - -; we'll be reusing the same function repository object for all contexts created when rendering templates. -; any custom functions added will be added to this instance -(defonce functions (atom (create-function-repository))) - -(defn reset-functions! - "removes any added custom template function handlers" - [] - (reset! functions (create-function-repository))) - -(defn function-exists? [name] - (try - (.retrieve @functions name) - true - (catch FunctionNotFoundException ex - false))) - -(defn add-function! - "adds a new template function using the name specified. templates can call the function by the - name specified and passing in the same number of arguments accepted by f. the return value of - f is returned to the template. - prefer to use the 'deftwigfn' macro when possible." - [name f] - (if (function-exists? name) - (throw (new Exception (str "JTwig template function \"" name "\" already defined."))) - (let [handler (reify JtwigFunction - (execute [_ arguments] - (clojure->java (apply f (map java->clojure arguments)))))] - (.add @functions handler name (make-array String 0)) - (.retrieve @functions name)))) - -(defmacro deftwigfn - "adds a new template function. templates can call it by by the name specified and passing in the - same number of arguments as in args. the return value of the last form in body is returned to the - template." - [fn-name args & body] - `(do - (add-function! ~fn-name (fn ~args ~@body)))) - (defn- get-resource-path [filename] (-> (Thread/currentThread) (.getContextClassLoader) diff --git a/src/clj_jtwig/functions.clj b/src/clj_jtwig/functions.clj new file mode 100644 index 0000000..27c7818 --- /dev/null +++ b/src/clj_jtwig/functions.clj @@ -0,0 +1,48 @@ +(ns clj-jtwig.functions + "standard functions added to jtwig contexts by default. these are in addition to the + functions added by default in all jtwig function repository objects" + (:import (com.lyncode.jtwig.functions JtwigFunction) + (com.lyncode.jtwig.functions.repository DefaultFunctionRepository) + (com.lyncode.jtwig.functions.exceptions FunctionNotFoundException)) + (:require [clj-jtwig.convert :refer [java->clojure clojure->java]])) + +(defn- create-function-repository [] + (new DefaultFunctionRepository (make-array JtwigFunction 0))) + +; we'll be reusing the same function repository object for all contexts created when rendering templates. +; any custom functions added will be added to this instance +(defonce functions (atom (create-function-repository))) + +(defn reset-functions! + "removes any added custom template function handlers" + [] + (reset! functions (create-function-repository))) + +(defn function-exists? [name] + (try + (.retrieve @functions name) + true + (catch FunctionNotFoundException ex + false))) + +(defn add-function! + "adds a new template function using the name specified. templates can call the function by the + name specified and passing in the same number of arguments accepted by f. the return value of + f is returned to the template. + prefer to use the 'deftwigfn' macro when possible." + [name f] + (if (function-exists? name) + (throw (new Exception (str "JTwig template function \"" name "\" already defined."))) + (let [handler (reify JtwigFunction + (execute [_ arguments] + (clojure->java (apply f (map java->clojure arguments)))))] + (.add @functions handler name (make-array String 0)) + (.retrieve @functions name)))) + +(defmacro deftwigfn + "adds a new template function. templates can call it by by the name specified and passing in the + same number of arguments as in args. the return value of the last form in body is returned to the + template." + [fn-name args & body] + `(do + (add-function! ~fn-name (fn ~args ~@body)))) diff --git a/test/clj_jtwig/core_test.clj b/test/clj_jtwig/core_test.clj index 92c45c2..8399e3f 100644 --- a/test/clj_jtwig/core_test.clj +++ b/test/clj_jtwig/core_test.clj @@ -2,7 +2,8 @@ (:import (java.io FileNotFoundException) (clojure.lang ArityException)) (:require [clojure.test :refer :all] - [clj-jtwig.core :refer :all])) + [clj-jtwig.core :refer :all] + [clj-jtwig.functions :refer :all])) ; The purpose of these tests is to establish that our wrapper around JTwig works. That is, ; we will be focusing on stuff like making sure that passing Clojure data structures @@ -20,7 +21,7 @@ (-> x (class) (.getName) - (.startsWith "clj_jtwig.core$add_function")))) + (.startsWith "clj_jtwig.functions$add_function")))) (deftest string-template (testing "Evaluating templates in string vars"