ClearSilver

I'm currently in the process of rebuilding my main app using ClearSilver,
and it's really slick. In a nutshell, it's a presentation layer (view)
for an MVC-style application.  Your controller (the 'C') uses the
model/backend (the 'M') to create a dataset that it passes to
ClearSilver (the 'V') to render the actual page.

This is a good idea for several reasons, the main one being that it
forces a complete separation between your view and your
controller.  It also allows you to hand off your view to some
non-programmers to build using ClearSilver.  They needn't learn
CF, or anything about your application.  All they need is to
understand how to access data from the dataset using a couple very
simple tags.  ClearSilver is also entirely platform neutral. 
It's written as a native C library, with bindings for Java, Ruby,
Python, Perl, C#, and CGI, so you can seamlessly move templates between
any of those environments without needing any changes.  Finally,
it's a good way to allow users of an application to have a very high
level of control over page formatting, without exposing the app to
malicious CF code.  Since ClearSilver templates can only recall
data out of the dataset, the wost they can possibly do is create a
template that is time consuming to process.

In my particular case, it's the last point that really
differentiated it from it's competitors (such as Velocity).  Our
app includes a web CMS as part of it's functionality, and exposing
complete control over the site layout makes for better integration with
existing infrastructure for our clients, without mandating a
significant amount of custom development work.

But enough of that, how does it work?

<cfsavecontent variable="data">
page.title = "My Title"
page.content << EOM
<h1>Hello, World!</h1>
<p>here's a paragraph
</p>
EOM
</cfsavecontent>
<cfsavecontent variable="template">
<html>
<head>
<title><?cs var:page.title ?></title>
</head>
<body>
<?cs var:page.content ?>
</body> 
</html>
</cfsavecontent>
<cfset hdf = createObject("java", "org.clearsilver.HDF").init() />
<cfset hdf.readString(data) />
<cfset cs = createObject("java", "org.clearsilver.CS").init(hdf) />
<cfset cs.parseString(template) />
<cfoutput>#cs.render()#</cfoutput>

Of course, your data sets get a lot more complex than that, as do
your templates.  You can load data sets from files, create them
from strings (as I did above), or build them a field at a time using hdf.setValue(path, value)
Templates are usually stored on the filesystem (so they can include one
another), and you define a template path (like your $PATH at the
shell), which makes customization a snap.  Provide default
templates, and allow people to add custom templates to a directory
that's earlier in the path.

All in all, ClearSilver is a very
functional presentation engine.  Some of the syntax is a bit
obtuse because of all the extra "<?cs" and "?>" bits in there,
but it's very easy to work with.  And best of all, it's
ludicriously fast.  Even with the overhead of having to convert
native CF datatypes (structs, arrays, queries) into HDF, using
ClearSilver instead of CF templates to generate the HTML is still
faster.

If that sounds interesting, I highly recommend checking
it out.  The Java API is somewhat lacking compared to the Python
and C interfaces, but after I implemented a couple of the missing bits,
the guy who wrote it said that he'd put in a bunch of missing stuff
into the next release.  So it should be even more capable when
that rolls out.  Of course, if you don't mind getting your hands a
little dirty, the API is simple to augment on your own.

2 responses to “ClearSilver”

  1. Jon BLock

    This is very interesting. I am going to look into this … had I known about this back when I started my CF based template parser, I may not have even created it. Anyway, I'd love a little tutorial about how to set this up with CFMX so I can get started.

    Thank you,
    Jon

  2. Barney

    Setting it up is pretty simple. After downloading, if you're on *nix, you should fine clearsilver.jar and libclearsilver-jni.so in the 'java-jni' subdirectory. Add those to your CF classpath and library path respectively, and after a restart, you should be ready to go. If you need to recompile for some reason (i.e. you're not on Linux), a simple `./configure && make` should do you. Part of the make process is a simple test runner, which should indicate success/failure without having to actually install it in CF to see.

    I don't know about the Windows version, but I expect it's similar.