Kwartz-Ruby Users' Guide
1 Introduction to Kwartz
1-1 What's Kwartz?
Kwartz(*2) is a template system which realized the concept of 'Independence of Presentation Logic'(IoPL). It means that Kwartz separates presentaion logics from both presentation data (typically HTML document) and business logics.
You know CSS (Cascading Style Sheet). CSS separates design from HTML file. In the same way, Kwartz separates presentation logics from HTML template. If you are familiar with CSS, you'll be also familiar with Kwartz.
The following figure show the relation of HTML, CSS, JavaScript, and Kwartz.
- HTML represents document structure.
- CSS represents document design.
- JavaScript represents client-side logics.
- Kwartz represents server-side presentation logics.
(Notice that Kwartz represents only presentation logics and not business logics.)
Kwartz-ruby is an implemenation of Kwartz in Ruby.
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'.
1-2 Features Overview
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.
- Multi-languages support
-
Kwartz can create output scripts for Ruby(eRuby), PHP, JSP(JSTL 1.2 & 1.1). Presentation logics are written in each language(*3). This approach gives you the power of the target language fully. For example, you can write Ruby on Rails helper methods (such as
link_to,form_tag, and so on) directly as a part of presentation logic. - 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 or kw:d attributes for marking in an HTML template. - Able to handle any text file
-
Kwartz uses an original template parser; not using an HTML or XML parser, it is able to handle any type of text file (HTML, PostScript, CSV, 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-escape and Partial-escape
-
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.
- (*3)
- Previous version of Kwartz adopt original language and convert it to each target language(Ruby, PHP, JSTL, and so on). From version 3.0, it is required to write presentation logic in target language.
1-3 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.
- '
id="list1"' means "I'll operate this element in presentation logic" (called 'marking' in Kwartz). - '
id="mark:item1"' is also an marking. Difference betweenid="mark:item1"andid="item1"is that id attribute in the former format is removed automatically and the latter format is leaved.
Presentation data file(example1.html):
<table>
<tr id="list1">
<td id="mark:item1">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.
- '
#list1 { ... }' represents an element marked with name 'list1' (= '<tr>...</tr>')- '
logic: { ... }' represents presentation logic of the element. - '
_stag' represents a start tag (= '<tr>'). - '
_cont' represents content(= '<td id="mark:item1">foo</td>'). - '
_etag' represents an end tag(= '</tr>'). - '
for var in list ...' is a Ruby code to loop. In this case, the element(= start-tag + content + end-tag) is looped.
- '
- '
#item1 { ... }' represents an element marked with name 'item1' (= '<td>...</td>').- '
value: expression;' represents that the content of the element is replaced by value ofexpression, which is value of a variablememberin this case.
- '
/* The element which is marked by 'id="list1"' */
#list1 {
logic: {
for member in @members
_stag # start tag
_cont # content
_etag # end tag
end
}
}
/* The element which is marked by 'id="mark:item1"' */
#item1 {
/* replace the content with value of a variable 'member' */
value: member;
}
(Don't forget the semicolon at the end of line!)
Kwartz generates eRuby script from the above files. This action is called 'compiling'.
$ kwartz -p example1.plogic example1.html > example1.rhtml
The following is the compiled output script.
Notice that id="mark:item1" is removed automatically while id="list1" is leaved.
<table>
<% for member in @members %>
<tr id="list1">
<td><%= member %></td>
</tr>
<% end %>
</table>
1-4 Complex Example
Next is bordered table example which is a little complex than previous.
<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.
*/
#list {
attrs: "bgcolor" color;
logic: {
@members.each_with_index do |member, i|
color = i % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
_stag # start tag
_cont # content
_etag # end tag
end
}
}
/*
* 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[:email] as contentn of the element.
* - print "mailto:" and member[:email] as href attribute value.
*/
#email {
value: member[:email];
attrs: "href" "mailto:#{member[:email]}";
}
(Don't forget the semicolon at the end of line especially for Ruby user!)
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.
$ kwartz -p example2.plogic example2.html > example2.rhtml
<table>
<% @members.each_with_index do |member, i| %>
<% 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>
1-5 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.
- Iterate an element.
#list { logic: { for member in @members _stag _cont _etag end } }Or#list { logic: { for member in @members _elem # equivarent to _stag + _cont + _etag end } }
- Iterate only contents. This is useful for <dl></dl>.
#list { logic: { _stag for member in @members _cont end _etag } }
- Replace content of element by expression value.
#list { logic: { _stag print expr _etag } }Or#list { value: expr; }
- Replace element by exression value
#list { logic: { print expr } }Or#list { elem: expr; }
- Delete start-tag and end-tag, and leaves content only.
#list { logic: { _cont } }
- Delete elemnt. This is useful for delete dummy data.
#list { logic: { } }
- Replace element with other element.
#list { logic: { _element(foo) # expand other element marked with name 'foo' } }
- Replace element with other element's content.
#list { logic: { _content(foo) # expand content of other element } }
- Include complex presentation logics.
#list { logic: { i = 0 for member in @members i += 1 if i % 2 == 0 color = '#FFCCCC' else color = '#CCCCFF' end _elem # '_elem' is equivarent to _stag + _cont + _etag end } }
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 and main program.