Leszek Gawron wrote:
Daniel Fagerstrom wrote:

macro(<name>,<param-name>,...,<param-name>)
-------------------------------------------

example:

<table do="macro(mytable,list,td-class)">
  <tr do="forEach($list)">
    <td class="${$class}">${item}</td>
  </tr>
</table>

We also need an evalBody as in JXTG. And maybe we should have a possibilty to give a name space to the macro name.

We also need: - some script compiler directives i.e. for cache control (as in JXTG)
Seem reasonable, sugest some mechanism.

- template inclusion so the templates may be defined in a separate file
Absolutely.

Named macros rock! This way we can completely eliminate the need for this hack:
http://cocoon.apache.org/2.1/userdocs/flow/jxtemplate.html#eval


Imagine that user wants to render a fancy table providing only a header rendering macro and a row template:

<tr do="macro(tableHeader,context)">
  <th>Elem1</th>
  <th>Elem2</th>
</tr>

<tr do="macro(singleRow,context)">
  <td>{context.elem1}</td>
  <td>{context.elem2}</td>
</tr>

<table do="macro(mytable,list,headerMacro,rowMacro)">
  <!-- some fancy longish code here -->
  <tr>
    <th>No.</th>
    <th do="eval($headerMacro)"/>
  </tr>
  <tr do="forEach($list)">
    <td>${index}</td>
    <td do="eval($rowMacro,context=.)"/><!-- problem here -->
  </tr>
</table>

Lovely!

Still I see one problem: as every directive is bound to some tag one should be able to eval the macro and strip the root element. In my case the output would look like this:

<tr>
  <th>No.</th>
  <tr>
    <th>Elem1</th>
    <th>Elem2</th>
  </tr>
</tr>

This would fix it: <th do="eval($headerMacro,stripRoot=true)"/>

If we used tags we would be able to introduce <jx:template> as in jxtg that would not show up in the output. Here we have no such possibility.

TAL has an omit-tag(<test>) directive that takes away the surrounding tag if <test> is true, it always keeps the content.


It would solve both cases.

The macro would be:

<tr do="macro(singleRowContent,context);omitTag(true)">
  <td>{context.elem1}</td>
  <td>{context.elem2}</td>
</tr>

One could also have something like:

<th do="xpath(tr/*);eval($headerMacro)"/>

Or some more specialized childs() directive, but I think it starts to get to complicated if we add such things.

Several directives
------------------

So, how do we handle multiple directives for one element? We could handle the TAL example above like:

<p do="let(x=/a/long/path/from/the/root;if(x);content(x/txt);attributes(class=x/class)">


IMO this one is not that clear as the same syntax using tags.

Agree, but most uses will not get this complex but if they will I think tags or using XSLT is better.


This will be also a lot harder to implement as we will have to create much more sophisticated parser. With tags, the xml syntax does 95% of parsing itself with only a little amount of additional coding.

If we keep it as simple as directive(par[=expr],...,par[=expr]);..., it will not be that complicated to parse, and we only need to write the parser once. The complicated thing is to parse the expre, and the expression library take care of that. Don't worry ;)


<snip/>
I am only afraid how I will explain the directive ordering to my developers. Moreover: how many mistakes they will make, which IMO will be much harder to trace comparing to old verbose syntax.
Start by showing examples with single directives, that covers most cases. The show some simple combinations of two directives ;) Honestly, I don't know some larger examples are needed. Maybe it will be clearer with some other composition charachter than ";".

/Daniel

Reply via email to