2008-11-10

<jstemplate>


<jstemplate>
<description>Hello world!</description>
<description>{"Hello world!"}</description>
<description value="{'Hello world!'}"/>
</jstemplate>


<description>Hello world!</description>
<description>Hello world!</description>
<description value="Hello world!">




<description>Good { new Date().getHours() > 11 ? "afternoon" : "morning" }.</description>


<description>Good morning.</description>




<?js for each (let i in [1, 2, 3]) { ?>
<description>There's no place like home.</description>
<?js } ?>


<description>There's no place like home.</description>
<description>There's no place like home.</description>
<description>There's no place like home.</description>




<script type="application/javascript">
let people = [
{ name: "Jim", rank: "celebrated", cerealBrand: "Special K" },
{ name: "Midge", rank: "heard of", cerealBrand: "Trix" },
{ name: "Genie", rank: "unknown", cerealBrand: "Muesli" },
];
</script>

<jstemplate>
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>Name</th>
<th>Rank</th>
<th>Cereal Brand</th>
</tr>
<?js for each (let person in people) { ?>
<tr>
<td>{person.name}</td>
<td>{person.rank}</td>
<td>{person.cerealBrand}</td>
</tr>
<?js } ?>
</table>
</jstemplate>


<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<th>Name</th>
<th>Rank</th>
<th>Cereal Brand</th>
</tr>
<tr>
<td>Jim</td>
<td>celebrated</td>
<td>Special K</td>
</tr>
<tr>
<td>Midge</td>
<td>heard of</td>
<td>Trix</td>
</tr>
<tr>
<td>Genie</td>
<td>unknown</td>
<td>Muesli</td>
</tr>
</table>



The code is available. Your thoughts & comparisons to JavaScript Templates, Better JavaScript Templates, JSmarty, seethrough and others are welcome!

3 comments:

Wladimir Palant said...

Looks nice, pretty simple and similar to E4X. And since it uses DOM methods rather than HTML/XUL code generation, it seems to be safe. However, I don't really like the amount of run-time code generation where almost all the code is actually static. At the very least I would move this into methods like processElementNode(sourceChild) and only call these methods from the generated code. Some tricks with closures might help to clean this up even more.

Blair McBride said...

Very interesting. A the moment, Ubiquity is using TrimPath JavaScript Templates, but there's been interest in switching to to something that can be validated. The favourite so far has been MJT.

This seems to be in between JS Templates and MJT, in that while its validatable, I find the logic more readable then MJT (and possibly more readable than JS Templates too). I love that its so minimal, and anyone using it can rely on their JavaScript knowledge, rather than learning some other new syntax.

Myk said...

wladimir: good points. The current version is just a weekend hack, and there's clearly plenty of room for improvement, especially given that most of the code is static. Closures are an interesting suggestion. I'll see if I can use them to maintain scope across function calls.

blair: thanks for the interesting comparisons with other template languages!

I've looked at MJT, and it feels clunky in the same way as other programming languages expressed via markup (Cold Fusion, XSLT, XUL Templates).

I've also looked at JS Templates, and I like that it provides a domain-specific language (DSL) designed expressly for (HTML) templates. I used the Template Toolkit DSL for several years when I was hacking on Perl web applications, and I really appreciated its grammatical simplicity and targeted libraries.

David Ascher pointed out to me that Django has also implemented a DSL for templates that looks a lot like Template Toolkit.

On the other hand, the downside of a DSL is that you have to learn another language, and it's not clear how useful that is in this case, since JavaScript is already a fairly simple language (unlike Perl, whose programmers benefited greatly from the simplicity of TT).

Also, this implementation is targeted to the client-side generation of portions of documents rather than the server-side generation of entire documents and sites, so it probably doesn't need a number of the primitives that are so useful in TT and Django's DSL (like TT's INCLUDE directive).

Overall, I think the current approach of embedding plain JavaScript is a good one, and I'm not inclined to implement a DSL, although domain-specific libraries would be a welcome addition.

Also, while I didn't design the syntax for validatibility, I see no reason to break that side-effect if it's useful for folks. But I could imagine adding an option to sacrifice it for developers who really want the flexibility of PHP (f.e. perhaps CDATA sections within the template could be parsed that way).