Kwartz Users' Guide

Makoto Kuwata <kwa(at)kuwata-lab.com>
last update: $Date: 2005-06-21 19:23:20 +0900 (Tue, 21 Jun 2005) $

Preface

This is the users' guide to Kwartz(*1), a template system which realized the concept of 'Separation of Presentation Logic and Presentation Data'(SoPL/PD) or 'Independence of Presenation Logic'(IoPL).

(*1)
Development of Kwartz had subsidized by Exploratory Software Project of IPA (Information-Technology Promotion Agency Japan).

Table of Contents



Introduction to Kwartz

What's Kwartz?

Kwartz(*2) is a template system which realized the concept of 'Separation of Presentation Logic and Presentaion Data'(SoPL/PD) or 'Independence of Presentation Logic'(IoPL).

Kwartz-ruby is an implemenation of Kwartz in Ruby. There is a plan to implement Kwartz in PHP or Java.

In the following, the word 'Kwartz' means the specification of the template system and the word 'Kwartz-ruby' means the implementation of it in Ruby language.

(*2)
'Kwartz' is pronounced like 'Quartz'.

Features

Kwartz has the following features:

Separates presentation logic from presentation data.

Using template systems such as Smarty, Velocity, XMLC, amrita, etc, you can separate HTML design from business logic as a template. With Kwartz, you can separate presentation logic from a template. In other words, Kwartz divides a template into 'presentation data' and 'presentation logic'. You need not mix presentation logic into HTML files nor main program.

Very fast

Kwartz creates a script from a template (= presentation data and presentaion logic). All you have to do in main program is to call the output script. Because Kwartz doesn't use DOM trees or the like, it is both fast and light-weight.

Multiple programing languages

Kwartz can create output scripts for Ruby(eRuby), PHP, JSP(JSTL 1.1 & 1.0), and Velocity from a template file, because Kwartz uses an internal intermediate language. You don't have to change the presentation layer at all, even if you changed programming language.

Doesn't break HTML design at all

You must use directives like {foreach ...}{/foreach} in Smarty or #foreach(...) in Jakarta Velocity. These directives break the HTML design of template. Kwartz doesn't break HTML design because Kwartz uses id attributes for marking in an HTML template.

Can handle any text file

Kwartz uses an original template parser; not using an HTML or XML parser, it is able to handle any text file (HTML, PostScript, RTF, and so on). This also means that Kwartz can handle non-well-formed XML files, as well as well-formed XML files. This is an advantage of Kwartz against Enhydra XMLC or amrita, which handle only XML/HTML files.

Auto-Sanitizing and Partial-Sanitizing

Kwartz can do sanitizing automatically. You don't need to write 'CGI.escapeHTML(var)' or 'htmlspecialchars($var)'. You are free to turn sanitizing on/off, as well specifying which parts of the template to sanitize.


Simple Example

In Kwartz, a template is defined as both presentation data and presentation logic. They may be described in separate files.

This is an example of a presentation data file.

Presentation data file(example1.html):

<table>
  <tr id="list">
    <td id="item">foo</td>
  </tr>
</table>

And the following is an example of presentation logic. In presentation logic, you can operate on elements which are marked in presentation data.

Presentation logic file(example1.plogic):

#item {            // The element which is marked by 'id="item"'
  value: member;      // replace the content with value of a variable 'member'
  remove: "id";       // remove the id attribte
}

#list {            // The element which is marked by 'id="list"'
  remove: "id";       // remove the id attribute
  plogic: {           // define the presentation logic
    foreach (member in member_list) {
      @stag;          // start tag
      @cont;          // content
      @etag;          // end tag
    }
  }
}

Kwartz creates output scripts automatically for eRuby, PHP, and JSP (JSTL 1.1&1.0) from the above two files. This action is called 'compiling'. To compile, enter one of the following commands:

### for eRuby
$ kwartz -l eruby  -p example1.plogic example1.html > example1.rhtml

### for PHP
$ kwartz -l php    -p example1.plogic example1.html > example1.php

### for JSTL 1.1
$ kwartz -l jstl11 -p example1.plogic example1.html > example1.jsp

### for JSTL 1.0
$ kwartz -l jstl10 -p example1.plogic example1.html > example1.jsp

### for Velocity
$ kwartz -l velocity -p example1.plogic example1.html > example1.vm

The following is the output script for each respective language.

Output Script for eRuby(example1.rhtml):

<table>
<% for member in member_list do %>
  <tr>
    <td><%= member %></td>
  </tr>
<% end %>
</table>

Output Script for PHP(example1.php):

<table>
<?php foreach ($member_list as $member) { ?>
  <tr>
    <td><?php echo $member; ?></td>
  </tr>
<?php } ?>
</table>

Output Script for JSTL 1.1(*3)(example1.jsp):

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<table>
<c:forEach var="member" items="${member_list}">
  <tr>
    <td><c:out value="${member}" escapeXml="false"/></td>
  </tr>
</c:forEach>
</table>

Output Script for JSTL1.0(example1.jsp):

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<table>
<c:forEach var="member" items="${member_list}">
  <tr>
    <td><c:out value="${member}" escapeXml="false"/></td>
  </tr>
</c:forEach>
</table>

Output Script for JSTL1.0(example1.jsp):

<table>
#foreach($member in $member_list)
  <tr>
    <td>$!{member}</td>
  </tr>
#end
</table>

Using the command-line option '-e' when compiling, Kwartz will output sanitized scripts. For sanitizing, CGI.escapeHTML() is used in eRuby, htmlspecialchars() in PHP, <c:out/> without escapeXml="false" in JSTL, $esc.html() of EscapeTool in Velocity.

Then execute or import these output scripts into your main program, like this:

Main Program (Ruby) :

## set a data
member_list = [ 'Oboro', 'Ominae', 'Jaquemonde' ]

## print out using ERB
require 'erb'
require 'cgi'        # for sanitizing
str = File.open('example1.rhtml') { |f| f.read() }
str.untaint
trim_mode = 1
erb = ERB.new(str, $SAFE, trim_mode)
print erb.result(binding())

## or print out using ERuby
require 'eruby'
require 'cgi'        # for sanitizing
ERuby::import('example1.rhtml')

Main Program (PHP) :

<?php
   // set a data
   $member_list = array('Oboro', 'Ominae', 'Jaquemonde');
   
   // print out
   include('example1.php');
 ?>

Main Program (JSTL) :

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
                  throws ServletException, IOException {
   ...
   // set a data
   java.util.List member_list = new java.util.ArrayList();
   member_list.add("Oboro");
   member_list.add("Ominae");
   member_list.add("Jaquemonde");

   // print
   RequestDispatcher dispatcher = 
       request.getRequestDispatcher("example1.jsp");
   dispatcher.include(request, response);
   // or dispatcher.forward(request, response);
}

Main Program (Velocity) :

import org.apache.velocity.app.Velocity;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.Template;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.MethodInvocationException;
import java.io.OutputStreamWriter;
import java.io.IOException;

public class Main1 {
  public static void main(String[] args) {
    try {
    // initialization
    Velocity.init();
 
    // create data
    java.util.List member_list = new java.util.ArrayList();
    member_list.add("Oboro");
    member_list.add("Ominae");
    member_list.add("Jaquemonde");
 
    // create context and set data
    VelocityContext context = new VelocityContext();
    context.put("member_list", member_list);
 
    // read template and merge it with context
    Template template = Velocity.getTemplate("Test.vm", "UTF8");
    OutputStreamWriter writer = new OutputStreamWriter(System.out);
    template.merge(context, writer);

    // print out
    writer.flush();
  }
  catch (ResourceNotFoundException ex) {
    // template not found
  }
  catch (ParseErrorException ex) {
    // syntax error exists in template
  }
  catch (MethodInvocationException ex) {
     // method invocation violation
  }
  catch (IOException ex) {
    // I/O exepption
  }
  catch (Exception ex) {
    // other exception
  }
}

Calling or executing the output script, you might get a web page like this:

<table>
  <tr>
    <td>Oboro</td>
  </tr>
  <tr>
    <td>Ominae</td>
  </tr>
  <tr>
    <td>Jaquemonde</td>
  </tr>
</table>
(*3)
if you specify the command-line option '--charset=CHARSET', Kwartz will output <%@ page contentType="text/html; charset=CHARSET" %> when the language is JSTL.

Complex Example

The following is a little complex example which is borderd table.

Marking is done with id="mark:name" instead of id="name" in the following presentation data. You don't have to write remove: "id" in presentation logic file because Kwartz removes id="mark:name" automatically.

Presentation Data (example2.html):

<table>
 <tr bgcolor="#CCCCFF" id="mark:list">
  <td id="mark:name">foo</td>
  <td>
   <a href="mailto:foo@mail.com" id="mark:email">foo@mail.com</a>
  </td>
 </tr>
</table>

The following is the presentation logic file. In the presentation logic, you should detect whether odd or even line in the iteration.

Presentation Logic (example2.plogic):

// an element which is marked by 'id="mark:list"':
// * print value of a variable 'color' as bgcolor attribute value.
// * change value of a variable 'color' whether odd or even line.
#list {
  attrs:  "bgcolor" color;
  plogic: {
    i = 0;
    foreach (member in member_list) {
      i += 1;
      color = i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
      @stag;    // start tag
      @cont;    // content
      @etag;    // end tag
    }
  }
}

// an element which is marked by 'id="mark:name"':
// * print value of member['name'] as content of the element.
#name {
  value: member['name'];
}

// an element marked by 'id="mark:email"':
// * print value of member['emal'] as contentn of the element.
// * print "mailto:" and member['email'] as href attribute value.
//   (operator '.+' means string concatenation.)
#email {
  value: member['email'];
  attrs: "href" ("mailto:" .+ member['email']);
}

You will find that there is no HTML tag in the presentation logic and no logic in the presentation data. That is to say, Kwartz can separate presentation logic from presentation data.

Notice that you cannot write ctr++ because incremental operator (++) is not supported.

Compile:

### for eRuby
$ kwartz -l eruby  -p example2.plogic example2.html > example2.rhtml

### for PHP
$ kwartz -l php    -p example2.plogic example2.html > example2.php

### for JSTL 1.1
$ kwartz -l jstl11 -p example2.plogic example2.html > example2.jsp

### for JSTL 1.0
$ kwartz -l jstl10 -p example2.plogic example2.html > example2.jsp

### for Velocity
$ kwartz -l velocity -p example2.plogic example2.html > example2.vm

Output Script:

### for eRuby
<table>
<% i = 0 %>
<% for member in member_list do %>
<%   i += 1 %>
<%   color = i % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %>
 <tr bgcolor="<%= color %>">
  <td><%= member["name"] %></td>
  <td>
   <a href="mailto:<%= member["email"] %>"><%= member["email"] %></a>
  </td>
 </tr>
<% end %>
</table>

### for PHP
<table>
<?php $i = 0; ?>
<?php foreach ($member_list as $member) { ?>
<?php   $i += 1; ?>
<?php   $color = $i % 2 == 0 ? "#FFCCCC" : "#CCCCFF"; ?>
 <tr bgcolor="<?php echo $color; ?>">
  <td><?php echo $member["name"]; ?></td>
  <td>
   <a href="mailto:<?php echo $member["email"]; ?>"><?php echo $member["email"]; ?></a>
  </td>
 </tr>
<?php } ?>
</table>

### for JSTL
<table>
<c:set var="i" value="0"/>
<c:forEach var="member" items="${member_list}">
  <c:set var="i" value="${i + 1}"/>
  <c:set var="color" value="${i % 2 eq 0 ? '#FFCCCC' : '#CCCCFF'}"/>
 <tr bgcolor="<c:out value="${color}" escapeXml="false"/>">
  <td><c:out value="${member['name']}" escapeXml="false"/></td>
  <td>
   <a href="mailto:<c:out value="${member['email']}" escapeXml="false"/>"><c:out value="${member['email']}" escapeXml="false"/></a>
  </td>
 </tr>
</c:forEach>
</table>

### for Velocity
<table>
#set($i = 0)
#foreach($member in $member_list)
  #set($i = $i + 1)
  #if($i % 2 == 0)
    #set($color = "#FFCCCC")
  #else
    #set($color = "#CCCCFF")
  #end
 <tr bgcolor="$!{color}">
  <td>$!{member["name"]}</td>
  <td>
   <a href="mailto:$!{member["email"]}">$!{member["email"]}</a>
  </td>
 </tr>
#end
</table>

Other Examples of Presentation Logic

Kwartz enables you to write complex presentation logic natulally. This section shows some examples. See Presentation Pattern Catalog for details.

It is very important that tag/attribute names don't appear in presentation logic at all. This way, you don't need to change presentation logic files even if the tag/attribute names are changed in the presentation data.

Kwartz separates presentation logic from presentation data.



Directives

Presentation logic may be embedded into presentation data in Kwartz. You can choose to separate or not to sepearate presentation data and presentation logic.

To embed presentation logic into presentation data, use directives. Directive is a command to embed presentation logic into presentation data. In Kwartz, 'id' and 'kw:d' attributes are used to describe directives.

The following is an example to use directives.

Presentation Data(example3.html):

<table>
  <tr id="foreach:member=member_list">
    <td id="value:member['name']">foo</td>
    <td><a href="mailto:@{member['email']}@">
         @{member['email']}@</a></td>
  </tr>
  <tr id="dummy:d1">
    <td>bar</td>
    <td><a href="mailto:bar@mail.org">bar@mail.org</a></td>
  </tr>
  <tr id="dummy:d2">
    <td>baz</td>
    <td><a href="mailto:baz@mail.net">baz@mail.net</a></td>
  </tr>
</table>

Compile:

### for eRuby
$ kwartz -l eruby   example3.html > example3.rhtml

### for PHP
$ kwartz -l php     example3.html > example3.php

### for JSTL1.1
$ kwartz -l jstl11  example3.html > example3.jsp

Output script:

### for eRuby
<table>
<% for member in member_list do %>
  <tr>
    <td><%= member["name"] %></td>
    <td><a href="mailto:<%= member["email"] %>">
         <%= member["email"] %></a></td>
  </tr>
<% end %>
</table>

### for PHP
<table>
<?php foreach ($member_list as $member) { ?>
  <tr>
    <td><?php echo $member["name"]; ?></td>
    <td><a href="mailto:<?php echo $member["email"]; ?>">
         <?php echo $member["email"]; ?></a></td>
  </tr>
<?php } ?>
</table>

### for JSTL
<table>
<c:forEach var="member" items="${member_list}">
  <tr>
    <td><c:out value="${member['name']}" escapeXml="false"/></td>
    <td><a href="mailto:<c:out value="${member['email']}" escapeXml="false"/>">
         <c:out value="${member['email']}" escapeXml="false"/></a></td>
  </tr>
</c:forEach>
</table>

### for Velocity
<table>
#foreach($member in $member_list)
  <tr>
    <td>$!{member["name"]}</td>
    <td><a href="mailto:$!{member["email"]}">
         $!{member["email"]}</a></td>
  </tr>
#end
</table>

There are several directives such as conditional branching. See reference manual for details.

(*4)
This pattern is editable with a constant EMBED_PATTERN in configuration file(kwartz/config.rb).

Sanitizing

Kwartz supports Automatic Sanitizing and Partially Sanitizing.

Automatic Sanitizing

-e is the command-line optin to generate output script with sanitizing. CGI.escapeHTML() is used in eRuby for sanitizing, htmlspecialchars() in PHP, <c:out/> tag without escapeXml="false" in JSTL, and $!esc.html() in Velocity.

Presentation Data (sanitize1.html):

<tr bgcolor="@{color}@">
  <td id="value:str">foo</td>
</tr>

Compile:

### for eRuby
$ kwartz -e -l eruby  sanitize1.html > sanitize1.rhtml
	
### for ERB
$ kwartz -e -l erb    sanitize1.html > sanitize1.rhtml
	
### for PHP
$ kwartz -e -l php    sanitize1.html > sanitize1.php
	
### for JSTL
$ kwartz -e -l jstl   sanitize1.html > sanitize1.jsp

### for Velocity
$ kwartz -e -l velocity sanitize1.html > sanitize1.vm

Output Scirpt:

### for eRuby
<tr bgcolor="<%= CGI::escapeHTML((color).to_s) %>">
  <td><%= CGI::escapeHTML((str).to_s) %></td>
</tr>

### for ERB
<tr bgcolor="<%=h(color)%>">
  <td><%=h(str)%></td>
</tr>

### for PHP
<tr bgcolor="<?php echo htmlspecialchars($color); ?>">
  <td><?php echo htmlspecialchars($str); ?></td>
</tr>

### for JSTL
<tr bgcolor="<c:out value="${color}"/>">
  <td><c:out value="${str}"/></td>
</tr>

### for Velocity
<tr bgcolor="$!esc.html($color)">
  <td>$!esc.html($str)</td>
</tr>

Constant string and constant number are not sanitized. Conditional expression such as 'flag ? " checked" : ""' is not sanitized because the result is constant string whether the value of 'flag' is true or false.


Partially Sanitizing

The function E(expr) always sanitizes expression expr even when '-e' is not specified. The function X(expr) doesn't sanitize expression expr even when '-e' is specified. (*5)

Presentaion Data:

<table>
 <tr bgcolor="@{X(color)}@">
   <td id="value:E(str)">foo</td>
 </tr>
</table>

Compile:

### for eRuby
$ kwartz -e -l eruby  sanitize1.html > sanitize1.rhtml
	
### for ERB
$ kwartz -e -l erb    sanitize1.html > sanitize1.rhtml
	
### for PHP
$ kwartz -e -l php    sanitize1.html > sanitize1.php
	
### for JSTL 1.1
$ kwartz -e -l jstl11 sanitize1.html > sanitize1.jsp

### for Velocity
$ kwartz -e -l velocity sanitize1.html > sanitize1.vm

Output Script:

### for eRuby
<table>
 <tr bgcolor="<%= color %>">
   <td><%= CGI::escapeHTML((str).to_s) %></td>
 </tr>
</table>

### for ERB
<table>
 <tr bgcolor="<%= color %>">
   <td><%=h(str)%></td>
 </tr>
</table>

### for PHP
<table>
 <tr bgcolor="<?php echo $color; ?>">
   <td><?php echo htmlspecialchars($str); ?></td>
 </tr>
</table>

### for JSTL
<table>
 <tr bgcolor="<c:out value="${color}" escapeXml="false"/>">
   <td><c:out value="${str}"/></td>
 </tr>
</table>

### for Velocity
<table>
 <tr bgcolor="$!{color}">
   <td>$!esc.html($str)</td>
 </tr>
</table>

Directives id="Value:expr" and id="Attr:name=expr" always sanitize expression expr even when the sanitizing command-line option is not specified. Directives id="VALUE:expr:" and id="ATTR:name=expr" doesn't sanitize expression expr even when the sanitizing command-line option is specified. These are equivalent to id="value:E(expr)", id="attr:name=E(expr)", id="value:X(expr)", and id="attr:name=X(expr)".

(*5)
E() and X() are pseudo-function. They are not expression but allowed to appear as argument of print statement of PL. For example, '@{E(...)}@' and 'id="value:E(...)' are valid, but 'id="set:str=E(...)"' is invalid.

Configuration for sanitizing

File 'kwartz/config.rb' is a configuration file for Kwartz-ruby. If you want to sanitize in default, change value of constant ESCAPE to true in the configuration file.



Other Topics

Restrictions

Kwartz parses presentation data file by regular expression pattern matching. It means that Kwartz doesn't use HTML parser nor XML parser for parsing presentation data. This approach enables Kwartz to handle any type of text file, and also brings the following restrictions to Kwartz.


Analyzing Global and Local Variables

Kwartz have a function to analyze presentation data/logic files and inspect variables.

In Kwartz, variables are called 'template global variables' if they are set in the main program and are passed to output script. Variables are called 'template local variables' if they are used only in the template. Kwartz have a function to detect whether variables are template global or local and report the result.

Assume the following presentation data and presentation logic:

Presentation Data (analyze.html):

<span kw:d="value:title">Analyzer Example</span>
<dl id="mark:items">
  <dt kw:d="value:ctr"></dt>
  <dd kw:d="value:item">Foo</dd>
</dl>

Presentation Logic (analyze.plogic):

#items {
  plogic: {
    @stag;
    ctr = 0;
    foreach (item in list) {
      ctr += 1;
      @cont;
    }
    @etag;
  }
}

In this case, variables ctr and item are template local variables because they are used only in the template. Variables title and list are template global variables because they are set in the main program and passed to output script.

Invoking kwartz with the command-line option -a analyze reports template global or local variables.

Analyzing Example:

$ kwartz -a analyze -p analyze.plogic analyze.html
Global: title list
Local:  ctr item

Rename Template Global/Local Variable Names

The command-line option --globalvar-prefix=prefix and --localvar-prefix=prefix add a prefix to global/local variable names in template.

In Ruby or PHP, for example, if template local variables in templates have the same name of variables in main program, assignment into template local variables effects the control of main program. To avoid this confliction, you should add a prefix such as '_' to template local variable names automatically.

The following is the example using 'analyze.html' and 'analyze.plogic' shown in the previous section.

Compile:

$ kwartz -l eruby  -p analyze.plogic --localvar-prefix='_' analyze.html
$ kwartz -l php    -p analyze.plogic --localvar-prefix='_' analyze.html
$ kwartz -l jstl11 -p analyze.plogic --localvar-prefix='_' analyze.html
$ kwartz -l velocity -p analyze.plogic --localvar-prefix='_' analyze.html

Output Script:

### for eRuby
<%= title %>
<dl>
<% _ctr = 0 %>
<% for _item in list do %>
<%   _ctr += 1 %>
  <dt><%= _ctr %></dt>
  <dd><%= _item %></dd>
<% end %>
</dl>

### for PHP
<?php echo $title; ?>
<dl>
<?php $_ctr = 0; ?>
<?php foreach ($list as $_item) { ?>
<?php   $_ctr += 1; ?>
  <dt><?php echo $_ctr; ?></dt>
  <dd><?php echo $_item; ?></dd>
<?php } ?>
</dl>

### for JSTL
<c:out value="${title}" escapeXml="false"/>
<dl>
<c:set var="_ctr" value="0"/>
<c:forEach var="_item" items="${list}">
  <c:set var="_ctr" value="${_ctr + 1}"/>
  <dt><c:out value="${_ctr}" escapeXml="false"/></dt>
  <dd><c:out value="${_item}" escapeXml="false"/></dd>
</c:forEach>
</dl>

### for Velocity
$!{title}
<dl>
#set($_ctr = 0)
#foreach($_item in $list)
  #set($_ctr = $_ctr + 1)
  <dt>$!{_ctr}</dt>
  <dd>$!{_item}</dd>
#end
</dl>

Constant GLOBALVAR_PREFIX and LOCALVAR_PREFIX in configuration file specifies the default prefix.


Span Tag Deletion

The span tags which contains only directives are regarded as dummy tags and deleted automatically.

Presentation Data:

<h1><span id="mark:title">title</span></h1>

Hello <span id="value:user">World</span>!

Presentation Logic:

#title {
  value: title;
}

Output Script(for eRuby):

<h1><%= title %></h1>

Hello <%= user %>!

The span tags are not removed when they have other attributes.

Presentation Data:

<h1><span id="mark:title" class="title">title</span></h1>

Hello <span kw:d="value:user" style="color:black">World</span>!

Output Script(for eRuby):

<h1><span class="title"><%= title %></span></h1>

Hello <span style="color:black"><%= user %></span>!

Appending Expression to Start Tag

The following is an example to print only attribute variable such as <input type="..." checked>.

Presentation Data:

<input type="checkbox" name="foo" value="Y" id="foo" />

Presentation Logic:

#foo {
  append: flag ? ' checked' : '';
}

Output Script:

### for eRuby
<input type="checkbox" name="foo" value="Y" id="foo"<%= flag ? " checked" : "" %> />

### for PHP
<input type="checkbox" name="foo" value="Y" id="foo"<?php echo $flag ? " checked" : ""; ?> />

### for JSTL 1.1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<input type="checkbox" name="foo" value="Y" id="foo"<c:out value="${flag ? ' checked' : ''}" escapeXml="false"/> />

### for JSTL 1.0
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<c:choose><c:when test="${flag}">
<input type="checkbox" name="foo" value="Y" id="foo" checked />
</c:when><c:otherwise>
<input type="checkbox" name="foo" value="Y" id="foo" />
</c:otherwise></c:choose>

### for Velocity
#if($flag)
<input type="checkbox" name="foo" value="Y" id="foo" checked />
#else
<input type="checkbox" name="foo" value="Y" id="foo" />
#end

A directive append(expr) appends the value of the expression expr in the element tag.

Presentation Data:

<input type="checkbox" name="foo" value="Y" id="append:flag?' checked':''" />

There are useful functions to print checked="checked" or selected="selected" easily. C(expr), S(expr), D(expr) prints checked="checked", selected="selected", disabled="disabled" respectively when the expression expr is true.

Presentation Data:

<input type="checkbox" name="foo" value="Y" id="foo" />

Presentation Logic:

#foo {
  append: C(foo == 100);
}

Output Script:

### for eRuby
<input type="checkbox" name="foo" value="Y" id="foo"<%= foo == 100 ? " checked=\"checked\"" : "" %> />

### for PHP
<input type="checkbox" name="foo" value="Y" id="foo"<?php echo $foo == 100 ? " checked=\"checked\"" : ""; ?> />

### for JSTL 1.1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<input type="checkbox" name="foo" value="Y" id="foo"<c:out value="${foo eq 100 ? ' checked="checked"' : ''}" escapeXml="false"/> />

### for JSTL 1.0
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<c:choose><c:when test="${foo eq 100}">
<input type="checkbox" name="foo" value="Y" id="foo" checked="checked" />
</c:when><c:otherwise>
<input type="checkbox" name="foo" value="Y" id="foo" />
</c:otherwise></c:choose>

### for Velocity
#if($foo == 100)
<input type="checkbox" name="foo" value="Y" id="foo" checked="checked" />
#else
<input type="checkbox" name="foo" value="Y" id="foo" />
#end

Describe Presentation Logic in Target Language

Kwartz allows you to write presentation logics in target language (such as Ruby, PHP, Java, etc).

Presentation Logic(eRuby):

#foo {
  value:  <%= str.empty? ? "null" : str %>;
  plogic: {
    @stag;
    <% ENV.each do |name, value| %>
      @cont;
    <% end %>
    @etag;
  }
}

Presentation Logic(PHP):

#foo {
  value:  <?= $str === NULL ? "null" : str ?>;
  plogic: {
    @stag;
    <?php foreach ($_ENV as $name => $value) { ?>
      @cont;
    <?php } ?>
    @etag;
  }
}

Kwartz just print code in <%= ... %> and <% ... %> and doesn't parse or analyze it. Therefore Kwartz doesn't report syntax error in the target code nor report analyzing template local/global variables.

Write X(<%= expression %>) if you don't want to sanitize expression.


Kwartz with Ruby on Rails

Kwartz-ruby has a special option -Rails for Ruby on Rails. It is equivarent to -l erb --globalvar-prefix='@'.

If you want to use Rails-specific functions such as link_to() or url_for(), use <% ... %> or <%= ... %> (or embed them into presentation data file).

Presentation Data (list.html)

<html>
 <body>

  <h1>Online Cookbook - All Recipes</h1>
  
  <table border="1">
   <tr>
    <th width="80%">Recipe</th>
    <th width="20%">Date</th>
   </tr>
   <tr id="mark:recipes">
    <td><a href="..." id="mark:recipe_title">Hot Chips</a></td>
    <td id="mark:recipe_date">2004 November 11</td>
   </tr>
   <tr id="dummy:d1">
    <td><a href="...">Ice Water</a></td>
    <td>2004 November 11</td>
   </tr>
  </table>

  <p>
   <a href="..." id="mark:recipe_new">Create new recipe</a>
  </p>

 </body>
</html>

Presentation Logic (list.plogic)

#recipes {
  plogic: {
    foreach (recipe in recipes) {
      @stag;   // start tag
      @cont;   // content
      @etag;   // end tag
    }
  }
}

#recipe_title {
  value: recipe.title;
  attrs: "href" <%= url_for(:action => "show", :id => recipe.id) %>;
}

// Or
//  #recipe_title {
//    plogic: {
//      print(<%= link_to recipe.title, :action => "show", :id => recipe.id %>);
//    }
//  }

#recipe_date {
  value: recipe.date;
}

#recipe_new {
  attrs: "href" <%= url_for(:action => "new") %>;
}

// Or
//  #recipe_new {
//    plogic: {
//      print(<%= link_to "Create new recipe", :action => "new" %>);
//    }
//  }

Compile:

$ kwartz -Rails -p list.plogic list.html > list.rhtml

Output Script:

<html>
 <body>

  <h1>Online Cookbook - All Recipes</h1>
  
  <table border="1">
   <tr>
    <th width="80%">Recipe</th>
    <th width="20%">Date</th>
   </tr>
<% for recipe in @recipes do %>
   <tr>
    <td><a href="<%= url_for(:action => "show", :id => recipe.id) %>"><%= recipe.title %></a></td>
    <td><%= recipe.date %></td>
   </tr>
<% end %>
  </table>

  <p>
   <a href="<%= url_for(:action => "new") %>">Create new recipe</a>
  </p>

 </body>
</html>

Write X(<%= expression %>) if you don't want to sanitize expression.


Compile Template into a Function of Ruby or PHP

Using the command-line option '-a defun', you can compile templates into a function of Ruby or PHP.

Presentation Data (hoge1.html)

Hello @{user}@ !
<ul id="mark:list">
  <li id="value:item">xxx</li>
</ul>

Presentation Logic (hoge1.plogic)

#list {
  plogic: {
    @stag;
    foreach (item in list) {
      @cont;
    }
    @stag;
  }
}

Compile:

$ kwartz -l eruby -a defun -p hoge1.plogic hoge1.html > hoge1.rb
$ kwartz -l php   -a defun -p hoge1.plogic hoge1.html > hoge1.php

Output Script:

### for eRuby
  def view_hoge1(__args)
    user = __args[:user]
    list = __args[:list]
    return _view_hoge1(user,list)
  end
  def _view_hoge1(user,list)
    _erbout = ''; _erbout << "Hello "; _erbout <<(( user ).to_s); _erbout << " !\n"
    _erbout << "<ul>\n"
     for item in list do 
    _erbout << "  <li>"; _erbout <<(( item ).to_s); _erbout << "</li>\n"
     end 
    _erbout << "<ul>\n"
    _erbout
  end

### for PHP
<?php
    function view_hoge1($__args) {
        $user = $__args['user']
        $list = $__args['list']
        return _view_hoge1($user, $list)
    }
    function _view_hoge1($user, $list) {
        ob_start();
?>Hello <?php echo $user; ?> !
<ul>
<?php foreach ($list as $item) { ?>
  <li><?php echo $item; ?></li>
<?php } ?>
<ul>
<?php
        $__s = ob_get_contents();
        ob_end_clean();
        return $__s;
    }
?>

Two functions are defined by '-a defun' option. You can use whichever you prefer.

You can specify funtion or method name with the command-line option '-F name', class or module name with '-C name', and arguments with '-A arg1,arg2,...'. The constant DEFUN_CLASS and DEFUN_FUNCTION in configuration file also enables you to set default class/module name and default function/method name.