http://github.com/rosejn/clj-libs/tree/master
This library is based loosely on erb from Ruby, which is the only other
template system I've used, and it allows you to insert Clojure
scriptlets inside a text document. Following is a short example of how
it currently works. Any thoughts, suggestions or feedback are welcome.
I plan on making it easier to instantiate pages by passing a hash, or
maybe a sequence of hashes, which will be successively bound for you.
I'll probably add some configuration options for handling whitespace and
trimming newlines too. Any other ideas or patches welcome.
Cheers,
Jeff
;; Here is a short example of creating an HTML template and then
;; instantiating it under a binding to generate the string output.
;; Define an HTML page template with embedded Clojure code
(def *page*
"<h3>Dear <%= winner %>,<h3>
<p>
We are pleased to inform you that you have been nominated as
president of this years <%= club %> club. Great job! You will
soon receive a set of important items:
</p>
<ul>
<% (doseq [doc documents] -%>
<li><%= doc %></li>
<% ) -%>
</ul>
<p>
Thanks for all your hard work.
Sincerely,
<%= from %>
</p>")
;; Need these or binding complains...
(def winner nil)
(def club nil)
(def documents nil)
(def from nil)
(let [page (template *page*)]
;; Now calling (page) under different bindings will produce different
;; pages.
(binding [winner "Joe Bob"
club "Winners"
documents ["winner's check" "waiver" "member list"]
from "Winners Club Headquarters"]
(println (page)))
StringTemplate, by the way, is how ANTLR generates its parser code
(ANTLR is target-language-neutral, not Java-specific).
> ...
>
> Rich
Randall Schulz
Ok, I can see the benefits of a functional style template. Do you think
the important aspect of this is whether you use a push or a pull model
for populating forms with data? In a functional style you would pass
all the necessary values to a function, which would then populate the
form and return a result. I don't like the idea of having to use XML or
some mini-language to do variable replacement, if statements, and
iteration over collections though. If I make the template library a
push model where you send it the values, but you just use Clojure code
to determine how they get used, does that still fit the bill?
As for the javascript template engines, I think that kind of solution
might be great for a websites, but a template engine like this is useful
for many applications besides filling in html pages, so I'd still like
to have a generic template mechanism from within Clojure. From the
above, I think StringTemplate has some interesting ideas. I'm going to
look into supporting recursive template application and include mechanisms.
-Jeff