Far Beyond Code LLC /

HTML 5 Template Language for CFML Applications

Posted on 8/21/2011 by Bruce Kirkpatrick | Last modified 4/17/2013

An implementation of a unique extendable template language
built for ColdFusion Markup Language (CFML) applications.

Purpose

This template language is designed to utilize XHTML 5 friendly syntax so that unrendered templates look nearly identical to the rendered version when viewed in HTML browsers or IDEs. Many features in other languages will cause browsers or IDEs like dreamweaver to show a broken layout. Being able to edit parts of the template with more visually oriented tools reduces the skill level needed to customize the design for an application that implements this approach.

This template language will be used for the view files in our Jetendo CMS application (GPLv3+ License with some exceptions) and the CFML source code for the template language will also be released as a stand-alone open source project (MIT License) on GitHub. I also support the new "data-" custom attribute feature in HTML 5 to simplify certain kinds of code that read better as html tags, such as repeating a <tr> tag in multi-row table output. The template language can be used for non-HTML markup by using txt instead of the html file extension.

Click here to validate this page as HTML 5 on the W3C Validator in a new window

Example

This is what you see on a page that is using the Valid HTML 5 template language file before there is live data inserted.

Fancy Header

3 Most Popular Blog Articles

Title

Posted by Author on Date/Time
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam vitae fermentum odio. Donec sit amet nisl at ipsum ornare lobortis. Maecenas felis risus, volutpat eleifend tincidunt sit amet, imperdiet nec felis. Curabitur pharetra, odio bibendum sollicitudin tincidunt, leo mi imperdiet mauris, in blandit erat arcu eu turpis. Vivamus placerat felis eu eros tincidunt luctus. Vivamus eu vestibulum est. Pellentesque euismod facilisis luctus. Sed imperdiet malesuada augue nec pulvinar. Phasellus leo odio, cursus consectetur aliquam euismod, malesuada vel enim. Donec id risus in nibh ultrices cursus. Curabitur auctor leo in mi hendrerit laoreet. Etiam eget elit ac ipsum tempor blandit nec in lectus.


 

Template Source Code For Example

Below is the source code for the valid HTML 5 tag language example from above. This language can be used for inserting widgets, variables, logic and loops into regular HTML files that can still validate. Pay close attention to the parts where you see "data-" and the HTML comments since this shows the way you will be able to insert widgets, variables, logic and loops.



Live Data Example

If the template was part of a live web site, it would render like what is shown below.

Fancy Header

3 Most Popular Blog Articles

Read this, its amazing

Posted by Bob on 1/1/10

The world is great

Posted by Bruce on 1/15/10

The world has turn for the worse

Posted by Joe on 1/9/10
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam vitae fermentum odio. Donec sit amet nisl at ipsum ornare lobortis. Maecenas felis risus, volutpat eleifend tincidunt sit amet, imperdiet nec felis. Curabitur pharetra, odio bibendum sollicitudin tincidunt, leo mi imperdiet mauris, in blandit erat arcu eu turpis. Vivamus placerat felis eu eros tincidunt luctus. Vivamus eu vestibulum est. Pellentesque euismod facilisis luctus. Sed imperdiet malesuada augue nec pulvinar. Phasellus leo odio, cursus consectetur aliquam euismod, malesuada vel enim. Donec id risus in nibh ultrices cursus. Curabitur auctor leo in mi hendrerit laoreet. Etiam eget elit ac ipsum tempor blandit nec in lectus.

Expressions & Operators

$variablename$ syntax can be used to output variables anywhere in the skin. To escape a literal dollar sign, you just repeat it like this $$1,000.00. Double or Single quotes in a string must be escaped with a backslash such as \' or \". However, a double quote should be escaped as &quot; in an HTML document in order for it to be valid syntax.

The template language currently supports a variety of operators which are intentionally verbose so they read like English instead of using symbols like >= and !=.

Examples:
snippets.meta EQUALS 'test'
snippets.meta DOES NOT CONTAIN 'fudge'
(test1) EQUALS 5
snippets.meta IS EMPTY
url.content_id EQUALS true
url.content_id EQUALS false
url.content_id EQUALS 0
url.content_id GREATER THEN 0
url.content_id LESSER THEN 0
url.content_id GREATER THEN OR EQUAL TO 0
url.content_id LESSER THEN OR EQUAL TO 0
snippets.meta DOES NOT EXIST
snippets.meta EXISTS
request.cgi_script_name EQUALS 'index.cfm' or blogarticle.status DOES NOT EQUAL 1
snippets.meta IS NOT EMPTY
snippets.meta EXISTS and snippets.meta CONTAINS 'bruce'
(url.content_id EQUALS 5 or url.content_id EQUALS 3) and status EQUALS 1

Performance

A valid template file is compiled to the fastest possible CFML code and output as a CFC file. All the skin CFCs are loaded into the Application scope during start-up. Rendering a template has about the same performance as calling a CFC method to do simple logic and variable output. Therefore, there is nearly zero overhead to utilize this template language.

JSON-like expressions

JSON-like expressions are used when configuring widgets, loops and variable output like this:

<div data-zloop="blog.popularArticles({count:3,name:'blog'})">
<span data-zvar="blog.title">Title</span>
</div>

There are intentional limits placed on the JSON notation. You can't have nested objects or arrays for example. There is only support for string and number values. This was done only so that skins don't get overly complex.
Front-end work typically involves understanding some jquery to add slideshows and other UI behavior. I felt like the template language should be familiar to anyone who knows a little jquery.

Deploying Templates

There will also be FTP/browser editing support. The FTP user account for design changes will only allow txt, html, javascript and CSS files to be uploaded to improve security.

The skin object handles indexing the filesystem for each site and the shared skin directories automatically. Only files that have changed are re-compiled and cached. This process only happens when the developer triggers the cache to be flushed for the specific site or the entire application.

Valid XHTML 5

Because the skin is fully parsed into objects and then converted back into XHTML 5, it is able to auto-correct and detect many syntax problems. This will reduce the amount of work it takes to produce valid code. Many times only serious missing tags and out of order tags will need to be manually fixed.

The HTML analysis step when compiling templates is able to detect a variety of HTML syntax problems by reviewing the tree structure and knowing which elements are block level or inline.

Integration API

The directory for skins is a convention in Jetendo CMS, so integration simply requires placing your skin files in the skin directory.

To render a template, you call the includeSkin method of the skin CFC, which is restricted to including files in the skin directory. The full output of the skin is returned as a string.

<cfset stringResult=request.zos.skin.includeSkin("/skins/template/default.html")>

By default, there are a limited number of variables available to a skin. To extend this, you set the viewData as the second argument to includeSkin. Example:

<cfscript>
viewData={
widget1=[
{heading="test", htmltext="<strong>testing bold1</strong>", date1="2012-01-04"},
{heading="test2", htmltext="<strong>testing bold2</strong>", date1="2012-04-04" }
]
};
stringResult=request.zos.skin.includeSkin("/skins/template/default.html", viewData);
</cfscript>

viewData can't be changed by the template by default, so it isn't necessary to make copies of data. You want to minimize the amount of additional processing whenever possible.

Custom Widgets

Simple variable output, loops and logic is often is enough, but sometimes you may want to have advanced back-end code execute in a template to make data available that usually isn't available in that skin. While it is impossible to add this code directly in the skin language, you can implement this code as a custom widget that extends the skin language.

The skin compiler has a collection of widgets that are used when analyzing the document as an object. For example, the behavior of "if", "loop" and "for" are all implemented as skin widgets. Essentially, the entire template language is a set of plugin functions that analyze and transform the skin into CFML code.

A widget's job is to translate the HTML object into a string of CFML code. The CFML code is then inserted into the cached CFC. It is a little strange writing code that writes code, but this feature allows you to implement anything you wish the skin language had in it in a fairly simple way.

The widget's function receives an array of the entire parsed skin and the index where the widget's name was first encountered in the skin. You are able to transform as much of the data as you want by analyzing the tags, attributes, values and nested information contained in the skin array. Typically, the behavior of a widget ends either at the closing > symbol or when reaching the closing widget.

To implement nested HTML elements in between widget tags, you would have another widget name for the ending tag. For example, the end widget name for "loop" is "endloop". When implement a widget as an html attribute, it must be prefixed with z in order to execute the widget function.

An attribute based widget doesn't need an ending tag since the HTML end tag is automatically determined. The example above with the <tr> using data-zloop is an example of an attribute based widget.

More documentation on the API for building widgets will provided at a later date.

Why implement logic and loops in a simple template language?

I don't like other applications that need an excessive number of skin files just because they don't support logic. It takes too much time to find which file you need to change when each file links to another file. Often it is impossible to implement certain changes to the layout when you don't have logic, and you resort to using javascript to modify the page instead. This leaves large sections of the code in the output sometimes. It is better if those sections are removed server side based on the request data.

Future Roadmap

Deeper integration with Jetendo CMS

In-browser skin editing interface

In-browser syntax highlighting via google-code-prettify or another open source project.

Implement a Javascript template compiler for rendering some templates on the client side.

Automated documentation of variables available to each view file.

Launch as a separate MIT Licensed open source project on GitHub.com


© 2013 Far Beyond Code LLC - All Rights Reserved.