Kwartz Reference Manual
last update: $Date: 2005-03-07 08:15:41 +0900 (Mon, 07 Mar 2005) $
Preface
This document is the Kwartz Reference Manual. Presentation language (PL), directives, command-line options, and configuration option are described in this document.
Table of Contents
- Preface
- PL - Presentation Language
- Directives
- What is a Directive?
- Marking
- Printing Values of Expressions
- Printing value of expression 2
- Attribute Values
- Appending Attribute Expression
- Assignment
- Conditional Branching
- Iteration (foreach)
- Iteration(loop)
- Iteration with Count
- Iteration with a Toggle Switch
- Iteration (while)
- Dummy data
- Replacement of Elements
- Placeholder
- Including Presentation Data Files
- id and kw:d Attributes
- Notes
- Command-line options
- Configuration options
PL - Presentation Language
PL is a language which is used to describe presentation logic in Kwartz. This section shows how to write in PL.
Comments
Characters following '//
' in a line is a comment.
// comment
Strings
"..."
or '...'
represents a string literal.
The former can contain special characters: line feed (\n), carriage return (\r) and tab (\t).
'foo bar' // String "foo bar\n" // String which contains a line feed character
Booleans and Null
The keywords true
, false
, null
are available in expressions.
flag = obj == null ? true : false;
true
, false
and null
are translated to the proper keywords in each language.
Language name | true | false | null |
---|---|---|---|
PHP | TRUE | FALSE | NULL |
eRuby | true | false | nil |
JSP(JSTL) | true | false | null |
Variables
A varaible starts with alphabetic character or '_
' and is followed by alphanumerics or '_
'.
You need not declare variables nor specify its type(*1).
- (*1)
- Because of this feature, it is very difficult to translate PL program into "static languages" such as Java.
Operators
There are several operators in Kwartz. Comparison operators are available for numbers and strings(*2).
Comparison operators | == != < <= > >= |
Logical operators | && || ! |
Arithmetic operators | + - * / % |
String Concatenation operators | .+ |
Conditional operators | ?: |
String concatenation operator ('.+
') is converted into '+
' in eRuby, '.
' in PHP,
a function 'fn:join()
' in JSTL1.1.
There is no concatenation operator in JSTL1.0, so Kwartz converts it into a little tricky code.
PL Program (PL):
filename = basename .+ '.plogic';
Output Script:
### for eRuby <% filename = basename + ".plogic" %> ### for PHP <?php $filename = $basename . ".plogic"; ?> ### 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" %> <c:set var="filename" value="${fn:join(basename,'.plogic')}"/> ### for JSTL 1.0 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:set var="filename" value="${basename}${'.plogic'}"/>
Conditional Operator is available in eRuby, PHP, and JSTL1.1. However, it is not available in JSTL1.0. Therefore, conditional operators will be translated to if statements in JSTL1.0.
PL Program:
color = ctr % 2 == 0 ? '#FFCCCC' : '#CCCCFF';
Output Script:
### for eRuby <% color = ctr % 2 == 0 ? "#FFCCCC" : "#CCCCFF" %> ### for PHP <?php $color = $ctr % 2 == 0 ? "#FFCCCC" : "#CCCCFF"; ?> ### 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" %> <c:set var="color" value="${ctr % 2 eq 0 ? '#FFCCCC' : '#CCCCFF'}"/> ### for JSTL 1.0 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:choose><c:when test="${ctr % 2 eq 0}"> <c:set var="color" value="#FFCCCC"/> </c:when><c:otherwise> <c:set var="color" value="#CCCCFF"/> </c:otherwise></c:choose>
- (*2)
- It is very difficult to translate PL program into Perl program, because Perl have different operators for numbers and strings ('==' vs 'eq', '!=' vs 'ne', ...).
Printing
print(...);
is print statement.
Any expression can be in arguments.
PL Program:
print('foo', bar, "baz\n"); // print a string and the value of a variable
Output Script:
### for eRuby foo<%= bar %>baz ### for PHP foo<?php echo $bar; ?>baz ### for JSTL foo<c:out value="${bar}" escapeXml="false"/>baz
When you enable auto-sanitizing, the output scripts will be one of the following:
### for eRuby foo<%= CGI::escapeHTML((bar).to_s) %>baz ### for PHP foo<?php echo htmlspecialchars($bar); ?>baz ### for JSTL foo<c:out value="${bar}"/>baz
If conditional operator returns constant string or number, sanitizing will be off even when using auto-sanitizing.
PL Program:
// Sanitized. print("<option ", condition ? var1 : var2, ">\n"); // Not sanitized. print("<option ", condition ? 'selected' : '', ">\n");
Output Script:
### for eRuby <option <%= CGI::escapeHTML((condition ? var1 : var2).to_s) %>> <option <%= condition ? "selected" : "" %>> ### for PHP <option <?php echo htmlspecialchars($condition ? $var1 : $var2); ?>> <option <?php echo $condition ? "selected" : ""; ?>> ### for JSTL <option <c:out value="${condition ? var1 : var2}"/>> <option <c:out value="${condition ? 'selected' : ''}" escapeXml="false"/>>
Assignment
Assignment statement is such as var = 100;
.
Also '+=
', '-=
', '*=
', '/=
', '%=
' and '+=
' are allowed.
PL Program:
name = 'Foo'; // assign a string count += 1; // increment the value of the variable str .+= '.txt'; // append a string
Output Script:
### for PHP <?php $name = "Foo"; ?> <?php $count += 1; ?> <?php $str .= ".txt"; ?> ### for eRuby <% name = "Foo" %> <% count += 1 %> <% str += ".txt" %> ### 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" %> <c:set var="name" value="Foo"/> <c:set var="count" value="${count + 1}"/> <c:set var="str" value="${fn:join(str,'.txt')}"/> ### for JSTL 1.0 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:set var="name" value="Foo"/> <c:set var="count" value="${count + 1}"/> <c:set var="str" value="${str}${'.txt'}"/>
Arrays and Hashes
You can reference an array element as arr[expr]
.
You can reference a hash element in the same way.(*3).
In JSTL, assignment into an array element or a hash element is not available.
PL Program:
list[n] = 10; // assign into n-th element of the array print(list[i], "\n"); // print i-th element of the array hash['key'] = 'foo'; // assign into a hash element print(hash['key'], "\n"); // print a hash element
Output Script:
### for eRuby <% list[n] = 10 %> <%= list[i] %> <% hash["key"] = "foo" %> <%= hash["key"] %> ### for PHP <?php $list[$n] = 10; ?> <?php echo $list[$i]; ?> <?php $hash["key"] = "foo"; ?> <?php echo $hash["key"]; ?>
You can reference a hash by 'hash[:key]
'.
'key
' must be a string which contains only alphpanumerics and '_
'.
'hash[:key]
' will be translated according to target programming language:
Target language | Result of translation |
---|---|
eRuby | hash[:key] |
PHP | $hash['key'] |
JSTL | hash['key'] |
PL Program:
print(hash[:key]);
Output Script:
### for eRuby <%= hash[:key] %> ### for PHP <?php echo $hash['key']; ?> ### for JSTL <c:out value="${hash['key']}" escapeXml="false"/>
- (*3)
- Operators for arrays and hashes are the same, therefore it is difficult to support a language, say Perl, which use different operators for arrays and hashes.
Properties & Methods
You can reference a property of an object as 'object->property
'.
You can also call a method with arguments such as 'object->method(arg1, arg2, ..)
'.
Translation of method call into JSTL will raise an error because JSTL's Expression Language doesn't support method call.
PL Program:
// property user.name = 'Foo'; print(user.name, "\n");
Output Script:
### for eRuby <% user.name = "Foo" %> <%= user.name %> ### for PHP <?php $user->name = "Foo"; ?> <?php echo $user->name; ?> ### for JSTL <c:set var="user" property="name" value="Foo"/> <c:out value="${user.name}" escapeXml="false"/>
PL Program:
// method call print(user.method(10, 20));
Output Script:
### for eRuby <%= user.method(10, 20) %> ### for PHP <?php echo $user->method(10, 20); ?>
There is no way to create a new object or define a new class in PL. These tasks must be done in the main program.
Iteration
foreach(loopvar in list) { ... }
represents a foreach iteration.
Items in the list
is assigned into the variable loopvar
each time through the iteration.
PL Program:
foreach(item in list) { print(item, "\n"); }
Output Script:
### for eRuby <% for item in list do %> <%= item %> <% end %> ### for PHP <?php foreach ($list as $item) { ?> <?php echo $item; ?> <?php } ?> ### for JSTL <c:forEach var="item" items="${list}"> <c:out value="${item}" escapeXml="false"/> </c:forEach>
You can also use a while statment. Kwartz will raise an error if you try to translate a while statement into a JSTL script, because there is no JSTL tag which is equivalent to the while statment.
PL Program:
i = 0; while(i < length) { i += 1; print(list[i]); }
Output Script:
### for eRuby <% i = 0 %> <% while i < length do %> <% i += 1 %> <%= list[i] %><% end %> ### for PHP <?php $i = 0; ?> <?php while ($i < $length) { ?> <?php $i += 1; ?> <?php echo $list[$i]; ?><?php } ?>
for-statements (like in C or Java) are not available.
Conditional Branching
'if(condition) { ... } else if(condition) { ... } else { ... }
' represents a conditional branch.
PL Program:
if (val > 0) { print ("* value is positive.\n"); } else if (val < 0) { print ("* value is negative.\n"); } else { print ("* value is zero.\n"); }
Output Script:
### for eRuby <% if val > 0 then %> * value is positive. <% elsif val < 0 then %> * value is negative. <% else %> * value is zero. <% end %> ### for PHP <?php if ($val > 0) { ?> * value is positive. <?php } elseif ($val < 0) { ?> * value is negative. <?php } else { ?> * value is zero. <?php } ?> ### for JSTL <c:choose><c:when test="${val gt 0}"> * value is positive. </c:when><c:when test="${val lt 0}"> * value is negative. </c:when><c:otherwise> * value is zero. </c:otherwise></c:choose>
Functions
The following functions are available in PL.
- E(expr)
- Sanitizes(escapes) the expression expr. Using this function sanitizes even when the command-line option for sanitizing is not specified.
- X(expr)
- Don't sanitize expression expr, even when the command-line option for sanitizing is specified.
- C(expression)
-
Equivarent to
expression ? ' checked="checked"' : ''
.
- S(expression)
-
Equivarent to
expression ? ' selected="selected"' : ''
.
- D(expression)
-
Equivarent to
expression ? ' disabled="disabled"' : ''
.
- list_new()
- Create a new list.
- list_length(list)
- Return the length of the list.
- hash_new()
- Create a new hash.
- hash_keys(hash)
- Return a list which contains all keys of the hash.
- str_length(string)
- Return the length of the string.
- str_tolower(string)
- Make a string to lowercase and return it.
- str_toupper(string)
- Make a string to uppercase an return it.
- str_trim(string)
- Strip whitespace from the beginning and end of a string and return it.
- str_index(string, char)
- Return the first positin a char occurs in a string.
JSTL1.0 doesn't support any function, so you cannot use these function in JSTL1.0 (except E() and X()). JSTL1.1 supports some functions but it is limited. In fact, list_new(), hash_new(), and hash_keys() are not supported.
Functions | eRuby | PHP | JSTL1.1 | JSTL1.0 |
---|---|---|---|---|
list_new() |
[] |
array() |
- | - |
list_length(list) |
list.length |
array_length(list) |
fn:length(list) |
- |
hash_new() |
{} |
array() |
- | - |
hash_keys(hash) |
hash.keys |
array_keys(hash) |
- | - |
str_length(str) |
str.lenth |
strlen(str) |
fn:length(str) |
- |
str_tolower(str) |
str.downcase |
strtolower(str) |
fn:toLowerCase(str) |
- |
str_toupper(str) |
str.upcase |
strtoupper(str) |
fn:toUpperCase(str) |
- |
str_index(str,ch) |
str.index(ch) |
strchr(str,ch) |
fn:indexOf(str,ch) |
- |
All functions except above are printed "as is" when translating into PHP or eRuby script. Translating into JSTL script will be error because Exrepssion Language of JSTL doesn't support user-defined functions.
Functions E() and X() are intended to be used as arguments of print statement. You shouldn't use them in other place.
Empty
'empty
' is a keyword used to check whether a value is either null or an empty string.
It can be placed only at the right-side of the operators '==
' and '!=
'.
PL Program:
if (str1 == empty) { print("str1 is empty.\n"); } else if (str2 != empty) { print("str2 is not empty.\n"); }
Output Script:
### for eRuby <% if !str1 || str1.empty? then %> str1 is empty. <% elsif str2 && !str2.empty? then %> str2 is not empty. <% end %> ### for PHP <?php if (!$str1) { ?> str1 is empty. <?php } elseif ($str2) { ?> str2 is not empty. <?php } ?> ### for JSTL <c:choose><c:when test="${empty str1}"> str1 is empty. </c:when><c:when test="${not empty str2}"> str2 is not empty. </c:when></c:choose>
Element declaration
Element declaration is description to manipulate elements
marked by 'id="name"
' or 'id="mark:name"
',
for example, delete attributes or change presentation logic.
In Kwartz, presentation logic file is described as a set of element declarations.
Element declaration starts with '#name
' and is followed by some declaration parts.
-
value: expression;
-
Replace content of the element by value of
expression
.
-
attr: "attr1" expr1 , "attr2" expr2 , ... ;
-
Replace value of attribute
attr
by value ofexpr
.
-
remove: "attr1" , "attr2" , ... ;
-
Remove attribute
attr
.
-
append: expr1 , expr2 , ... ;
-
Append expression
expr
at the end of start tag. This is useful for appendingchecked
orselected
in <input> tag or <option> tag.
-
tagname: expression;
-
Replace tag name by value of
expression
. This may be useful for Struts or JSF.
-
plogic: { ... }
-
Change the presentation logic of the element.
@stag
,@cont
, and@etag
are available in{ ... }
. These represents start tag, content, end tag of the element respectively. And@element(other)
is also available which represents other element and expand it.
Presentation Data:
<ul> <li id="foo" class="foo">dummy</li> </ul> <form action="foo.cgi"> <input type="checkbox" name="user" value="Y" checked="checked" id="mark:chkbox"/> </form>
Presentation Logic:
#foo { value: item; attr: "class" klass; plogic: { foreach (item in list) { @stag; @cont; @etag; } } } #chkbox { remove: "checked"; append: flag ? " checked" : ""; tagname: "html:text"; }
Output Script:
### for eRuby <ul> <% for item in list do %> <li id="foo" class="<%= klass %>"><%= item %></li> <% end %> </ul> <form action="foo.cgi"> <html:text type="checkbox" name="user" value="Y"<%= flag ? " checked" : "" %> /> </form> ### for PHP <ul> <?php foreach ($list as $item) { ?> <li id="foo" class="<?php echo $klass; ?>"><?php echo $item; ?></li> <?php } ?> </ul> <form action="foo.cgi"> <html:text type="checkbox" name="user" value="Y"<?php echo $flag ? " checked" : ""; ?> /> </form> ### 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" %> <ul> <c:forEach var="item" items="${list}"> <li id="foo" class="<c:out value="${klass}" escapeXml="false"/>"><c:out value="${item}" escapeXml="false"/></li> </c:forEach> </ul> <form action="foo.cgi"> <html:text type="checkbox" name="user" value="Y"<c:out value="${flag ? ' checked' : ''}" escapeXml="false"/> /> </form>
Document declaration
#DOCUMENT { ... }
is a special element declaration for document.
It represents document information and takes the following declaration parts.
-
begin: { ... }
- Represents PL code which is added at the beginning of the output script.
-
end: { ... }
- Represents PL code which is added at the end of the output script.
-
require: "filename1" , "filename2", ... ;
- Load presentation logic file.
-
global: varname1 , varname2 , ... ;
- List of global variables. Currently this part have no means but will be used in future release.
-
local: varname1 , varname2 , ... ;
- List of local variables. Currently this part have no means but will be used in future release.
Presentation data:
<ul id="mark:list"> <li id="value:item">foo</li> </ul>
PL Program:
#DOCUMENT { begin: { list = context[:list]; } end: { print("<!-- copyright(c) 2005 kuwata-lab.com ALL RIGHTS RESERVERD. -->\n"); } global: context; } #list { plogic: { @stag; foreach (item in list) @cont; @etag; } }
Output script:
### for eRuby <% list = context[:list] %> <ul> <% for item in list do %> <li><%= item %></li> <% end %> </ul> <!-- copyright(c) 2005 kuwata-lab.com ALL RIGHTS RESERVERD. --> ### for PHP <?php $list = $context['list']; ?> <ul> <?php foreach ($list as $item) { ?> <li><?php echo $item; ?></li> <?php } ?> </ul> <!-- copyright(c) 2005 kuwata-lab.com ALL RIGHTS RESERVERD. --> ### for JSTL <c:set var="list" value="${context['list']}"/> <ul> <c:forEach var="item" items="${list}"> <li><c:out value="${item}" escapeXml="false"/></li> </c:forEach> </ul> <!-- copyright(c) 2005 kuwata-lab.com ALL RIGHTS RESERVERD. -->
Raw-code
Code in the target program language can be in the PL program.
If Kwartz find a line starting with '<%
' or '<?
',
Kwartz prints the string from '<%
' or '<?
' to the end of line directly.
The following is an example which includes PHP code.
PL Program:
<?php foreach($hash as $key => $value) { ?> print("key=", key, " value=", value, "\n"); <?php } ?>
Output Script:
### for PHP <?php foreach($hash as $key => $value) { ?> key=<?php echo $key; ?> value=<?php echo $value; ?> <?php } ?>
Raw-code can be in 'plogic:' part of element declaration, or 'begin:'/'end:' part of document declaration. This means that you can write presentation logics in target language.
Presentation Logic:
#foo { plogic: { @stag; <% hash.each do |key, value| %> @cont; <% end %> @etag; } }
Raw-cde cannot be in 'value:' or 'attr:' part of element declaration, because raw-code is statement and not expression.
You should remember that writing a raw-code takes portability away.
Global and Local Variables
In Kwartz, variables are called Global variables if they are set in the main program and are passed to output script. Variables are called Local variables if they are used only in the template.
Assume the following presentation data and presentation logic:
Presentation data (analyze.html) :
<table> <caption id="value:title">Sample</caption> <tr id="mark:items" bgcolor="@{color}@"> <td id="value:item">Foo</td> </tr> </table>
Presentation logic (analyze.plogic) :
#items { plogic: { ctr = 0; foreach (item in list) { ctr += 1; color = ctr%2 == 0 ? '#FFCCCC' : '#CCCCFF'; @stag; @cont; @etag; } } }
There are several variables. They are classified as follows:
- Global variables
-
The variables '
title
' and 'list
' need to be set in the main program and be passed to template. These variables are called 'Global variables' in Kwartz. - Local variables
-
The variables '
item
', 'ctr
', and 'color
' are used only in the template. These variables are called 'Local variables' in Kwartz.
Invoking Kwartz with the command-line option '-a analyze
' analyzes the template and reports global/local variables.
$ kwartz -p analyze.plogic -a analyze analyze.html Global: title list Local: ctr item color
Kwartz detemines whether variables are global/local according to the following rule:
- When Kwartz finds a new variable ...
- If it appears in the lefthand-side of an assignment, it is to be recognized as a local variable.
- If it appears as the loop variable of a foreach statement, it is to be recognized as a local variable.
- Otherwize, it is to be recognized as a global variable.
Kwartz reports warnings if global variables appears in the lefthand-side of assignments or are used as loop variables in foreach statements. Because the role of template system is to display global variables, templates should not change or modify global variables.
Analyzing templates and reporting global/local variables is very useful, especially when the presentation data/logic is large and complex. It also helps you to find typos of variable names.
Features Under Consideration
The following features are not implemented. They may be implemented in the future release (or not).
- break, continue
- user-defined functions/procedures
- creating arrays and hashes in JSTL
Directives
What is a Directive?
Kwartz allows presentation logic to be embedded in presentation data. Commands for that purpose are called 'directives'.
'Directives' is a set of commands to embed presentation logic into presentation data.
Kwartz uses the id attribute and the kw:d attribute to embed directives in presentation data.
Kw:d is an original attribute of Kwartz, but the ability of id and kw:d attributes are equivalent for Kwartz.
Marking (id="name"
or id="mark:name"
) is also a directive.
You may have a question: If it is the most important feature for Kwartz that separates presentation logic from presentation data, why does Kwartz allow me to embed presentation logic into presentation data?
The answer is choosability - to make it possible for developers to choose either approach. In other words, to increase options of development styles. Kwartz doesn't force you to use one approach. Separate presentation logic and presentation data if you like to separate them, or mix them if you like.
You may wonder whether Kwartz becomes an ordinary template system if presentation logic is embedded into presentation data. But Kwartz has the following merits compared to other template systems;
- Kwartz doesn't break HTML design. Compare to Jakarta Velocity or Template-Toolkit.
- Kwartz doesn't need complex programming. Compare to Enhydra XMLC, which needs complex DOM programming.
- Kwartz works very quickly and is light-weight. Compared to amrita.
- Kwartz can handle any type of text. Compare to Enhydra XMLC or amrita.
- Kwartz can be used in several languages. There is no other template system like this!
Marking
The directive 'id="name"
' or 'id="mark:name"
' marks an element
with a name name
. This is called 'marking'.
The difference between 'id="name"
' and 'id="mark:name"
' is
that the former is left in but the latter is removed when compiling.
kw:d attributes are always removed.
Presentation Data:
<div id="foo">foo</div> <div id="mark:bar">bar</div>
Output Script:
### for eRuby <div id="foo">foo</div> <div>bar</div> ### for PHP <div id="foo">foo</div> <div>bar</div> ### for JSTL <div id="foo">foo</div> <div>bar</div>
Printing Values of Expressions
'@{expression}@
' is a directive which prints the value of an expression.
This pattern is changeable with a constant EMBED_PATTERN in configuration file (kwartz/config.rb).
Presentation Data:
Hello @{user.name}@!
Output Program:
### for eRuby Hello <%= user.name %>! ### for PHP Hello <?php echo $user->name; ?>! ### for JSTL Hello <c:out value="${user.name}" escapeXml="false"/>!
Expressions are sanitized if you specified the command-line option '-e
' when compiling templates.
Notice that all expressions except string and numbers constants are sanitized.
Output Program (with command-line option -e
) :
### for eRuby Hello <%= CGI::escapeHTML((user.name).to_s) %>! ### for PHP Hello <?php echo htmlspecialchars($user->name); ?>! ### for JSTL Hello <c:out value="${user.name}"/>!
Using the functions E()
or X()
, you can toggle sanitizing on/off for each expression.
E(expr)
means that the expression expr
is sanitized
and X(expr)
means that expr
is not sanitized.
These are not effected by the command-line option '-e
'.
Presentation Data:
With sanitizing: @{E(var)}@! Without sanitizing: @{X(var)}@!
Output Program:
### for eRuby With sanitizing: <%= CGI::escapeHTML((var).to_s) %>! Without sanitizing: <%= var %>! ### for PHP With sanitizing: <?php echo htmlspecialchars($var); ?>! Without sanitizing: <?php echo $var; ?>! ### for JSTL With sanitizing: <c:out value="${var}"/>! Without sanitizing: <c:out value="${var}" escapeXml="false"/>!
. .
Printing value of expression 2
'id="value:expression"
' is a directive to print the value of expression instead of the content.
It is more suitable for HTML design than '@{expression}@
' because it allows for the use of dummy data.
Presentation Data:
<li id="value:hash['name']">foo</li>
Output Program:
### for eRuby <li><%= hash["name"] %></li> ### for PHP <li><?php echo $hash["name"]; ?></li> ### for JSTL <li><c:out value="${hash['name']}" escapeXml="false"/></li>
'id="Value:expr"
' sanitizes the expression.
'id="VALUE:expr"
' un-sanitizes the expression.
These are equal to 'id="value:E(expr)"
' and 'id="value:X(expr)"
'.
Attribute Values
'id="attr:name=value"
' (or 'id="attr:name:value"
') is a directive to set an attribute value.
It overwrites the existing value if attribute name
is already set.
In the following example, attribute 'class' has the dummy value 'odd
', and the actual value is derived from the variable 'klass
'.
Presentation Data:
<tr class="odd" id="attr:class=klass"> <td>foo</td> </tr>
Output Program:
### for eRuby <tr class="<%= klass %>"> <td>foo</td> </tr> ### for PHP <tr class="<?php echo $klass; ?>"> <td>foo</td> </tr> ### for JSTL <tr class="<c:out value="${klass}" escapeXml="false"/>"> <td>foo</td> </tr>
'id="Attr:name=value"
' sanitizes the value.
'id="ATTR:name=value"
' un-sanitizes the value.
These are equal to 'id="attr:name=E(value)"
' and 'id="attr:name=X(value)"
'.
Separating with ';
', you can have several 'attr:name=value
' directives in one id attribute.
You can enumerate other attributes this way as well.
Presentation Data:
<font id="if:message!=empty;attr:class=klass;attr:bgcolor=color"> @{message}@ </font>
Output Script:
### for eRuby <% if message && !message.empty? then %> <font class="<%= klass %>" bgcolor="<%= color %>"> <%= message %> </font> <% end %> ### for PHP <?php if ($message) { ?> <font class="<?php echo $klass; ?>" bgcolor="<?php echo $color; ?>"> <?php echo $message; ?> </font> <?php } ?> ### for JSTL <c:if test="${not empty message}"> <font class="<c:out value="${klass}" escapeXml="false"/>" bgcolor="<c:out value="${color}" escapeXml="false"/>"> <c:out value="${message}" escapeXml="false"/> </font> </c:if>
Appending Attribute Expression
'id="append:expression"
' is a directive to append expression into a tag.
This is useful to output '<input ... checked />' or '<option ... selected></option>'.
Presentation Data:
<option name="lang" value="ruby" id="append:lang=='ruby'?' selected':''">Ruby</option> <input type="radio" name="gender" value="M" id="append:gender=='M'?' checked':''">
Output Script:
### for eRuby <option name="lang" value="ruby"<%= lang == "ruby" ? " selected" : "" %>>Ruby</option> <input type="radio" name="gender" value="M"<%= gender == "M" ? " checked" : "" %>> ### for PHP <option name="lang" value="ruby"<?php echo $lang == "ruby" ? " selected" : ""; ?>>Ruby</option> <input type="radio" name="gender" value="M"<?php echo $gender == "M" ? " 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" %> <option name="lang" value="ruby"<c:out value="${lang eq 'ruby' ? ' selected' : ''}" escapeXml="false"/>>Ruby</option> <input type="radio" name="gender" value="M"<c:out value="${gender eq 'M' ? ' checked' : ''}" escapeXml="false"/>> ### for JSTL 1.0 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:choose><c:when test="${lang eq 'ruby'}"> <option name="lang" value="ruby" selected></c:when><c:otherwise> <option name="lang" value="ruby"></c:otherwise></c:choose> Ruby</option> <c:choose><c:when test="${gender eq 'M'}"> <input type="radio" name="gender" value="M" checked> </c:when><c:otherwise> <input type="radio" name="gender" value="M"> </c:otherwise></c:choose>
A function to output 'checked="checked"'
, 'selected="selected"'
and 'disabled="disabled"'
easily for HTML/XHTML is available in Kwartz.
C(expr)
, S(expr)
, and D(expr)
print ' checked="checked"'
, ' selected="selected"'
and ' disabled="disabled"'
respectively when expression expr
is true.
Presentation Data:
<option name="lang" value="ruby" id="append:S(lang=='ruby')">Ruby</option> <input type="radio" name="gender" value="M" id="append:C(gender=='M')" />Male <input type="radio" name="os" value="win" id="append:D(os=='mac')" />Windows
Output Script:
### for PHP <option name="lang" value="ruby"<?php echo $lang == "ruby" ? " selected=\"selected\"" : ""; ?>>Ruby</option> <input type="radio" name="gender" value="M"<?php echo $gender == "M" ? " checked=\"checked\"" : ""; ?> />Male <input type="radio" name="os" value="win"<?php echo $os == "mac" ? " disabled=\"disabled\"" : ""; ?> />Windows ### for eRuby <option name="lang" value="ruby"<%= lang == "ruby" ? " selected=\"selected\"" : "" %>>Ruby</option> <input type="radio" name="gender" value="M"<%= gender == "M" ? " checked=\"checked\"" : "" %> />Male <input type="radio" name="os" value="win"<%= os == "mac" ? " disabled=\"disabled\"" : "" %> />Windows ### 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" %> <option name="lang" value="ruby"<c:out value="${lang eq 'ruby' ? ' selected="selected"' : ''}" escapeXml="false"/>>Ruby</option> <input type="radio" name="gender" value="M"<c:out value="${gender eq 'M' ? ' checked="checked"' : ''}" escapeXml="false"/> />Male <input type="radio" name="os" value="win"<c:out value="${os eq 'mac' ? ' disabled="disabled"' : ''}" escapeXml="false"/> />Windows ### for JSTL 1.0 <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <c:choose><c:when test="${lang eq 'ruby'}"> <option name="lang" value="ruby" selected="selected"></c:when><c:otherwise> <option name="lang" value="ruby"></c:otherwise></c:choose> Ruby</option> <c:choose><c:when test="${gender eq 'M'}"> <input type="radio" name="gender" value="M" checked="checked" /></c:when><c:otherwise> <input type="radio" name="gender" value="M" /></c:otherwise></c:choose> Male <c:choose><c:when test="${os eq 'mac'}"> <input type="radio" name="os" value="win" disabled="disabled" /></c:when><c:otherwise> <input type="radio" name="os" value="win" /></c:otherwise></c:choose> Windows
Assignment
'id="set:var=value"
' is a directive for assigning values into variables.
Other than '=
', '+=
', '-=
', '*=
', '/=
', '.=
' are also available.
Presentation Data:
<dt id="set:var=value">foo</dt> <dd id="set:count+=1">123</dd>
Output Program:
### for eRuby <% var = value %> <dt>foo</dt> <% count += 1 %> <dd>123</dd> ### for PHP <?php $var = $value; ?> <dt>foo</dt> <?php $count += 1; ?> <dd>123</dd> ### for JSTL <c:set var="var" value="${value}"/> <dt>foo</dt> <c:set var="count" value="${count + 1}"/> <dd>123</dd>
Conditional Branching
'id="if:expression"
' is a directive for conditional branching.
'else
' and 'elseif
' are also available.
Presentation Data:
<div id="if:value > 0"> Value is positive. </div> <div id="elseif:value < 0"> Value is negative. </div> <div id="else:"> Value is zero. </div>
Output Program:
### for eRuby <% if value > 0 then %> <div> Value is positive. </div> <% elsif value < 0 then %> <div> Value is negative. </div> <% else %> <div> Value is zero. </div> <% end %> ### for PHP <?php if ($value > 0) { ?> <div> Value is positive. </div> <?php } elseif ($value < 0) { ?> <div> Value is negative. </div> <?php } else { ?> <div> Value is zero. </div> <?php } ?> ### for JSTL <c:choose><c:when test="${value gt 0}"> <div> Value is positive. </div> </c:when><c:when test="${value lt 0}"> <div> Value is negative. </div> </c:when><c:otherwise> <div> Value is zero. </div> </c:otherwise></c:choose>
If using 'elseif
' or 'else
' directives, don't insert empty lines just before.
Iteration (foreach)
'id="foreach:loopvar=list)"
' (or 'id="foreach:loopvar:list)"
') is a directive for iteration, assigning each value in the array into a variable each time through the loop.
Presentation Data:
<tr id="foreach:item=list"> <td>@{item}@</td> </tr>
Output Program:
### for eRuby <% for item in list do %> <tr> <td><%= item %></td> </tr> <% end %> ### for PHP <?php foreach ($list as $item) { ?> <tr> <td><?php echo $item; ?></td> </tr> <?php } ?> ### for JSTL <c:forEach var="item" items="${list}"> <tr> <td><c:out value="${item}" escapeXml="false"/></td> </tr> </c:forEach>
Iteration(loop)
'id="loop:loopvar=list"
' (or 'id="loop:loopvar:list"
') is a directive for iteration.
It iterates only contents. The start tag and the end tag are not iterated.
It is very useful especially for <dl></dl> tag.
Presentation Data:
<dl id="loop:item=list"> <dt>@{item.text}@</dt> <dd>@{item.desc}@</dd> </dl>
Output Program:
### for eRuby <dl> <% for item in list do %> <dt><%= item.text %></dt> <dd><%= item.desc %></dd> <% end %> </dl> ### for PHP <dl> <?php foreach ($list as $item) { ?> <dt><?php echo $item->text; ?></dt> <dd><?php echo $item->desc; ?></dd> <?php } ?> </dl> ### for JSTL <dl> <c:forEach var="item" items="${list}"> <dt><c:out value="${item.text}" escapeXml="false"/></dt> <dd><c:out value="${item.desc}" escapeXml="false"/></dd> </c:forEach> </dl>
Iteration with Count
'id="Foreach:var=list"
' and 'id="Loop:var=list"
' are directives for iteration with loop counting.
The counter variable is var_ctr
. It starts at 1.
Presentation Data:
<tr id="Foreach:item=list"> <td>@{item_ctr}@</td> <td>@{item}@<td> </tr>
Output Program:
### for eRuby <% item_ctr = 0 %> <% for item in list do %> <% item_ctr += 1 %> <tr> <td><%= item_ctr %></td> <td><%= item %><td> </tr> <% end %> ### for PHP <?php $item_ctr = 0; ?> <?php foreach ($list as $item) { ?> <?php $item_ctr += 1; ?> <tr> <td><?php echo $item_ctr; ?></td> <td><?php echo $item; ?><td> </tr> <?php } ?> ### for JSTL <c:set var="item_ctr" value="0"/> <c:forEach var="item" items="${list}"> <c:set var="item_ctr" value="${item_ctr + 1}"/> <tr> <td><c:out value="${item_ctr}" escapeXml="false"/></td> <td><c:out value="${item}" escapeXml="false"/><td> </tr> </c:forEach>
Iteration with a Toggle Switch
'id="FOREACH:var=list"
' and 'id="LOOP:var=list"
' are directives for iteration with toggle switching.
The toggle switch's value changes depending on whether loop counter is odd or even.
The toggle switch is named var_tgl
.
The value of the toggle switch is '"odd"
' or '"even"
' by default.
You can change them with the command-line option '--odd=value
' and '--even=value
',
or constant variable ODD and EVEN in configuration file kwartz/config.rb.
Presentation Data:
<table> <tbody id="LOOP:item=list"> <tr class="@{item_tgl}@"> <td>@{item}@</td> </tr> </tbody> </table>
Output Program:
### for eRuby <table> <tbody> <% item_ctr = 0 %> <% for item in list do %> <% item_ctr += 1 %> <% item_tgl = item_ctr % 2 == 0 ? "even" : "odd" %> <tr class="<%= item_tgl %>"> <td><%= item %></td> </tr> <% end %> </tbody> </table> ### for PHP <table> <tbody> <?php $item_ctr = 0; ?> <?php foreach ($list as $item) { ?> <?php $item_ctr += 1; ?> <?php $item_tgl = $item_ctr % 2 == 0 ? "even" : "odd"; ?> <tr class="<?php echo $item_tgl; ?>"> <td><?php echo $item; ?></td> </tr> <?php } ?> </tbody> </table> ### for JSTL <table> <tbody> <c:set var="item_ctr" value="0"/> <c:forEach var="item" items="${list}"> <c:set var="item_ctr" value="${item_ctr + 1}"/> <c:set var="item_tgl" value="${item_ctr % 2 eq 0 ? 'even' : 'odd'}"/> <tr class="<c:out value="${item_tgl}" escapeXml="false"/>"> <td><c:out value="${item}" escapeXml="false"/></td> </tr> </c:forEach> </tbody> </table>
Iteration (while)
'id="while:expression"
' is a directive to iterate with a while statement.
Kwartz will raise an error when compiling a while statement into JSP, because there is no custom tag in JSTL which is equivalent to a while statement.
Presentation Data:
<tr id="while:row=sth.fetch()"> <td>@{row[0]}@</td> </tr>
Output Program:
### for eRuby <% while row = sth.fetch() do %> <tr> <td><%= row[0] %></td> </tr> <% end %> ### for PHP <?php while ($row = $sth->fetch()) { ?> <tr> <td><?php echo $row[0]; ?></td> </tr> <?php } ?>
Dummy data
'id="dummy:str"
' is a directive for ignoring an element.
'str
' has no effect. It is to make id attribute value to be unique in the HTML file.
Presentation Data:
<tr id="dummy:d1"> <td>bar</td> </tr> <tr id="dummy:d2"> <td>baz</td> </tr>
Intermediate Code:
// Nothing
Output Program:
// Nothing
Replacement of Elements
'id="replace:name"
' replaces an element with other element
which is already marked with the name name.
Presentation Data:
<html> <body> <!-- breadcrumbs navigation --> <div id="mark:breadcrumbs"> <a href="/">Home</a> > <a href="/kwartz">Kwartz</a> > <a href="/kwartz/ruby">Kwartz-ruby</a> </div> .... <div id="replace:breadcrumbs"> Home > Kwartz > Kwartz-ruby </span> </div> </html
Output Script:
<html> <body> <!-- breadcrumbs navigation --> <div> <a href="/">Home</a> > <a href="/kwartz">Kwartz</a> > <a href="/kwartz/ruby">Kwartz-ruby</a> </div> .... <div> <a href="/">Home</a> > <a href="/kwartz">Kwartz</a> > <a href="/kwartz/ruby">Kwartz-ruby</a> </div> </html
The command-line option '-i file1,file2,...
' enables you to use elements
in other files.
Placeholder
'id="placeholder:name"
' replaces content of the element by other element
which is already marked with the name name.
Usually this directive is used to import elements defined in other files,
with the command-line option -i file1,file2,...
.
Presentation Data(article.html):
<html> <body> <div id="mark:article"> <p>Kwartz is a template system, which realized the concept <strong>`Separation of Presentation Logic and Presentation Data'(SoPL/PD)</strong>. </p> </div> </body> </html>
Presentation Data(layout.html):
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <link rel="stylesheet" type="text/css" href="design.css"> </head> <body> <table border="0"> <tr> <td width="400" id="placeholder:article"> aaa<br> bbb<br> ccc<br> ddd<br> </td> </tr> </table> </body> </html>
Compile:
$ kwartz -i article.html layout.html
Output Script:
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <link rel="stylesheet" type="text/css" href="design.css"> </head> <body> <table border="0"> <tr> <td width="400"> <div> <p>Kwartz is a template system, which realized the concept <strong>`Separation of Presentation Logic and Presentation Data'(SoPL/PD)</strong>. </p> </div> </td> </tr> </table> </body> </html>
Including Presentation Data Files
id="include:filename"
is a directive to read and to include another presentation data file (HTML file).
Included data file can contain directives.
Presentation Data (copyright.html) :
<!-- begin footer --> <center> copyright© <span id="value:year">2005</span> kuwata-lab all rights reserverd </center> <!-- end footer -->
Presentation Data (mainpage.html) :
<html> <body> ... main contents ... <div id="include:copyright.html"> ... copyright ... </div> </body> </html>
Compile:
$ kwartz -l eruby mainpage.html > mainpage.view
Output Script:
### for eRuby <html> <body> ... main contents ... <!-- begin footer --> <center> copyright© <%= year %> kuwata-lab all rights reserverd </center> <!-- end footer --> </body> </html>
'Include
' and 'INCLUDE
' directives are also available.
- '
include
' directive replaces the element by presentation data included. - '
Include
' directive inserts the presentation data included before the element. - '
INCLUDE
' directive inserts the presentation data included after the element.
When presentation data files to be included are placed in other directories,
you can specify those directories with the command-line option --incdirs=dir1,dir2,...
or the constant INCDIRS
in configuration file.
id and kw:d Attributes
- The kw:d attribute is equivalent to the id attribute in Kwartz. Anything that can go in an id attribute can also be placed in a kw:d attribute.
- If a tag has both an id attribute and a kw:d attribte,
Kwartz overrides the former with the latter.
For example, if you write '
id="name" kw:d="foreach:item=list"
',
- However, if the kw:d attribute has only
attr
directives, then the id attribute is not overwritten. For example, if you write 'id="name" kw:d="attr:href=url"
, the element is marked with the namename
.
- The HTML Specification defines that the id attribute value can contain only alphanumeric characters, underscores (
_
), colons(:
), hyphens(-
) and periods(.
). Other characters cannot be in the id attribute. This means thatid="foreach:item=list"
orid="attr:name=value"
are not valid according to the HTML Specification. Therefore, it is recommended to writeid="foreach:item:list"
orid="attr:name:value"
instead.
- You can change the kw:d attribte name with the command-line option
--dattr=xxx
. For example,--dattr=style
make Kwartz to use 'style' attributes instead of 'kw:d' attributes. ConstantDATTR
in configuration file also enables you to change 'kw:d' attribute name.
Notes
These are some notes on the use of directives.
- One id or kw:d attribute can have only one directive.
For example, '
id="set:var=100;value:var"
' causes an error.## NG <span id="set:var=100;value:var">foo</span>
- However, the '
attr:name=value
' directive and the 'append=expression
' directive can be used with other directive in an id attribute, as well as with itself.## OK <foo id="foreach:item=list;attr:class=item.class;attr:href=item.url"> .... </foo>
- You cannot omit end-tags when using Kwartz directives.
But you can use empty-element tags, such as '
<foo .../>
'.## NG <ul> <li id="value:item">foo </ul> ## OK <a id="attr:name=refname"/>
- The <span></span> tag is deleted if it has only directives.
For example, the presentation data '
Hello <span id="value:name">World</span>!
' will be converted into the output script 'Hello <%= name %>!
' (in eRuby), deleting <span></span>.## presentation data Hello <span id="value:name">World</span>! ## output script for eRuby Hello <%= name %>!
- You must describe attributes like
attr="value"
in the start tag which contains directives. In other words, you cannot omit attribute names or attribute values when using directives. This is not a bug; it's an intended behavior so as to make Kwartz available in any text file.## NG <input type="checkbox" id="foreach:item=list" checked/> ## OK <input type="checkbox" id="foreach:item=list" checked="checked"/> ## NG <option id="attr:value=val" @{flag ? 'selected' : ''}@/> ## OK <option value="@{val}@" @{flag ? 'selected' : ''}@>
Command-line options
The script 'kwartz' is a commad-line script to compile templates (presentation data file and presentation logic file) into output scripts.
Usage:
kwartz [options...] [-p plogic ] pdata.html > output-script
Options:
- -h, --help
- Print help.
- -v
- Version information.
- -a action
-
Action to do. action may be one of the following (default is 'compile').
- compile
- Read presentation data and presentation logic, and generate output script.
- analyze
- Read presentation data and presentation logic, and report scope of variables.
- convert
- Read presentation data, and convert to PL program. This is for debugging.
- translate
- Read PL program, and translate into output script. This is for debugging.
- -e , -s
-
Enable auto-sanitizing. This option is equal to
--escape=true
.
- -i file1,file2,...
-
Import elements defined in outer files.
Usually this option is used for 'placeholder' directive ('
id="placeholder:name
').
- -l lang
- Target language of the output script. lang may be eruby, erb, php, jstl11, jstl10.
- -p plogic-file
-
Filename of the presentation logics. It is possible to specify several filename using '
,
' as a separator.
- --charset=charset
-
Character set. Kwartz will print '
<%@ page contentType="text/html; charset=charset" %>
' in JSTL.
- --dname=name
- Attribute name used as a directive. Default is 'kw:d'.
- --escape=true|false
- Auto-sanitizing. If value is ommited then true is used as value.
- --even=value
-
Even value. Default is
'even'
. Directives FOREACH and LIST will use this value.
- --extract=name
- Extract an element which is marked with name name.
- --footer=string
- Footer string.
- --header=string
-
Header string.
'
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
' is used as default in JSP. If you don't want to print any header text, use--header=false
.
- --indent=' '
- Specifies the indent space of output script.
- --incdirs=dir1,dir2,...
-
Specify directories from which '
include
' directive includes.
- --odd=value
-
Odd value. Default is
'odd'
. Directives FOREACH and LIST will use this value.
- --rename=true|false
- Specify rename or not local variable names. Regarded as true when value is omitted.
Examples:
- Compile presentation data file 'file1.html' and get an output script 'file1.rhtml'.
The target language is eRuby.
$ kwartz -l eruby file1.html > file1.rhtml
- Compile presentation data file 'file1.html' and a presentation logic file 'file1.plogic', and get an output script 'file1.php'.
The target language is PHP.
$ kwartz -l php -p file1.plogic file1.html > file1.php
- Convert presentation data into PL program.
$ kwartz -a convert file1.html | more
Configuration options
You can sepcify Kwartz options in configuration file. Configuration file for Kwartz is different for each implementation. It is kwartz/config.rb in Kwartz-ruby.
The following is the options for Kwartz.
- ESCAPE
- Specify auto-sanitizing on/off.
- NEWLINE
- Specify a string which represents newline characters ("\n" or "\r\n") of output script. You don't have to change this option because Kwartz detects newline characters automatically.
- INDENT
- Specify a string which represents indent of output script.
- RENAME
- Specify whether rename local variable names. If true, '_' is added to beginning of local variable name.
- RENAME_PREFIX
- Specify the prefix of local variable name when RENAME is true.
- LANG
- Specify default language for output script.
- ODD
-
Specify odd value of toggle variable.
This is used by
id="FOREACH:var=list"
andid="LOOP:var=list"
.
- EVEN
-
Specify even value of toggle variable.
This is used by
id="FOREACH:var=list"
andid="LOOP:var=list"
.
- DATTR
-
Specify an attribute name for directives. Default is '
kw:d
'.
- NOEND
- List of tag name which doesn't require end tag. Default is [ "input", "br", "meta", "img", "hr" ].
- CHARSET
- Specify character encoding name for jstl11 and jstl10.
- EMBED_PATTERN
- Specify a pattern to embed expression into presentation data.
- INCDIRS
-
Specify a list of directories from which '
include
' directive includes. Default is [ "." ].