ClearSilver templates

A ClearSilver template file, usually with an extension of .cst or .cs, consists of text with embedded ClearSilver templating commands. The syntax for the embedded commands is similar to many other HTML macro/template systems, which use <? ?> tags. A ClearSilver command consists of an opening delimiter, <?cs , a command designation, and then the command parameters, and the closing delimiter, ?>.

The template commands are:
   Substitution: var, evar, lvar, include, linclude, set, name
   Flow Control: if, else, elif, alt
   Iteration: each, loop, with
   Macros: def, call

All Flow Control, Iteration, and the def command have a corresponding ending command, just like HTML. So if has a corresponding /if.

Most commands take one or more expresssions as arguments.

In addition, Clearsilver supports comments using the # (hash) character, ie: <?cs # this is a comment ?>


Simple variable substitution is done with: <?cs var:Page.Name ?> Ie, the command is var and the parameter is the name of the var, ie Page.Name. evar is like var, except that the value of the dataset variable is also parsed for ClearSilver commands. This evar parsing happens during the load and parse of the CS template. As a result, syntax errors will be reported before display begins, and evar can not be used to display elements within an each loop. lvar is like evar, except that the value of the dataset variable is parsed at render time, not parse time. Syntax errors will be reported at render time. If you are not buffering your output, this will cause a partial page render. The CGI Kit always buffers its output. name will substitute the name of the lowest part of the dataset, ie <?cs name:Page.Name ?> will result in Name. This is most useful during iteration or macro expansion, where the true name of the aliased variable could have specific meaning. (pointers to later examples). There is an equivalent built-in function which does the same thing, such that <?cs name:Page.Name ?> is equivalent to <?cs var:name(Page.Name) ?>. Note also that when used on a local variable, this will return the name of the variable the local variable is mapped to. include will include (and parse) another CS file. The parameter to include can be either a string or a variable. A string is denoted by double quotes, ie: <?cs include:"header.cs" ?> The file is searched for in the HDF search path. Note: because this include happens at load/parse time, you can not use a local variable which is part of an each expression. This also means that using flow control (if/else) will have no affect on whether or not the file is loaded and parsed, it will always be loaded and parsed. linclude is similar to include, but the loading/parsing occurs at render time. local variables can be used to specify the filename, and conditional variables can be used to prevent loading of the file. Local variables are not passed to the linclude file, however. Like lvar, errors will be reported at render time. set will set a value in the dataset. The syntax for a set is fairly complicated. In general, the set command should be used only where necessary: most of the dataset should be specified either in static HDF files, or in the CGI via the HDF api. Typically, the set command is used for formatting, ie for splitting a set of elements into a number of columns, or for determining whether there were any matches during an iteration. (pointers to later examples)

A set command consists of the HDF value you are setting, and an expression that is evaluated to determine the value. For example: <?cs set:Page.Title = "The Title is " + Page.Menu.0.Name ?>

Flow Control

Neotonic ClearSilver provides if/elif/else commands for flow control. The argument to if and elif is an expression, evaluated as a boolean. So, the following if command always evaluates to true:

<?cs if:#1 ?>
<?cs /if ?>
Note the ending /if command as well. alt is short hand for an if var else. If the argument to alt is true, it is displayed, otherwise everthing to the closing /alt is displayed. These two are identical:

  <?cs alt:my_text ?>There is nothing to see here<?cs /alt ?>
  <?cs if:my_text ?><?cs var:my_text<?cs else ?>There is nothing to see here<?cs /if ?>

As part of the "safety" of running rendering a CS macro, the only iteration supported is guaranteed to be finite. The iteration command is each. each iterates over all of the children of a node of the dataset. For example, consider the following dataset:

Page {
  Access = Public
  Content = myword.cs
  Menu {
    0 {
      Name = Home
      URL = /
    1 {
      Name = Preferences
      URL = /prefs
    2 {
      Name = Help
      URL = /help.html
    3 {
      Name = Support
      URL = /feedback/
Using each on Page will result in iterating through Page.Access, Page.Content, and Page.Menu. Using each on Page.Menu will iterate through Page.Menu.0, Page.Menu.1, Page.Menu.2 and Page.Menu.3. For instance, to show the menu, you might do the following:
<?cs each:item = Page.Menu ?>
  <?cs name:item ?> - <a href="<?cs var:item.URL ?>">
        <?cs var:item.Name ?></a><br>
<?cs /each ?>
This results in the following HTML snippet (with some additional whitespace):
  0 - <a href="/">Home</a><br>
  1 - <a href="/prefs">Preferences</a><br>
  2 - <a href="/help.html">Help</a><br>
  3 - <a href="/feedback/">Support</a><br>
Note that the local variable, in this case item, acts the same as if you were actually using Page.Menu.0, ie you can access the sub-elements of the dataset from there easily.

Note also the use of the name command to access the name of the child that the local variable is pointing to.

with is similar to the Pascal with operand. It is similar to each, except instead of iterating over the variables, it allows access to that variable by a different variable name. Conceptually, you can also think of this as a scoped variable pointer. This is usually most convenient when you have longer variable names consisting of a complex syntax, for instance:

<?cs with:item = Page.Menu[ - #1] ?>
  <?cs name:item ?> - <a href="<?cs var:item.URL ?>">
        <?cs var:item.Name ?></a><br>
<?cs /with ?>
Which results in (if == 3) (with additional whitespace):
  2 - <a href="/help.html">Help</a><br>
loop is used to create a numeric loop. The arguments to loop are the starting number, the ending number, and the step. ClearSilver will always evaluate the loop expression to guarantee that it will finish. For instance, if you use a negative step value, but the ending number is greater than the starting number, ClearSilver will automatically switch the starting and ending numbers. The expressions are only evaluated once, so changing the variables in the loop will have no affect. Some quick examples:
<?cs loop:x = #1, #5, #2 ?><?cs var:x ?>, <?cs /loop ?>
1, 3, 5

<?cs loop:x = #1, #205, #2 ?><?cs var:x ?>, <?cs /loop ?>
1, 3, 5... 205

<?cs loop:x = #205, #1, "-2" ?><?cs var:x ?>, <?cs /loop ?>
205, 203, 201, ... 1