Kwartzリファレンスマニュアル

Makoto Kuwata <kwa(at)kuwata-lab.com>
last update: $Date: 2005-04-30 10:56:26 +0900 (Sat, 30 Apr 2005) $

はじめに

このドキュメントは、Kwartzのリファレンスマニュアルです。 プレゼンテーション用言語「PL」、ディレクティブ、コマンドラインオプション、 設定オプションについて説明しています。

目次



プレゼンテーション用言語「PL」

PLとは、Kwartzにおいてプレゼンテーションロジックを記述するのに利用される言語です。 この章では、PLの書き方について説明します。

コメント

/*」と「*/」で囲まれた範囲と、「//」から行末まではコメントになります。

// ここはコメント
/*
  ここもコメント
*/

文字列

文字列は「"..."」または「'...'」で表します。 前者には改行(Line Feed)「\n」と復改(Carriage Returen)「\r」とタブ(Tab)「\t」を含めることができます。

'foo bar'         // 文字列
"foo bar\n"       // 改行を含む文字列

真偽値、null

式の中で truefalsenull が使えます。

flag = obj == null ? true : false;

truefalsenullは各言語において次のように変換されます。

truefalsenullの変換
変換先言語 true false null
PHP TRUE FALSE NULL
eRuby true false nil
JSP(JSTL) true false null
Velocity true false -

なおVelocityではnullやそれに類するキーワードがありません。 そのため、nullを含むPLプログラムをVelocityに変換するとエラーになります。 ただしnullとの比較を行う論理式は、nullを使わない式に変換されます。

PLプログラム:

flag = obj == null? true : false;

if (expr != null) {
  print("expr is not null.\n");
} else {
  print("epxr is null.\n");
}

出力用スクリプト:

### for Velocity
#if($obj)
  #set($flag = true)
#else
  #set($flag = false)
#end
#if(! $expr)
expr is not null.
#else
epxr is null.
#end

変数

変数はアルファべットまたは「_」で始まり、アルファベットと数字と「_」が連続したものです。

また変数には型がなく、変数宣言もする必要がありません(*1)

(*1)
この性質から、PLまたはPL-Kwartzで書かれたプログラムを、変数に型のある言語や変数宣言が必要な言語に変換するのは困難です。

演算子

演算子には次のものが使用できます。基本的には、文字列用と数値用とで演算子を分けてはいません(*2)

演算子
比較演算子 == != < <= > >=
論理演算子 && || !
算術演算子 + - * / %
文字列の連結 .+
条件演算子 ?:

文字列の連結演算子「.+」は、eRubyでは「+」に、PHPでは「.」に、 JSTL1.1では関数fn:join()に変換されます。 JSTL1.0では連結演算子がないので、トリッキーな方法で凌いでいます。 Velocityではエラーになります。

PLプログラム(PL):

filename = basename .+ '.plogic';

出力用スクリプト:

### 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'}"/>

条件演算子(3項演算子)はeRubyとPHPとJSTL1.1では使用できますが、JSTL1.0とVelocityでは使用できません。 そのため条件演算子を含む式は、JSTL1.0とVelocityではif文(JSTL1.0ならif文に相当する<c:choose>)に変換されます。

PLプログラム(PL):

color = ctr % 2 == 0 ? '#FFCCCC' : '#CCCCFF';

出力用スクリプト:

### 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>

### for Velocity
#if($ctr % 2 == 0)
  #set($color = "#FFCCCC")
#else
  #set($color = "#CCCCFF")
#end
(*2)
Perlのように文字列用と数値用とで演算子が異なる言語に対しては、Kwartzを対応させるのは困難です。

出力

出力は「print(...);」で表します。 引数には任意の式を書くことができます。

PLプログラム:

print('foo', bar, "baz\n");    // 文字列と変数を出力

出力用スクリプト:

### for eRuby
foo<%= bar %>baz

### for PHP
foo<?php echo $bar; ?>baz

### for JSTL
foo<c:out value="${bar}" escapeXml="false"/>baz

### for Velocity
foo$!{bar}baz

自動サニタイズ機能を使用した場合は次のような出力になります。

### 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

### for Velocity
foo$!esc.html($bar)baz

また自動サニタイズ機能を使用しても、条件演算子が返す値が文字列または数字である場合は、サニタイズされません。

PLプログラム:

// サニタイズされる
print("<option ", condition ? var1 : var2, ">\n");
// サニタイズされない(必要がないから)
print("<option ", condition ? 'selected' : '', ">\n");

出力用スクリプト:

### 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"/>>

print(a .+ b .+ c);」は「print(a); print(b); print(c);」と展開されます。 これは、文字列の連結演算子「.+」をサポートしていない一部の言語を考慮した仕様です。


代入

代入は「var = 100;」のように行います。 また、「+=」「-=」「*=」「/=」「%=」「.=」も使用できます。

PLプログラム:

name = 'Foo';		// 文字列を代入
count += 1;		// 値を1増やす
str .+= '.txt';		// 文字列の末尾に追加

出力用スクリプト:

### 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'}"/>

配列、ハッシュ

配列は「arr[expr]」の形で参照できます。 ハッシュも同じ形で参照できます(*3)

JSTLでは配列やハッシュの要素を参照することはできますが、配列やハッシュの要素に代入することはできません。

PLプログラム:

list[n] = 10;           // n番目の要素に代入
print(list[i], "\n");   // i番目の要素を出力
hash['key'] = 'foo';    // ハッシュの要素に代入
print(hash['key'], "\n"); // ハッシュの要素を出力

出力用スクリプト:

### 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"]; ?>

ハッシュは、「hash[:key]」という形でも参照できます。 このとき、「key」は英数字と「_」のみからなる文字列である必要があります。

hash[:key]」は、各プログラム言語に応じて次のように変換されます。

hash[:key]」の変換結果
ターゲット言語 変換結果
eRuby hash[:key]
PHP $hash['key']
JSTL hash['key']
Velocity hash.key

PLプログラム:

print(hash[:key]);

出力用スクリプト:

### for eRuby
<%= hash[:key] %>

### for PHP
<?php echo $hash['key']; ?>

### for JSTL
<c:out value="${hash['key']}" escapeXml="false"/>

### for Velocity
$!{hash.key}
(*3)
配列とハッシュとで同じ演算子を用いているため、Perlのように異なる演算子を必要とするプログラミング言語への変換は困難です。

プロパティとメソッド

オブジェクトのプロパティは、「object.property」の形式で参照します。 また「object.method(arg1, arg2, ..)」のように引数をつけてメソッドを呼ぶこともできます。 ただし、メソッド呼び出しはJSTLではサポートしてませんので、JSTLへの変換時にはエラーになります。

PLプログラム:

// property
user.name = 'Foo';
print(user.name, "\n");

出力用スクリプト:

### 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"/>

### for Velocity
#set($user.name = "Foo")
$!{user.name}

PLプログラム:

// method call
print(user.method(10, 20));

出力用スクリプト:

### for eRuby
<%= user.method(10, 20) %>

### for PHP
<?php echo $user->method(10, 20); ?>

### for Velocity
$!{user.method(10, 20)}

またPLではオブジェクトやプロパティを参照することはできても、オブジェクトを自分で生成したりクラスを定義したりすることはできません。 それらはPLの外部で(つまりメインプログラムの中で)行われることになります。


繰り返し

繰り返しは「foreach(loopvar in list) { ... }」で表します。 いわゆるforeach文であり、listの要素をひとつひとつloopvarに代入しながら繰り返しを行います。

PLプログラム:

foreach(item in list) {     // listの要素をitemに代入しながら
  print(item, "\n");        // 繰り返し出力する
}

出力用スクリプト:

### 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>

### for Velocity
#foreach($item in $list)
$!{item}
#end

またwhile文も使用できます。 ただし、JSTLおよびVelocityにはwhile文に相当するカスタムタグやディレクティブがないため、 JSTLまたはVelocityへ変換しようとするとエラーになります。

PLプログラム:

i = 0;
while(i < length) {
  i += 1;
  print(list[i]);
}

出力用スクリプト:

### 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 } ?>

なおJavaやCのようなfor文は用意されていません。ご注意ください。


条件分岐

条件分岐は「if(condition) { ... } else if(condition) { ... } else { ... }」で表します。

PLプログラム:

if (val > 0) {
  print ("* value is positive.\n");
} else if (val < 0) {
  print ("* value is negative.\n");
} else {
  print ("* value is zero.\n");
}

出力用スクリプト:

### 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>

### for Velocity
#if($val > 0)
* value is positive.
#elseif($val < 0)
* value is negative.
#else
* value is zero.
#end

関数

PLでは、以下の関数を使用することができます。

E(expr)
expr をサニタイズします。サニタイズはコマンドラインオプションの指定に関わらず行われます。 E()は擬似関数であり、実際にはprint文の引数でしか使用できません。
X(expr)
式 expr をサニタイズしません。つまりコマンドラインオプションでサニタイズするよう指定されていても、 X(expr)で指定された式はサニタイズされません。 X()は擬似関数であり、実際にはprint文の引数でしか使用できません。
C(expression)
expression ? ' checked="checked"' : ''」と同じです。
S(expression)
expression ? ' selected="selected"' : ''」と同じです。
D(expression)
expression ? ' disabled="disabled"' : ''」と同じです。
list_new()
新しいリストを作成します。
list_length(list)
リストlistの長さを返します。
list_empty(list)
リストlistが空ならtrueを、空でないならfalseを返します。
hash_new()
新しいハッシュを作成します。
hash_length(hash)
ハッシュhashの長さ(要素の数)を返します。
hash_empty(hash)
ハッシュhashが空ならtrueを、空でないならfalseを返します。
hash_keys(hash)
ハッシュの全キーをリストで返します。
str_length(string)
文字列stringの長さを返します。
str_empty(string)
文字列stringが空ならtrueを、空でないならfalseを返します。
str_tolower(string)
文字列stringを小文字にして返します。
str_toupper(string)
文字列stringを大文字にして返します。
str_trim(string)
文字列stringの前後から空白を取り除いた文字列を返します。
str_index(string, char)
文字列stringにおいて文字charのある場所を返します。
str_replace(string, before, after)
文字列stringにおいて、文字列beforeを文字列afterに置き換えたものを返します。
str_linebreak(string)
文字列stringにおいて、改行のまえに<br />を挿入したものを返します。
escape_xml(html_string)
文字列html_stringをサニタイズします。
escape_url(url_string)
文字列url_stringをURL形式でエンコードします。
escape_sql(sql_string)
文字列sql_string中の「'」「"」「\」をバックスラッシュでエスケープします。

どのように変換されるかは次をご覧ください。

関数名 eRuby, ERB PHP JSTL1.1 Velocity
list_new() [] array() - -
list_length(list) list.length array_length(list) fn:length(list) (list).size()
list_empty(list) list.empty? array_length(list)==0 fn:length(list)==0 (list).size()==0
hash_new() {} array() - -
hash_length(hash) hash.length array_length(hash) fn:length(hash) hash.size()
hash_empty(hash) hash.empty? array_length(hash)==0 fn:length(hash)==0 hash.size()==0
hash_keys(hash) hash.keys array_keys(hash) - hash.keySet().toArray()
str_length(str) str.lenth strlen(str) fn:length(str) str.length()
str_tolower(str) str.downcase strtolower(str) fn:toLowerCase(str) str.toLowerCase()
str_toupper(str) str.upcase strtoupper(str) fn:toUpperCase(str) str.toUpperCase()
str_index(str,ch) str.index(ch) strchr(str,ch) fn:indexOf(str,ch) str.indexOf(ch)
str_replace(str,before, after) str.gsub(before,after) str_replace(before,after,str) fn:replace(str,before,after) str.indexOf(ch)
str_linebreak(str) str.gsub(/\r?\n/,'<br />\&') nl2br(str) fn:replace(str,'\n','<br />\n') str.replaceAll('$','<br />')
escape_xml(str) CGI::escapeHTML(str) (when eRuby)
html_escape(str) (when ERB)
htmlspecialchars(str) fn:escapeXml(str) $esc.xml(str)
escape_url(str) CGI::escape(str) (when eRuby)
url_encode(str) (when ERB)
urlencode(str) - $link.setURI(str).toString()
escape_sql(str) str.gsub(/['"\\\0]/,'\\\&') addslashes(str) - $esc.sql(str)

これら以外の関数が指定されたときは、次のように動作します。

E()とX()は、print文の引数として使われることを想定しています。 それ以外の場所では使わないでください。

Velocityでは、以下の関数を使うためにVelocityToolsをインストールする必要があります。

詳細はそれぞれのドキュメントを参照してください。


empty

値がnullまたは空文字列かどうかを調べるための予約語「empty」を用意しています。 「empty」は「==」または「!=」の右辺にのみ置くことができ、左辺がnullか空文字列なら真を、それ以外なら偽を返します。

PLプログラム:

if (str1 == empty) {
  print("str1 is empty.\n");
} else if (str2 != empty) {
  print("str2 is not empty.\n");
}

出力用スクリプト:

### 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>

### for Velocity
#if(! $str1 || $str1 == "")
str1 is empty.
#elseif($str2 && $str2 != "")
str2 is not empty.
#end

エレメント宣言

エレメント宣言とは、「id="name"」または「id="mark:name"」でマーキングされたエレメントに対して、属性を操作したり、プレゼンテーションロジックを変更するための記述です。 Kwartzでは、プレゼンテーションロジックファイルはエレメント宣言の集合として記述されます。

エレメント宣言は、「#name」および複数の宣言部から構成されます。

value: expression;
エレメントの内容を式expressionの値で置き換えます。
attrs: "attr1" expr1 , "attr2" expr2 , ... ;
属性attrの値を式exprで置き換えます。
remove: "attr1" , "attr2" , ... ;
属性attrを削除します。
append: expr1 , expr2 , ... ;
タグに式exprの値を追加します。 <input>タグや<option>タグにおいて「checked」や「selected」を追加するときに使用します。
tagname: expression;
タグの名前を式expressionで置き換えます。 StrutsやJSFのカスタムタグを利用するときに使用します。
plogic: { ... }
プレゼンテーションロジックを記述します。 { ... } の中では @stag@cont@etag が使用でき、それぞれ開始タグ、内容、終了タグを表します。 また @element(other) も使用でき、これはほかの名前がつけられたエレメントを展開することを表します。

プレゼンテーションデータ:

<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>

プレゼンテーションロジック:

#foo {
  value:  item;
  attrs:  "class" klass;
  plogic: {
    foreach (item in list) {
      @stag;
      @cont;
      @etag;
    }
  }
}
#chkbox {
  remove:  "checked";
  append:  flag ? " checked" : "";
  tagname: "html:text";
}

出力用スクリプト:

### 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>

### for Velocity
<ul>
#foreach($item in $list)
  <li id="foo" class="$!{klass}">$!{item}</li>
#end
</ul>

<form action="foo.cgi">
#if($flag)
  <html:text type="checkbox" name="user" value="Y" checked />
#else
  <html:text type="checkbox" name="user" value="Y" />
#end
</form>

ドキュメント宣言

#DOCUMENT { ... }は、ドキュメントのための特殊なエレメント宣言です。 この宣言はドキュメント全体の情報を表し、次の宣言部を使用します。

begin: { ... }
出力用スクリプトの先頭に、指定されたPLコードを追加します。
end: { ... }
出力用スクリプトの末尾に、指定されたPLコードを追加します。
require: "filename1" , "filename2", ... ;
プレゼンテーションロジックファイルを読み込みます。
global: varname1 , varname2 , ... ;
グローバル変数を列挙します。現在は何も使われていませんが、将来は使う予定です。
local: varname1 , varname2 , ... ;
ローカル変数を列挙します。現在は何も使われていませんが、将来は使う予定です。

プレゼンテーションデータ:

<ul id="mark:list">
  <li id="value:item">foo</li>
</ul>

PLプログラム:

#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;
  }
}

出力用スクリプト:

### 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. -->

### for Velocity
#set($list = $context.list)
<ul>
#foreach($item in $list)
  <li>$!{item}</li>
#end
</ul>
<!-- copyright(c) 2005 kuwata-lab.com ALL RIGHTS RESERVERD. -->

ターゲット言語のプログラムコード

ターゲット言語(Ruby,PHP,Javaなど)のプログラムコードを直接記述することもできます。 Kwartzではターゲット言語で書かれたコードをRawcodeと呼んでいます。

次の例は、Rubyコードを直接記述した例です。

PLプログラム:

// Rawcode式
hash = <%= { :a => 123, :b => 456, :c => 789, } %>;

// Rawcode文
<% hash.each do |key, value| %>
print("key=", key, " value=", value, "\n");
<% end %>

出力用スクリプト:

### for eRuby
<% hash = { :a => 123, :b => 456, :c => 789, } %>
<% hash.each do |key, value| %>
key=<%= key %> value=<%= value %>
<% end %>

次の例は、PHPのコードを直接記述した例です。

PLプログラム:

// Rawcode式
hash = <?= array("a"=>123, "b"=>456, "c"=>789) ?>;

// Rawcode文
<?php foreach($hash as $key => $value) { ?>
print("key=", key, " value=", value, "\n");
<?php } ?>

出力用スクリプト:

### for PHP
<?php $hash = array("a"=>123, "b"=>456, "c"=>789); ?>
<?php foreach($hash as $key => $value) { ?>
key=<?php echo $key; ?> value=<?php echo $value; ?>
<?php } ?>

Rawcode文は、エレメント宣言の「plogic:」部に記述できます。 またRawcode式は、「value:」部や「attrs:」部に記述できます。 なおRawcode式を「X(<%= ... %>)」のように記述すれば、サニタイズしません。

Rawcodeを用いてKwartzをRuby on Railsで使うサンプルが、Kwartzアーカイブのexamples/rails1ディレクトリにあります。 参考にしてください。

ターゲット言語のプログラムコードを直接記述した場合は、当然ですが他の言語では使用できなくなります。 それでも構わない場合にのみ使用してください。


グローバル変数とローカル変数

Kwartzでは、メインプログラムから出力用プログラムに渡される変数をテンプレートグローバル変数、テンプレートの中だけで使用される変数をテンプレートローカル変数と呼んでいます。

例えば次のようなプレゼンテーションデータとプレゼンテーションロジックを考えます。

プレゼンテーションデータ(analyze.html):

<table>
  <caption id="value:title">Sample</caption>
  <tr id="mark:items" bgcolor="@{color}@">
    <td id="value:item">Foo</td>
  </tr>
</table>

プレゼンテーションロジック(analyze.plogic):

#items {
  plogic: {
    ctr = 0;
    foreach (item in list) {
      ctr += 1;
      color = ctr%2 == 0 ? '#FFCCCC' : '#CCCCFF';
      @stag;
      @cont;
      @etag;
    }
  }
}

いくつかの変数がでてきますが、これらは次のように分類できます。

テンプレートグローバル変数
変数「title」と「list」は、メインプログラムからテンプレートに渡される変数であり、メインプログラムで値を設定する必要があります。 Kwartzではこれをテンプレートグローバル変数と呼んでいます。
テンプレートローカル変数
変数「item」と「ctr」と「color」はテンプレートの中だけで使用される変数であり、メインプログラムで設定する必要はありません。 Kwartzではこれをテンプレートローカル変数と呼んでいます。

kwartzコマンドにオプション「-a analyze」をつけて起動すると、テンプレートを分析してテンプレートグローバル変数とテンプレートローカル変数を報告してくれます。

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

このとき、Kwartzは次のようなルールでグローバルかローカルかを判定しています。

またテンプレートグローバル変数へ代入したり、テンプレートグローバル変数をループ変数としていると、分析時に警告を出します。 なぜなら、テンプレートシステムはメインプログラムで設定されたデータの表示のみを行うべきであり、それらを変更すべきではないから、つまりテンプレートグローバル変数を変更すべきではないからです(変更してよいのはテンプレートローカル変数のみのはずです)。

テンプレート(プレゼンテーションデータとプレゼンテーションロジック)が複雑になると、メインプログラムで設定しなければならない変数がどれか、わかりづらくなることがあります。 そのようなときは、この分析機能を利用してください。変数名のタイプミスも見つけやすくなります。


未実装(または検討中)の機能

以下の機能は実装されていませんが、将来において実装されるかもしれません。



ディレクティブ

ディレクティブとは?

Kwartzでは、プレゼンテーションデータの中にプレゼンテーションロジックを埋め込むこともできます。 そのための命令を「ディレクティブ(Directive)」といいます。

ディレクティブとは、プレゼンテーションデータの中にプレゼンテーションロジックを埋め込むための命令です。 Kwartzでは、ディレクティブはid属性またはid属性を使用します(使い方はどちらも同じです)。 「id="name"」や「id="mark:name"」も、「マーキング」というディレクティブです。

Kwartzではせっかくプレゼンテーションデータとプレゼンテーションロジックとを分離することができるのに、なぜ両者を一体化するような機能も用意されているのでしょう?

それは、開発者の好みに応じてどちらも選べるようにするため、つまり「選択可能性(choosability)」を高めるためです。 Kwartzは、開発者にどちらか一方を押しつけるようなことはしません。 分離するほうが望ましいのであれば分離すればよいし、一体化するほうが好みであれば一体化すればよいのです。

また両者を一体化すると、他のテンプレートと差別化できないと思われるかもしれません。 しかし一体化してもなお、Kwartzは他のテンプレートと比べて次のような利点があります。


マーキング

id="name"」または「id="mark:name"」とすることで、マーキングを行います。 マーキングとは、エレメントに対してその名前で目印をつけることです。

id="name"」と「id="mark:name"」との違いは、コンパイルされると前者ではid属性が残るのに対し後者は取り除かれるという点です。 またkw:d属性は必ず取り除かれます。

プレゼンテーションデータ:

<div id="foo">foo</div>
<div id="mark:bar">bar</div>

出力用スクリプト:

### 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>

### for Velocity
<div id="foo">foo</div>
<div>bar</div>

値の出力

@{expression}@」は、式の値を出力するディレクティブです。 このパターンは、設定ファイルのEMBED_PATTERNに設定されています。

プレゼンテーションデータ:

Hello @{user.name}@!

出力用プログラム:

### for eRuby
Hello <%= user.name %>!

### for PHP
Hello <?php echo $user->name; ?>!

### for JSTL
Hello <c:out value="${user.name}" escapeXml="false"/>!

### for Velocity
Hello $!{user.name}!

コンパイル時に、コマンドオプション-eを指定した場合は、式をサニタイズして出力します。 このとき、文字列や数値はサニタイズされず、式のみがサニタイズされることに注意してください。

出力用プログラム(コマンドオプション-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}"/>!

### for Velocity
Hello $!esc.html($user.name)!

コマンドオプションの有無に関わらずサニタイズをする/しないを指定するには、関数E()X()を使用します。 E(expr)は式exprをサニタイズし、X(expr)はサニタイズしません。

プレゼンテーションデータ:

With sanitizing:    @{E(var)}@!
Without sanitizing: @{X(var)}@!

出力用プログラム:

### 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"/>!

### for Velocity
With sanitizing:    $!esc.html($var)!
Without sanitizing: $!{var}!

. .


値の出力2

id="value:expression"」とすることで、内容のかわりに式の値を出力します。 ダミーデータを利用できるため、「@{expression}@」と比べてHTMLデザインがより崩れません。

プレゼンテーションデータ:

<li id="value:hash['name']">foo</li>

出力用プログラム:

### 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>

### for Velocity
<li>$!{hash["name"]}</li>

また「id="Value:expr"」でサニタイズすることを、「id="VALUE:expr"」でサニタイズしないことを指定できます。 これらはそれぞれ「id="value:E(expr)"」や「id="value:X(expr)"」と同じです。


属性値の設定

id="attr:name=value"」または「id="attr:name:value"」とすることで、タグの属性値を設定できます。 これを用いると、「@{...}@」を使わずに属性値を設定でき、またダミーの属性値を設定できます。

次の例では、属性classにダミーの属性値 "odd" を設定していますが、実際には変数klassの値を用いるようにしています。

プレゼンテーションデータ:

<tr class="odd" id="attr:class=klass">
  <td>foo</td>
</tr>

出力用プログラム:

### 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>

### for Velocity
<tr class="$!{klass}">
  <td>foo</td>
</tr>

また「id="Attr:name=value"」でサニタイズすることを、「id="ATTR:name=value"」でサニタイズしないことを指定できます。 これらはそれぞれ「id="attr:name=E(value)"」や「id="attr:name=X(value)"」と同じです。

なお「;」で区切ることにより、「attr:name=value」を複数設定したり他のテンプレートコマンドと一緒に設定したりできます。

プレゼンテーションデータ:

<font id="if:message!=empty;attr:class=klass;attr:bgcolor=color">
 @{message}@
</font>

出力用スクリプト:

### 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>

### for Velocity
#if($message && $message != "")
<font class="$!{klass}" bgcolor="$!{color}">
 $!{message}
</font>
#end

属性の追加

id="append:expression"」とすることで、タグの中に式の値を追加できます。 これは主に「<input ... checked />」や「<option ... selected></option>」を実現するための機能です。

プレゼンテーションデータ:

<option name="lang" value="ruby"
       id="append:lang=='ruby'?' selected':''">Ruby</option>
<input type="radio" name="gender" value="M"
       id="append:gender=='M'?' checked':''">

出力用スクリプト:

### 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>

なお「checked="checked"」「selected="selected"」「disabled="disabled"」の出力を簡単にするための機能として、関数「C(expr)」「S(expr)」「D(expr)」が用意されています。 これらは、式exprが真のときにそれぞれ「checked="checked"」「selected="selected"」「disabled="disabled"」を出力します。

プレゼンテーションデータ:

<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

出力用スクリプト:

### 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

変数への代入

id="set:var=value"」は、変数varに値valueを設定します。 「=」だけでなく「+=」「-=」「*=」「/=」「.=」が使用できます。

プレゼンテーションデータ:

<dt id="set:var=value">foo</dt>
<dd id="set:count+=1">123</dd>

出力用プログラム:

### 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>

### for Velocity
#set($var = $value)
<dt>foo</dt>
#set($count = $count + 1)
<dd>123</dd>

条件分岐

id="if:expression"」とすることで、条件分岐を行います。 elseやelseifも使用できます。

プレゼンテーションデータ:

<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>

出力用プログラム:

### 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>

### for Velocity
#if($value > 0)
<div>
  Value is positive.
</div>
#elseif($value < 0)
<div>
  Value is negative.
</div>
#else
<div>
  Value is zero.
</div>
#end

elseif」や「else」を使う場合は、直前に空行を入れないようにしてください。


繰り返し(foreach)

id="foreach:loopvar=list"」(または「id="foreach:loopvar:list"」)とすることで、リストlistの要素をひとつずつ変数loopvarに代入しながら、繰り返しを行います。

プレゼンテーションデータ:

<tr id="foreach:item=list">
  <td>@{item}@</td>
</tr>

出力用プログラム:

### 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>

### for Velocity
#foreach($item in $list)
<tr>
  <td>$!{item}</td>
</tr>
#end

繰り返し(loop)

id="loop:loopvar=list"」(または「id="loop:loopvar:list"」)とすることで、リストlistの要素をひとつずつ変数loopvarに代入しながら繰り返しを行います。 「id="foreach:loopvar=list)"」とよく似ていますが、開始タグと終了タグを含めず、内容だけ繰り返す点が異なります。 <dl></dl>で使うと非常に便利です。

プレゼンテーションデータ:

<dl id="loop:item=list">
  <dt>@{item.text}@</dt>
  <dd>@{item.desc}@</dd>
</dl>

出力用プログラム:

### 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>

### for Velocity
<dl>
#foreach($item in $list)
  <dt>$!{item.text}</dt>
  <dd>$!{item.desc}</dd>
#end
</dl>

カウンタつき繰り返し(Foreach,Loop)

id="Foreach:var=list)"」や「id="Loop:var=list)"」を使うと、カウンタを増やしながら繰り返しを行います。 カウンタは1から始まり、変数名はvar_ctrです。

プレゼンテーションデータ:

<tr id="Foreach:item=list">
  <td>@{item_ctr}@</td>
  <td>@{item}@<td>
</tr>

出力用プログラム:

### 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>

### for Velocity
#set($item_ctr = 0)
#foreach($item in $list)
  #set($item_ctr = $item_ctr + 1)
<tr>
  <td>$!{item_ctr}</td>
  <td>$!{item}<td>
</tr>
#end

トグルつき繰り返し(FOREACH,LOOP)

id="FOREACH:var=list"」や「id="LOOP:var=list"」とすると、トグルつきの繰り返しを行うことができます。 トグルは、繰り返し回数が奇数回か偶数回かによって、値が入れ替わります。 トグル変数の名前はvar_tglです。 トグルの値はデフォルトで「"odd"」と「"even"」が使われますが、コマンドオプション --odd と --even で指定できます。 また設定ファイルkwartz/config.rbの定数ODDとEVENでも指定できます。

プレゼンテーションデータ:

<table>
  <tbody id="LOOP:item=list">
    <tr class="@{item_tgl}@">
      <td>@{item}@</td>
    </tr>
  </tbody>
</table>

出力用プログラム:

### 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>

### for Velocity
<table>
  <tbody>
#set($item_ctr = 0)
#foreach($item in $list)
  #set($item_ctr = $item_ctr + 1)
  #if($item_ctr % 2 == 0)
    #set($item_tgl = "even")
  #else
    #set($item_tgl = "odd")
  #end
    <tr class="$!{item_tgl}">
      <td>$!{item}</td>
    </tr>
#end
  </tbody>
</table>

繰り返し(while)

id="while:expression"」とすることで、繰り返しを行うことができます。

またJSPとVelocityでは、whileを変換しようとするとエラーになります。 これは、whileに対応するカスタムタグやディレクティブがないからです。

プレゼンテーションデータ:

<tr id="while:row=sth.fetch()">
  <td>@{row[0]}@</td>
</tr>

出力用プログラム:

### 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 } ?>

ダミーデータ

id="dummy:str"」とすることで、そのノードをダミーデータとみなして読み飛ばします。

strは、id属性の値が重ならないようにするためのものであり、意味はありません。

プレゼンテーションデータ:

<tr id="dummy:d1">
  <td>bar</td>
</tr>
<tr id="dummy:d2">
  <td>baz</td>
</tr>

中間コード:

                          // 何も出力されない

出力用プログラム:

                          // 何も出力されない

エレメントの置換

id="replace:name"」とすることで、そのエレメントを別のエレメントに置き換えることができます。

プレゼンテーションデータ:

<html>
  <body>
    <!-- ナビゲーション -->
    <div id="mark:breadcrumbs">
      <a href="/">Home</a>
      &gt; <a href="/kwartz">Kwartz</a>
      &gt; <a href="/kwartz/ruby">Kwartz-ruby</a>
    </div>

   ....

    <div id="replace:breadcrumbs">
      Home &gt; Kwartz &gt; Kwartz-ruby
    </span>
  </div>
</html

出力用スクリプト:

<html>
  <body>
    <!-- ナビゲーション -->
    <div>
      <a href="/">Home</a>
      &gt; <a href="/kwartz">Kwartz</a>
      &gt; <a href="/kwartz/ruby">Kwartz-ruby</a>
    </div>

   ....

    <div>
      <a href="/">Home</a>
      &gt; <a href="/kwartz">Kwartz</a>
      &gt; <a href="/kwartz/ruby">Kwartz-ruby</a>
    </div>
</html

なおコマンドラインオプション「-i file1,file2,...」を指定すると、 他のファイルのエレメントを利用できます。


プレースホルダ

id="placeholder:name"」とすることで、そのエレメントの内容を別のエレメントで置き換えます。 通常は、コマンドラインオプション「-i file1,file2,...」とともに使用し、 他のファイルで定義されたエレメントを取り込むために使われます。

プレゼンテーションデータ(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>

プレゼンテーションデータ(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>

コンパイル:

$ kwartz -i article.html 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">
    <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>

プレゼンテーションデータファイルの読み込み

id="include:filename"」で他のプレゼンテーションデータファイル(HTMLファイル)を読み込むことができます。 読み込まれる側のファイルでも、ディレクティブを使用できます。

プレゼンテーションデータ(copyright.html):

<!-- begin footer -->
<center>
  copyright&copy; <span id="value:year">2005</span> kuwata-lab all rights reserverd
</center>
<!-- end footer -->

プレゼンテーションデータ(mainpage.html):

<html>
  <body>

    ... main contents ...

    <div id="include:copyright.html">
      ... copyright ...
    </div>

  </body>
</html>

コンパイル:

$ kwartz -l eruby mainpage.html > mainpage.view

出力用スクリプト:

### for eRuby
<html>
  <body>

    ... main contents ...

<!-- begin footer -->
<center>
  copyright&copy; <%= year %> kuwata-lab all rights reserverd
</center>
<!-- end footer -->

  </body>
</html>

include」ディレクティブのほかに、「Include」と「INCLUDE」が使用できます。

includeディレクティブで読み込むファイルは、別ディレクトリに置くことができます。 ファイルが置いてあるディレクトリは、コマンドラインオプション --incdirs=dir1,dir2,... または設定ファイルの INCDIRS で指定できます。


id属性とkw:d属性について

Kwartzでは、ディレクティブを記述するのにid属性とkw:d属性が使用できます。 ここでは、両者の使い分けについて説明します。

今までid属性で説明していましたが、すべてkw:d属性に書いても動作します。


注意事項

ディレクティブを使用する際の注意事項です。



プレゼンテーションロジックファイル

プレゼンテーションロジックファイルの書き方です。

プレゼンテーションロジック:

「id="mark:name"」でマーキングされたエレメントの宣言
#name {
  
  // 内容のかわりに出力する式
  value:  expression;
  
  // 属性(名前と値)
  attrs: "attr1" expr1, "attr2" expr2, "attr3" expr3;
  
  // 削除する属性の名前
  remove:  "attr1", "attr2", "attr3";
  
  // 開始タグに追加する式
  append:  expr1, expr2, expr3;
  
  // タグ名
  tagname: "tagname",

  // プレゼンテーションロジック本体
  plogic: {
    @stag;
    @cont;
    @etag;
  }
}

// ドキュメント宣言
#DOCUMENT {
  // はじめに実行されるロジック
  begin: {
    ...
  }

  // 最後に実行されるロジック
  end: {
    ...
  }
  
  // 他のプレゼンテーションロジックファイルを読み込む
  require: "file1.plogic", "file2.plogic";
}

コマンドラインオプション

テンプレートを出力用プログラムへコンパイルするには、kwartzコマンドを使用します。

使い方: kwartz [options...] [-p plogic ] pdata.html > output-script

オプションは次の通りです。

-h, --help
ヘルプを表示。
-v
バージョン情報を表示
-a action
実行する処理。actionには次のどれかを指定する(デフォルトはcompile)。
compile
プレゼンテーションデータとプレゼンテーションロジックを読み込み、出力用スクリプトを生成します。
analyze
プレゼンテーションデータとプレゼンテーションロジックを読み込み、変数のスコープを解析します。
defun
プレゼンテーションデータとプレゼンテーションロジックを読み込み、RubyまたはPHPの関数に変換します。
convert
プレゼンテーションデータを読み込み、PLプログラムに変換します。デバッグ用です。
transalte
PLプログラムを読み込み、出力用スクリプトに変換します。デバッグ用です。
-e , -s
サニタイズを行う。--escape=trueと同じ。
-i file1,file2,...
外部ファイルで定義されたエレメントをインポートする。 主にplaceholderディレクティブ(「id="placeholder:name」)のために使用される。
-l lang
ターゲット言語を指定。指定できるのは eruby, erb, php, jstl11, jstl10, velocity.
-p plogic-file
プレゼンテーションロジックのファイル名。「,」で区切ることで、複数のファイル名を指定できる。
-R arg
特殊オプション。今のところ以下の引数のみ指定可能。
  • ails ... 「-l erb --globalvar-prefix='@'」と同じ。Ruby on Rails用のファイルを出力する。
--charset=charset
文字コード。JSTLにおいて '<%@ page contentType="text/html; charset=charset "%>' を出力する。
--dname=name
ディレクティブで使用する属性名。デフォルトは 'kw:d'。
--escape=true|false
式をサニタイズして出力する。値が省略されたときはtrueが指定されたものとみなす。
--even=value
偶数のときの値。デフォルトは「'even'」。ディレクティブFOREACHとLISTで使われる。
--extract=name
指定された名前でマーキングされたエレメントだけを抽出する。
--footer=string
フッター文字列。
--header=string
ヘッダー文字列。 JSPではデフォルトで '<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>' が設定される。 これを出力したくないときは --header=false とする。
--indent=' '
出力用スクリプトのインデントを指定する。
--incdirs=dir1,dir2,...
includeディレクティブで読み込むファイル(プレゼンテーションデータファイル)のディレクトリを指定する。
--odd=value
奇数のときの値。デフォルトは「'odd'」。ディレクティブFOREACHとLISTで使われる。
--localvar-prefix=string
テンプレートローカル変数につけるプレフィックスを指定する。
--globalvar-prefix=string
テンプレートグローバル変数につけるプレフィックスを指定する。

使い方の例です。


設定オプション

設定ファイルで、Kwartzのオプションを指定できます。 Kwartzの設定ファイルは、実装ごとに異なります。 Kwartz-rubyでは、kwartz/config.rbです。

設定ファイルでは、以下のオプションが設定できます。

ESCAPE
自動サニタイズをデフォルトでオンにするか、オフにするかを指定します。
NEWLINE
改行を表す文字列を指定します。 ただし、Kwartzは改行が「\n」か「\r\n」かを自動判別することができるので、通常は変更する必要はありません。
INDENT
インデントとして使う空白文字列を指定します。
LOCALVAR_PREFIX
テンプレートローカル変数のプレフィックス(頭につける文字列)を指定します。
GLOBALVAR_PREFIX
テンプレートグローバル変数のプレフィックス(頭につける文字列)を指定します。
LANG
デフォルトの出力用言語を指定します。
ODD
トグル変数の奇数値を指定します。 「id="FOREACH:var=list"」と「id="LOOP:var=list"」で使用されます。
EVEN
トグル変数の偶数値を指定します。 「id="FOREACH:var=list"」と「id="LOOP:var=list"」で使用されます。
DATTR
ディレクティブで使用する属性名を指定します。デフォルトはkw:dです。
NOEND
終了タグを必要としないタグ名のリストです。デフォルトは [ "input", "br", "meta", "img", "hr" ] です。
DEFUN_CLASS
コマンドラインオプション'-a defun'を使って関数を定義するときの、 デフォルトのクラス名またはモジュール名です。
DEFUN_FUNCTION
コマンドラインオプション'-a defun'を使って関数を定義するときの、 デフォルトの関数名またはメソッド名です。
CHARSET
文字コードを指定します。出力用言語がjstl11、jstl10のときに使用されます。
EMBED_PATTERN
プレゼンテーションデータ中に式を埋め込むためのパターンを指定します。
INCDIRS
include:」ディレクティブで読み込むファイルを探すディレクトリを指定します。 デフォルトは [ "." ] つまりカレントディレクトリです。