Kwartz-Ruby Users' Guide

release: $Release$

4   Other Topics

4-1   Restrictions around presentation logic

There are several restrictions in presentation logic file.

  • Position in which comment '/* ... */' is available is limited. In the following example, 'value:' property will be error because string from 'expr;' to the end of comment is regared as argument of 'value:' property.
       /* this comment is ok */
       #foo {
         /* this comment is ok */
         value:  expr;   /* this comment is NG! */
         logic: {        /* this comment will be Ruby syntax error! */
            for item in list    # ruby comment is OK in 'logic:' property
    	  _stag
    	  _cont
    	  _etag
    	end
         }
       }
    
  • '_stag', '_cont', '_etag', '_elem', '_element()', and '_content()' must be placed one in per line, because Kwartz-ruby scans 'logic:' property with regular expression pattern such as '/^\s*_(stag|cont|etag|element|content)(\(.*\))\s*$/' or so.
       #foo {
         logic: {
           # OK
           if x > 0
             _elem
           end
    
           # NG (parse failed)
           _elem if x > 0
         }
       }
    
  • The number of '{' and '}' must be equal in 'logic:' property.
    #foo {
      logic: {
        str = "{"         # this will be parse error 
        _elem
      }
    }
    #bar {
      logic: {
        str = "{"         # add dummy '}' in comment!
        _elem
      }
    }
    
  • '@import "file.plogic"' should be at the beginning of presentation logic file.
       /* OK */
       @import 'file1.plogic';
       
       #foo {
       }
    
       /* NG */
       @import 'file2.plogic';
    

4-2   Restrictions around presentation data

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

  • Cannot omit end tag if id attribute is specified.
    <!-- Kwartz cannot parse the following because </li> is omitted. -->
    <ul>
     <li id="foo">foo
    </ul>
    
    An Element which doesn't have any content is to be written as an empty tag such as <foo id="..."/>.
  • However, <input>, <br>, <meta>, <img>, and <hr> are allowed to omit end tag. And these doesn't have to be written as an empty tag.
    <!-- </input/> is omitted but Kwartz can parse correctly. -->
    <input type="text" name="user" id="user">
    
    Configuration option PROPERTY_NOEND lists these tag names in file 'kwartz/config.rb'. Upper-case and lower-case are distinguished.
  • Attribute values should be surrounded with '"'.
    <!-- Kwartz fails parsing because attribute value is not surrounded with '"'. -->
    <h1 id='id:title' class=title>title</h1>
    

4-3   Makefile and Rakefile

The followings are examples of Makefile, Rakefile, Rantfile, and Rookbook.

example of Makefile
.SUFFIXES:  .rhtml .html .plogic

ALL    = file1.rhtml file2.rhtml file3.rhtml
LAYOUT = layout.html

default:  $(ALL)

%.rhtml:  %.html %.plogic
	kwartz -l eruby -p $*.plogic $*.html > $@

file3.rhtml: file3.html file3.plogic $(LAYOUT)
	kwartz -p file3.plogic -L $(LAYOUT) file3.html > file3.rhtml
example of Rakefile for Rake
all    = ["file1.rhtml", "file2.rhtml", "file3.rhtml"]
layout = 'layout.html'

task :default => all

rule '.rhtml' => ['.html', '.plogic']           do |t|
  pdata, plogic = t.sources
  sh "kwartz -l eruby -p #{plogic} #{pdata} > #{t.name}"
end

file 'file3.rhtml' => ["file3.html", "file3.plogic", layout] do |t|
  pdata, plogic, layout = t.prerequisites
  sh "kwartz -p #{plogic} -L #{layout} #{pdata} > #{t.name}"
end
example of Rantfile for Rant
all    = ["file1.rhtml", "file2.rhtml", "file3.rhtml"]
layout = 'layout.html'

task :default => all

gen Rule, ".rhtml" => [".html", ".plogic"] do |t|
  pdata, plogic = t.prerequisites
  sys "kwartz -p #{plogic} #{pdata} > #{t.name}"
end

file "file3.rhtml" => ["file3.html", "file3.plogic", layout] do |t|
  pdata, plogic, layout = t.prerequisites
  sys "kwartz -p #{plogic} -L #{layout} #{pdata} > #{t.name}"
end
example of Kookbook.yaml for Kook
properties:
  - layout  :  layout.html

parameters:
  - all     :  [ file1.rhtml, file2.rhtml, file3.rhtml ]
  - rook_product:  $(all)

recipes:

  - product:	*.rhtml
    ingreds:	[ $(1).html, $(1).plogic ]
    method*: |
        $pdata = $ingreds[0]; $plogic = $ingreds[1];
	k_sys("kwartz -p $plogic} $pdata > $product");

  - product:	file3.rhtml
    ingres:	[ file3.html, file3.plogic, $(layout) ]
    method*: |
	$pdata = $ingreds[0]; $plogic = $ingreds[1]
	k_sys("kwartz -p $plogic -L $(layout) $pdata > $product"
example of Rookbook.yaml for Rook
properties:
  - layout  :  layout.html

parameters:
  - all     :  [ file1.rhtml, file2.rhtml, file3.rhtml ]
  - rook_product:  $(all)

recipes:

  - product:	*.rhtml
    ingreds:	[ $(1).html, $(1).plogic ]
    method*: |
        pdata, plogic = @ingreds
	sys "kwartz -p #{plogic} #{pdata} > #{@product}"

  - product:	file3.rhtml
    ingres:	[ file3.html, file3.plogic, $(layout) ]
    method*: |
        pdata, plogic, layout = @ingreds
	sys "kwartz -p #{plogic} -L $(layout) #{pdata} > #{@product}"

4-4   Use Kwartz as Library

If you want to use Kwartz library in your Ruby script, use Kwartz::Main class.

usage of Kwartz::Main class
require 'kwartz'
require 'kwartz/main'
argv = %w[-p hello.plogic -L layout.html hello.html]
main = Kwartz::Main.new(argv)
output = main.execute()
File.open('hello.rhtml', 'w') { |f| f.write(output) }

4-5   Use Kwartz with Non-Supported Language

Using Erubis, it is able to use Kwartz with Java, JavaScript, Scheme, and so on. Erubis is an implementation of eRuby which supports not only Ruby but also other languages.

The followings are examples of using JavaScript with Kwartz and Erubis.

presentation data (js-example.html)
<table>
  <tr class="odd" id="mark:list">
    <td>@{item}@</td>
  </tr>
  <tr class="even" id="dummy:d1">
    <td>foo</td>
  </tr>
</table>
presentation logic (js-example.plogic)
#list {
  attrs:  'class' klass;
  logic: {
    for (var i=0, len=list.length; i < len; i++) {
      klass = i % 1 == 0 ? 'even' : 'odd';
      item = list[i];
      _elem;
    }
  }
}
compile
$ kwartz -l erubis -p js-example.plogic js-example.html  > js-example.jshtml
output script (js-example.jshtml)
<table>
<%     for (var i=0, len=list.length; i < len; i++) { %>
<%       klass = i % 1 == 0 ? 'even' : 'odd'; %>
<%       item = list[i]; %>
  <tr class="<%= klass %>">
    <td><%== item %></td>
  </tr>
<%     } %>
</table>

In Erubis, <%= ... %> means embedded expression and <%== ... %> means embedded expression with escaping. In this example, @{item}@ is compiled into <%== item %> because it needs escaping and attr: 'class' klass is compiled into <%= klass %> without escaping.

The following is an example to compile into JavaScript code with Erubis.

convert into JavaScript code with erubis
$ erubis -l javascript -x js-example.jshtml
var _buf = []; _buf.push("<table>\n");
     for (var i=0, len=list.length; i < len; i++) { 
       klass = i % 1 == 0 ? 'even' : 'odd'; 
       item = list[i]; 
_buf.push("  <tr class=\""); _buf.push(klass); _buf.push("\">\n\
    <td>"); _buf.push(escape(item)); _buf.push("</td>\n\
  </tr>\n");
     } 
_buf.push("</table>\n");
document.write(_buf.join(""));