A fork of HTML-TEMPLATES to support computed expressions
Common Lisp
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.





X-HTML-TEMPLATE library is a little fork of the Common Lisp library html-template which adds support for computed expressions while keeps mostly compatible. See the differences with html-template below.

I wrote this because we were using too many html-templates and migrating to a new template system was not worth. We wanted some extra flexibility however and it made our lives easier.

Using x-html-template

The HTML-TEMPLATE API is untouched (see its documentation if you are not used HTML-TEMPLATE before), except the system name and packages were renamed to X-HTML-TEMPLATE, to avoid possible collisions. A package nickname x-template is also provided as shortcut.

X-HTML-TEMPLATE changes the semantic of the template attributes. The tags accept expressions instead of symbols. The expressions follow the following syntax:

expression ::= 'literal'
             | "literal"
             | symbol
             | symbol(expression_1,expression_2,..,expression_N)

A hypothetical template could look like

<!-- tmpl_loop sort(users,'name') -->
      <!-- tmpl_var escape-html(upcase(name)) -->
   <!-- /tmpl_if -->
<!-- /tmpl_loop -->

This change diverges from the philosophy of HTML-TEMPLATE about separation of the code and the layout. However, this library does not provide harmful abstractions itself, but it offers the ability to provide them :-)

I really think that used properly, the extensions can be useful.


A simple use:

(with-output-to-string (*default-template-output*)
   "<!-- tmpl_var html-escape(string) -->"
   (list :string "0 <> 1" :html-escape #'escape-string-all)))


"0 &amp;lt;&amp;gt; 1"

Providing a default set of user-defined functions

Sometimes, it is convenient to provide a default set of user-defined function values to the templates. You can set the special variable *VALUE-ACCESS-FUNCTION* to provide them. The code would look like:

(defvar *x-template-default-values*
  (list :html-escape #'escape-string-all))

(unless (boundp '*original-value-access-function*)
  (defvar *original-value-access-function*

(setf *value-access-function*
      (lambda (symbol values &optional in-loop)
        (or (funcall *original-value-access-function* symbol values in-loop)
            (getf *x-template-default-values* symbol))))

Then, we can write the above example without defining the html-escape function.

(with-output-to-string (*default-template-output*)
   "<!-- tmpl_var html-escape(string) -->"
   (list :string "0 <> 1")))

Differences with html-template

X-HTML-TEMPLATE is not fully compatible with HTML-TEMPLATE, but it is in the common cases and porting your code should be trivial.

Quoting attributes

HTML-TEMPLATE allows to quote an attribute as <!-- tmpl_var 'foobar' --> As ‘foobar’ is a literal string in X-HTML-TEMPLATE, this code will not work in the same way. To port it, just remove the single or double quotes. However, if you are quoting the symbol because it contains spaces or non-allowed characters, then you will have to rename your symbol.

White-spaces delimiters

HTML-TEMPLATE white-spaces delimiters after the template start marker are optional and you could omit them if you quote the parameters. In X-HTML-TEMPLATE, quoting parameters is not allowed, but the white-spaces are optional anyway.

Therefore, a template like <!-- tmpl_var foo--> which is not legal in HTML-TEMPLATE, will be in X-HTML-TEMPLATE. It could seem weird, but it becomes useful if you override the default tag markers. Consider, for example:

<tmpl_var foo> in contrast to <tmpl_var foo >.

A full working example:

(let ((*template-start-marker* "<")
      (*template-end-marker* ">"))
  (with-output-to-string (*default-template-output*)
    (x-template:fill-and-print-template "<tmpl_var foo>" '(:foo "bar"))))