Clojure template library

392 views
Skip to first unread message

Jeff Rose

unread,
Dec 3, 2008, 1:04:41 PM12/3/08
to clo...@googlegroups.com
I've just pushed a template library for Clojure up onto github for
public use. You can find it here:

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)))

Stuart Sierra

unread,
Dec 3, 2008, 1:19:37 PM12/3/08
to Clojure
On Dec 3, 1:04 pm, Jeff Rose <ros...@gmail.com> wrote:
> I've just pushed a template library for Clojure up onto github for
> public use.

Cool! One thing to consider, a noted flaw in ERB: use real XML
processing instructions, like "<?clj ... ?>" instead of "<%= .. %>".
That way your template can be a valid XML document. Yes, it's more
verbose, but PHP does it. Or, if you want, allow user-definable
delimiters.
-Stuart Sierra

Jeff Rose

unread,
Dec 3, 2008, 1:40:35 PM12/3/08
to clo...@googlegroups.com
Ok, that makes sense. I'll do it. What about the other options
available in erb though? Do we use this:

<?clj (doseq [doc documents] -?>
* <?clj= doc ?>
<?clj ) -?>

Will '<clj=' and '-?>' pass for valid xml?

-Jeff

Rich Hickey

unread,
Dec 4, 2008, 9:04:20 AM12/4/08
to Clojure


On Dec 3, 1:04 pm, Jeff Rose <ros...@gmail.com> wrote:
> I've just pushed a template library for Clojure up onto github for
> public use. You can find it here:
>
> 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.
>

Neat! One thing I recommend is that you consider taking a functional
approach to templates - it would be much more in line with Clojure.
Two examples of a more functional approach are:

StringTemplate
http://www.stringtemplate.org/

Google XML Pages
http://code.google.com/p/gxp/

Rich

Randall R Schulz

unread,
Dec 4, 2008, 9:42:20 AM12/4/08
to clo...@googlegroups.com
On Thursday 04 December 2008 06:04, Rich Hickey wrote:
> ...
>
> StringTemplate
> http://www.stringtemplate.org/

StringTemplate, by the way, is how ANTLR generates its parser code
(ANTLR is target-language-neutral, not Java-specific).


> ...
>
> Rich


Randall Schulz

Stuart Sierra

unread,
Dec 4, 2008, 10:02:07 AM12/4/08
to Clojure
On Dec 4, 9:04 am, Rich Hickey <richhic...@gmail.com> wrote:
> StringTemplate http://www.stringtemplate.org/

StringTemplate looks cool -- a functional, context-free template
language, with a less annoying syntax than either ERB or Google XML
Pages. From the author: "Just so you know, I've never been a big fan
of functional languages and I laughed really hard when I realized ...
that I had implemented a functional language. The nature of the
problem simply dictated a particular solution."

Thanks, Rich.

-Stuart Sierra

.Bill Smith

unread,
Dec 4, 2008, 10:45:31 AM12/4/08
to Clojure
> StringTemplate http://www.stringtemplate.org/

In StringTemplate's case, the design was more than a stylistic issue;
the author wanted a specific kind of separation between the template
and the business logic. He wrote a short paper on the subject (see
his website for details), which is worth reading.

Bill Smith

ppierre

unread,
Dec 4, 2008, 10:53:43 AM12/4/08
to Clojure
A nice solution is PURE : http://beebole.com/pure/ JavaScript
templating engine converting Json to HTML.

With a Clojure version you have identical code for HTML and AJAX :

Server side :
Clojure/PURE + HTML -> HTML

Client side :
Clojure/JSON -> JavaScript/PURE + AJAX

pierre

blackdog

unread,
Dec 4, 2008, 11:52:57 AM12/4/08
to clo...@googlegroups.com



You can find a little demo I put together for lauofdk here:

http://www.ipowerhouse.com/lau.zip

It is exactly what ppierre mentioned, clojure servlets returning
json with a jquery/pure client "hello world".

the dl includes jetty, and can be fired up with

./run test.clj

test.clj configures jetty and a single test servlet.

I don't do any server side templating at all these days.

bd
--
None are more hopelessly enslaved than those who falsely believe they
are free — Goethe

Jeff Rose

unread,
Dec 5, 2008, 5:22:04 AM12/5/08
to clo...@googlegroups.com

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

blackdog

unread,
Dec 5, 2008, 6:09:32 AM12/5/08
to clo...@googlegroups.com

Hi Jeff,

Don't forget that Velocity and Freemarker are also good candidates for
server side templating and with clojure's java integration a snap to
use, e.g. ...

(defn genSyntaxHiLight
[] (let [fmc (freeMarkerConfig)
tmpl (. fmc getTemplate "clojure.ftl")
map (clj-ns/get-tree)
]

(. tmpl process (convertMap map) *out*)
))


the clojure.ftl is a free marker template. I think that with clojure's
maps implementing Map that the (convertMap) I had required previously
is no longer necessary.

bd
Reply all
Reply to author
Forward
0 new messages