Helma Logo
main list history

Version 50 by hannes on 17. March 2007, 16:17

Version 49 by hannes on 31. October 2006, 10:03

3# Macros in skins are delimited by <% %>&lt;% %&gt;.
65I removed the old examples since they didn't match the renewed spec anymore. Generally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use <% %> &lt;% %&gt; as macro delimiters.

Version 48 by hannes on 31. October 2006, 09:58

59== Todo ==
61What probably remains to be done is add smarts to the parsing of parenthesised expressions such as "(foo in bar)" or "(x < y)". Currently, these are simply parsed to a separate list/array. We might use a special purpose class for this that gives some support in determining what kind of expression we're dealing with.
62
64I removed the old examples since they didn't match the renewed spec anymore. Generally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use &lt;% %&gt; <% %> as macro delimiters.

Version 47 by hannes on 30. October 2006, 23:24

62I removed the old examples since they didn't match the renewed spec anymore. Generally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use <% %> &lt;% %&gt; as macro delimiters.

Version 46 by hannes on 30. October 2006, 23:20

41Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/file/helma/trunk/src/org/helma/template/TemplateScanner.java*, which can be conveniently accessed using the global parseSkinResource(path) function<b>parseSkin(str)</b> and <b>parseSkinResource(path)</b> functions. It parses skins to a java.util.List filled with Strings for the static parts and Macro tags, which are again java.util.List objects with a special param property that contains the tag's named parameters.

Version 45 by hannes on 30. October 2006, 23:16

3# Macros in skins are delimited by &lt;% %&gt;<% %>.
27  [image , [img, dancer.gif]{dim: {width: gif]{dim={width=30.0, height: 120}}]height=120.0}}]

Version 44 by hannes on 30. October 2006, 23:11

3# Macros in skins are delimited by <% %>&lt;% %&gt;.

Version 43 by hannes on 30. October 2006, 23:09

23  image <% img dancer.gif alt="dancer" dim={width: 30, height: 120} %>
27  [image , [img, dancer.gif]{alt: dancer, dim: gif]{dim: {width: 30, height: 120}}]
36  skin[1].params.alt == "dancer";

Version 42 by hannes on 30. October 2006, 23:02

31  skin.length == 2;

Version 41 by hannes on 30. October 2006, 23:00

19Macro parameters Parsed skins are passed in exposed as JavaScript arrays, with the static skin parts represented by string elements, while the macro parts are represented by a way that allows sequential access for unnamed parameters and keyed access for MacroTag class. The MacroTag class is itself a JavaScript array, with an additional params property to expose the named parameters:parameters.
21    var param = Consider for example the following skin source:
22      next: function() {
23          /\* provide iterator style access to unnamed parameters */
24      },     
25      byName: {
26          /\* provide access to named parameters */
27      }
28    }
23  image <% img dancer.gif alt="dancer" dim={width: 30, height: 120} %>
24
25It is parsed to the following construct:
26
27  [image , [img, dancer.gif]{alt: dancer, dim: {width: 30, height: 120}}]
28
29and the following conditions would evaluate to true:
30
31  skin[0] == "image ";
32  skin[1].length == 2;
33  skin[1][0] == "img";
34  skin[1][1] == "dancer.gif";
35  skin[1].params.alt == "dancer";
36  skin[1].params.dim.width == 30;
37  skin[1].params.dim.height == 120;
38
26Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/file/helma/trunk/src/org/helma/template/TemplateScanner.java*, which can be conveniently accessed using the global parseSkinResource(path) function.  It parses skins to a java.util.List filled with Strings for the static parts and Macro tags, which are again java.util.List objects with a special param property that contains the tag's named parameters. All this is wrapped in *ScriptableLists|helma 2 core reference/scriptableList* and *ScriptableMaps|helma 2 core reference/scriptablemap* so you can sweep through it like it were native JavaScript arrays and objects.
27
28All this is wrapped in *ScriptableLists|helma 2 core reference/scriptableList* and *ScriptableMaps|helma 2 core reference/scriptablemap* so you can sweep through it like it were native JavaScript arrays and objects.

Version 40 by hannes on 30. October 2006, 22:48

45    t.render({topics: ["Berge", "TälerTaeler", "Seen", "FlüsseFluesse"]});

Version 39 by hannes on 30. October 2006, 22:46

32Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/file/helma/trunk/src/org/helma/template/TemplateScanner.java*, which can be conveniently accessed using the global parseSkinResource(path) function.  It parses skins to a java.util.List filled with Strings for the static parts and Macro tags, which are again java.util.List objects with a special param property that contains the tag's named parameters. All this is wrapped in *helma *ScriptableLists|helma 2 core reference/scriptableLists* reference/scriptableList* and *helma *ScriptableMaps|helma 2 core reference/scriptablemaps* reference/scriptablemap* so you can sweep through it like it were native JavaScript arrays and objects.

Version 38 by hannes on 30. October 2006, 22:45

32Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/file/helma/trunk/src/org/helma/template/TemplateScanner.java*, which can be conveniently accessed using the global parseSkinResource(path) function. You It parses skins to a java.util.List filled with Strings for the static parts and Macro tags, which are again java.util.List objects with a special param property that contains the tag's named parameters. All this is wrapped in *helma 2 core reference/scriptableLists* and *helma 2 core reference/scriptablemaps* so you can currently test sweep through it using something like:like it were native JavaScript arrays and objects.
34I started a simple JavaScript renderer for skins parsed this way.   var t = new PackagesIt currently implements very simplistic if/foreach constructs.
35    t.parse("foo <% image 'dancer.gif' {class: 'storyImage'} %> bar");
36<% this.attachments %>
37
38The following code shows how to use this:
39
40  mountRepository("jslib");
41  include("jslib/template/Templatex.js");
42  
43  function handle_get() {
44    var t = new Templatex("skins/main.skin");
45    t.render({topics: ["Berge", "Täler", "Seen", "Flüsse"]});
46  }
47

Version 37 by hannes on 30. October 2006, 22:23

3# Macros in skins are delimited by &lt;% %&gt;<% %>.
32Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/helma/trunk/src/org/helma/template/TemplateScannerTemplateScanner|Source/file/helma/trunk/src/org/helma/template/TemplateScanner.java*. You can currently test it using something like:
39I removed the old examples since they didn't match the renewed spec anymore. Generally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use &lt;% %&gt; <% %> as macro delimiters.

Version 36 by hannes on 13. July 2006, 02:48

35    t.parse("foo <% image 'dancer.gif gif' {class: 'storyImage'} %> bar");

Version 35 by hannes on 13. July 2006, 02:47

36  

Version 34 by hannes on 13. July 2006, 02:47

30== Implementation ==
31
32Native template scanning support is implemented in class *org.helma.template.TemplateScanner|Source/helma/trunk/src/org/helma/template/TemplateScanner.java*. You can currently test it using something like:
33
34    var t = new Packages.org.helma.template.TemplateScanner();
35    t.parse("foo <% image dancer.gif {class: 'storyImage'} %> bar");
36  

Version 33 by hannes on 13. July 2006, 02:39

13# Round brackets ( ) can be used to group multiple macro parametersparameters into one. (syntactic sugar for arrays?)

Version 32 by hannes on 13. July 2006, 02:38

32I removed the old examples since they didn't match the renewed spec anymore. Generally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use &lt;% %&gt %&gt; as macro delimiters.

Version 31 by hannes on 13. July 2006, 02:38

15# Helma provides native skin scanning/parsing features, but skins and macros are implemented in JavaScript.

Version 30 by hannes on 13. July 2006, 01:12

13# Round brackets ( ) can be used to group macro parameters. (syntactic sugar for arrays?)
17# Todo: provide a feature for marking subtemplates within a skin file.

Version 29 by hannes on 13. July 2006, 01:10

17# Standard macros such as if/else, foreach, equals, greaterThan are implemented as plain macros in JS.
19Macro parameters are passed in a way that allows sequential value lookup, sequential name lookup access for unnamed parameters and keyed access for named lookup:parameters:
24      },       
25      

Version 28 by hannes on 13. July 2006, 01:06

23          /* /\* provide iterator style access to unnamed parameters */
25      
27          /* /\* provide access to named parameters */
37====I removed Jürg's comments as well, Juerg Lehnifor the same reason.
38
39I find this proposal somehow unclear and not so straight forward, but maybe I'm just missunderstanding it. Here are some remarks:
40
41<div class="reply">Replies in red by hannes. BTW, the css class for red indented text is "reply".</div>
42
43* You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case. <div class="reply">I would think in these cases that these are just plain properties. I think direct property access will be enhanced in Helma 2 from what is possible in Helma 1. But strictly speaking, this is not part of this proposal, which is about template/skin syntax.</div>
44* "Macro parameter values wrapped in ( ) are interpreted as nested macros": Again: I assume you're talking about parameters such as comment.title. But what if I'd want to call encode with a constant string as parameter? <div class="reply">For a constant string, you'd just write it as-is, or wrapped in quotes (see point 4 in the spec)</div>
45* Macros / Nested Skins: I understand that you want to try to avoid the mixing code / content scenario, but i somehow find the current proposal even more confusing than the previously discussed nesting of "code" and content blocks. The problem is that there are two kinds of open / close "tags" now ( "(%", "{{" ), and it seems to become rather hard to keep the overview. <div class="reply">I think this is the better approach. Most template engines just have tags to mark the beginning and ending of code sections, but they have no way of marking embedded skins and code. Having real embedded skins and macros is much preferable to me.</div>
46* If foreach is implemented as a JavaScript macro, how could this notation be possible: (% foreach comment in (story.comments)?<div class="reply"><tt>foreach</tt> is the macro name, <tt>comment</tt> and <tt>in</tt> are both constant unnamed string parameters, <tt>story.comments</tt> is a embedded macro.</div>
47* Likewise, how is it possible to have two macros with each a nested skin inside one macro block, and the macros' execution depending on each other. That would be the case with a construct like (% if {{ }} else {{ }}  %)<div class="reply"><tt>if</tt> is the macro name, the first and third parameters are nested skins, the second parameter is constant string "else".</div>
48* prefix / suffix: While it's nice to have this in the foreach example because it removes the need for checking for hasComments, I think it just increases complexity and makes the result harder to read.<div class="reply">I think it does in some cases, but it makes things simpler in others. I do think it's a good thing to keep, not just because it's part of Helma's heritage.</div>
49
50<div class="reply">Reply by Juerg:
51
52I now understand your porposal properly. It's a nice idea to use unnamed parameters and subskins as equal parts in order to create a pseudo-code like syntax.
53But there are still some akward things as well:
54* "foreach comment in (story.comments)": The placement of the parantheses looks weird. It makes technically sense, but it gives me a slightly hackish impression...
55* the nesting of macros, subskins, and macros within the subskins is complicated. I think it will tend to be hard to read, especially without a highlighting editor for this template format.
56* The double curly-braces give the feeling of some kind of code-block following. And in other template engines it is used just for the opposite, to print out a value (e.g. in django. The page about templates is worth a look: *http://www.djangoproject.com/documentation/templates/*).
57
58PS: Are there some guidelines about how to react to posts on this Wiki? I find the loose adding of replies and replies to replies a bit confusing. Maybe it should have a comment function like on blog websites?
59</div>
60

Version 27 by hannes on 13. July 2006, 01:03

19== Notes ==
20
21* My original intention was to use * instead of % for top level macro delimiters, but Gobi would interpret these as Wiki links. Anyway, I haven't committed myself to any choice of delimiter sequences, I just think my current proposal looks pretty sane and implementable to me. I do think this is an essential question.
22* Even though it doesn't look that way, this proposal provides easy backwards compatibility with old style model domain macro syntax and conventions. I'll show how when I talk further about JS implementation.
23
23      values: [], next: function()
24      names: [],   /* provide iterator style access to unnamed parameters */
25      byName: {}},
26
27      byName: {
28          /* provide access to named parameters */
29      }
28====I removed the old examples since they didn't match the renewed spec anymore. Simple login info/formGenerally speaking, all kinds of macro syntax can be implemented based on the features discribed in this proposals, as long as they use &lt;% %&gt as macro delimiters.
29
30 (%
31  if (user) {{
32    <div>Logged in as (% user.name %)</div>
33  }} else {{
34    <form action="(% loginUrl %)">
35    <table><tr>
36      <td>Name</td><td><input name="name"></td>
37    </tr><tr>
38      <td>Password</td><td><input type="password" name="password"></td>
39    </tr></table>
40    </form>
41  }}
42 %)
43
44==== Story with comments
45
46Variant 1, using multiple skin/macro nesting:
47
48 <h1>(% story.title %)</h1>
49 <div>(% story.text %)</div>
50 (%
51  if (story.hasComments) {{
52  <table>
53  (% foreach comment in (story.comments)
54    {{
55    <tr>
56      <td>(% encode(comment.title) %)</td>
57      <td>(% encode(comment.text) %)</td>
58    </tr>
59    }}
60  %)
61  </table>
62  }}
63 %)
64
65Variant 2, using prefix and suffix parameters to avoid nesting:
66
67 <h1>(% story.title %)</h1>
68 <div>(% story.text %)</div>
69 (%
70  foreach comment in (story.comments)
71  {{
72    <tr>
73      <td>(% encode(comment.title) %)</td>
74      <td>(% encode(comment.text) %)</td>
75    </tr>
76  }}
77  prefix=<table> suffix=</table>
78 %)

Version 26 by hannes on 13. July 2006, 00:55

6# For string parameter values, single or double quotes The following types are optional unless the value contains whitespace characters.supported as parameter values:
7# Macro parameter values wrapped in ( ) are interpreted as nested macros.## strings: "foo"
8## numbers: 13
9## boolean false|true
10## object literals: {foo: bar, x: y}
11## array literals: [1, 2, "drei"]
12# For string values, single or double quotes are optional unless the value contains whitespace characters.
13# Round brackets ( ) can be used to group macro parameters.

Version 25 by hannes on 13. July 2006, 00:51

3# Macros in skins are delimited by (% %)&lt;% %&gt;.
8# Macro <strike>Macro parameter values wrappedn in {{ }} are interpreted as nested skins.</strike>
9# Skins Helma provides scanning/parsing features, but skins and macros are both implemented as plain JS objectsin JavaScript.
10# Nested <strike>Nested skins and macros are passed to macros as skin and macro objects, respectively. In other words, macro evaluation and skin rendering is up to the containing macro.</strike>

Version 24 by Lehni on 04. January 2006, 04:45

102
103PS: Are there some guidelines about how to react to posts on this Wiki? I find the loose adding of replies and replies to replies a bit confusing. Maybe it should have a comment function like on blog websites?

Version 23 by Lehni on 04. January 2006, 04:43

96
99* "foreach comment in (story.comments): comments)": The placement of the parantheses looks weird. It makes technically sense, but it gives me a slightly hackish impression...
101* The double curly-braces give the feeling of some kind of code-block following. And in other template engines it is used just for the opposite, to print out a value (e.g. in django. The page about templates is worth a look: http://www*http://www.djangoproject.com/documentation/templates/ )com/documentation/templates/*).

Version 22 by Lehni on 04. January 2006, 04:42

95<div class="reply">Reply by Juerg:
96I now understand your porposal properly. It's a nice idea to use unnamed parameters and subskins as equal parts in order to create a pseudo-code like syntax.
97But there are still some akward things as well:
98* foreach comment in (story.comments): The placement of the parantheses looks weird. It makes technically sense, but it gives me a slightly hackish impression...
99* the nesting of macros, subskins, and macros within the subskins is complicated. I think it will tend to be hard to read, especially without a highlighting editor for this template format.
100* The double curly-braces give the feeling of some kind of code-block following. And in other template engines it is used just for the opposite, to print out a value (e.g. in django. The page about templates is worth a look: http://www.djangoproject.com/documentation/templates/ ).
101</div>
102

Version 21 by hannes on 20. December 2005, 11:03

86* You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case. <div class="reply">I would think >Replies in these cases that these are just plain propertiesred by hannes. I think direct property access will be enhanced in Helma 2 from what is possible in Helma 1. But strictly speakingBTW, this the css class for red indented text is not part of this proposal, which is about template/skin syntax"reply". -hns</div></div>
87
88* You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case. <div class="reply">I would think in these cases that these are just plain properties. I think direct property access will be enhanced in Helma 2 from what is possible in Helma 1. But strictly speaking, this is not part of this proposal, which is about template/skin syntax.</div>

Version 20 by hannes on 19. December 2005, 13:37

89* If foreach is implemented as a JavaScript macro, how could this notation be possible: (% foreach comment in (story.comments)?<div class="reply"><tt>foreach</tt> is the macro name, <tt>comment</tt> and <tt>in</tt> ar are both constant unnamed string parameters, <tt>story.comments</tt> is a embedded macro.</div>

Version 19 by hannes on 19. December 2005, 12:20

3* # Macros in skins are delimited by (% %).
4* # Macros can contain both named and unnamed parameters, in any combination (see Notes for implementation details).
5* # Named parameters are denoted as name=value, unnamed parameters are denoted as value.
6* # For string parameter values, single or double quotes are optional unless the value contains whitespace characters.
7* # Macro parameter values wrapped in ( ) are interpreted as nested macros.
8* # Macro parameter values wrappedn in {{ }} are interpreted as nested skins.
9* # Skins and macros are both implemented as plain JS objects.
10* # Nested skins and macros are passed to macros as skin and macro objects, respectively. In other words, macro evaluation and skin rendering is up to the containing macro.
11* # Standard macros such as if/else, foreach, equals, greaterThan are implemented as plain macros in JS.
78* You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case. <div class="reply">I would think in these cases that these are just plain properties. I think direct property access will be enhanced in Helma 2 from what is possible in Helma 1. But strictly speaking, this is not part of this proposal, which is about template/skin syntax.</div> -hns</div>
79* "Macro parameter values wrapped in ( ) are interpreted as nested macros": Again: I assume you're talking about parameters such as comment.title. But what if I'd want to call encode with a constant string as parameter?parameter? <div class="reply">For a constant string, you'd just write it as-is, or wrapped in quotes (see point 4 in the spec)</div>
80* Macros / Nested Skins: I understand that you want to try to avoid the mixing code / content scenario, but i somehow find the current proposal even more confusing than the previously discussed nesting of "code" and content blocks. The problem is that there are two kinds of open / close "tags" now ( "(%", "{{" ), and it seems to become rather hard to keep the overview. <div class="reply">I think this is the better approach. Most template engines just have tags to mark the beginning and ending of code sections, but they have no way of marking embedded skins and code. Having real embedded skins and macros is much preferable to me.</div>
81* If foreach is implemented as a JavaScript macro, how could this notation be possible: (% foreach comment in (story.comments)?comments)?<div class="reply"><tt>foreach</tt> is the macro name, <tt>comment</tt> and <tt>in</tt> ar both constant unnamed string parameters, <tt>story.comments</tt> is a embedded macro.</div>
82* Likewise, how is it possible to have two macros with each a nested skin inside one macro block, and the macros' execution depending on each other. That would be the case with a construct like (% if {{ }} else {{ }}  %)%)<div class="reply"><tt>if</tt> is the macro name, the first and third parameters are nested skins, the second parameter is constant string "else".</div>
83* prefix / suffix: While it's nice to have this in the foreach example because it removes the need for checking for hasComments, I think it just increases complexity and makes the result harder to read.<div class="reply">I think it does in some cases, but it makes things simpler in others. I do think it's a good thing to keep, not just because it's part of Helma's heritage.</div>

Version 18 by hannes on 19. December 2005, 12:07

86* You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case. <div class="reply">I would think in these cases that these are just plain properties. I think direct property access will be enhanced in Helma 2 from what is possible in Helma 1. But strictly speaking, this is not part of this proposal, which is about template/skin syntax.</div>

Version 17 by Lehni on 17. December 2005, 07:10

80== Comments ==
82== Juerg Lehni == Juerg Lehni

Version 16 by Lehni on 17. December 2005, 07:10

80==== Comments ====Comments
82== Juerg LehniLehni ==
86- * You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case.
87- * "Macro parameter values wrapped in ( ) are interpreted as nested macros": Again: I assume you're talking about parameters such as comment.title. But what if I'd want to call encode with a constant string as parameter?
88- * Macros / Nested Skins: I understand that you want to try to avoid the mixing code / content scenario, but i somehow find the current proposal even more confusing than the previously discussed nesting of "code" and content blocks. The problem is that there are two kinds of open / close "tags" now ( "(%", "{{" ), and it seems to become rather hard to keep the overview.
89- * If foreach is implemented as a JavaScript macro, how could this notation be possible: (% foreach comment in (story.comments)?
90- * Likewise, how is it possible to have two macros with each a nested skin inside one macro block, and the macros' execution depending on each other. That would be the case with a construct like (% if {{ }} else {{ }}  %)
91- * prefix / suffix: While it's nice to have this in the foreach example because it removes the need for checking for hasComments, I think it just increases complexity and makes the result harder to read.

Version 15 by Lehni on 17. December 2005, 07:09

79
80==== Comments ====
81
82== Juerg Lehni
83
84I find this proposal somehow unclear and not so straight forward, but maybe I'm just missunderstanding it. Here are some remarks:
85
86- You are using commment.title, comment.text, user.name in your examples, and I'm not sure if these are simply properties of these objects or if they're actually defined as macros. I would assume the second is the case.
87- "Macro parameter values wrapped in ( ) are interpreted as nested macros": Again: I assume you're talking about parameters such as comment.title. But what if I'd want to call encode with a constant string as parameter?
88- Macros / Nested Skins: I understand that you want to try to avoid the mixing code / content scenario, but i somehow find the current proposal even more confusing than the previously discussed nesting of "code" and content blocks. The problem is that there are two kinds of open / close "tags" now ( "(%", "{{" ), and it seems to become rather hard to keep the overview.
89- If foreach is implemented as a JavaScript macro, how could this notation be possible: (% foreach comment in (story.comments)?
90- Likewise, how is it possible to have two macros with each a nested skin inside one macro block, and the macros' execution depending on each other. That would be the case with a construct like (% if {{ }} else {{ }}  %)
91- prefix / suffix: While it's nice to have this in the foreach example because it removes the need for checking for hasComments, I think it just increases complexity and makes the result harder to read.
92

Version 14 by hannes on 09. December 2005, 14:55

37    </tr><tr>

Version 13 by hannes on 09. December 2005, 13:53

43Same thing implemented with prefix, suffix and default params:
44
45 (% user.name prefix="<div>Logged in as " suffix="</div>"
46    default={{
47      <form action="(% loginUrl %)">
48      <table><tr>
49        <td>Name</td><td><input name="name"></td>
50        <td>Password</td><td><input type="password" name="password"></td>
51      </tr></table>
52      </form>
53    }}
54  %)
55

Version 12 by hannes on 09. December 2005, 13:52

43Same thing implemented with prefix, suffix and default params:
44
45 (% user.name prefix="<div>Logged in as " suffix="</div>"
46    default={{
47      <form action="(% loginUrl %)">
48      <table><tr>
49        <td>Name</td><td><input name="name"></td>
50        <td>Password</td><td><input type="password" name="password"></td>
51      </tr></table>
52      </form>
53    }}
54  %)
55

Version 11 by anonymous user on 09. December 2005, 13:32

1== Spec ==
13== Notes ==
26== Examples ==
28==== Simple login info/form
29
42==== Story with comments
44Variant 1, using multiple skin/macro nesting:
45
62Variant 2, using prefix and suffix parameters to avoid nesting:
63
64 <h1>(% story.title %)</h1>
65 <div>(% story.text %)</div>
66 (%
67  foreach comment in (story.comments)
68  {{
69    <tr>
70      <td>(% encode(comment.title) %)</td>
71      <td>(% encode(comment.text) %)</td>
72    </tr>
73  }}
74  prefix=<table> suffix=</table>
75 %)

Version 10 by hannes on 09. December 2005, 13:08

20    var params param =

Version 9 by hannes on 09. December 2005, 12:23

7* Macro parameters parameter values wrapped in ( ) are interpreted as nested macros.
8* Macro parameters parameter values wrappedn in {{ }} are interpreted as nested skins.

Version 8 by hannes on 09. December 2005, 12:20

4* Macros can contain both named and unnamed parameters, in any combinationcombination (see Notes for implementation details).
10* Macro parameters are passed in a way that allows sequential value lookup, sequential name lookup and named lookup:
11    var params = {
12      values: [],
13      names: [],
14      byName: {}
15    }
18
19Macro parameters are passed in a way that allows sequential value lookup, sequential name lookup and named lookup:
20
21    var params = {
22      values: [],
23      names: [],
24      byName: {}
25    }

Version 7 by hannes on 09. December 2005, 12:18

3* Macros in skins are marked as delimited by (% %).
21* Even though it doesnMy original intention was to use * instead of % for top level macro delimiters, but Gobi would interpret these as Wiki links. Anyway, I haven't look that waycommitted myself to any choice of delimiter sequences, this I just think my current proposal provides easy backwards compatibility with old style model domain macro syntax looks pretty sane and conventionsimplementable to me. I do think this is an essential question.
22* Even though it doesn't look that way, this proposal provides easy backwards compatibility with old style model domain macro syntax and conventions. I'll show how when I talk further about JS implementation.

Version 6 by hannes on 09. December 2005, 12:14

19==== Notes
20
21* Even though it doesn't look that way, this proposal provides easy backwards compatibility with old style model domain macro syntax and conventions.
22

Version 5 by hannes on 09. December 2005, 12:10

3* Macros in skins are marked as (* *)(% %).
21 (*(%
23    <div>Logged in as (** (% user.name *)</div>%)</div>
25    <form action="(* (% loginUrl *)%)"
32 *)%)
35 <h1>(* <h1>(% story.title *)</h1>%)</h1>
36 <div>(* <div>(% story.text *)</div>%)</div>
37 (*(%
38   (* (% foreach comment in (story.comments)
41      <td>(* <td>(% encode(comment.title) *)</td>%)</td>
42      <td>(* <td>(% encode(comment.text) *)</td>%)</td>
44   *)%)
47 *)%)

Version 4 by hannes on 09. December 2005, 12:02

23    <div>Logged in as (* (** user.name *)</div>

Version 3 by hannes on 09. December 2005, 12:02

3* Macros in skins are marked as (&42; &42;)(* *).
21 (&42;(*
23    <div>Logged in as (&42; (* user.name &42;)</div>*)</div>
25    <form action="(&42; (* loginUrl &42;)*)"
32 &42;)*)
35 <h1>(&42; <h1>(* story.title &42;)</h1>*)</h1>
36 <div>(&42; <div>(* story.text &42;)</div>*)</div>
37 (&42;(*
38   (&42; (* foreach comment in (story.comments)
41      <td>(&42; <td>(* encode(comment.title) &42;)</td>*)</td>
42      <td>(&42; <td>(* encode(comment.text) &42;)</td>*)</td>
44   &42;)*)
47 &42;)*)

Version 2 by hannes on 09. December 2005, 12:01

3* Macros in skins are marked as (* *)(&42; &42;).
21 (*(&42;
23    <div>Logged in as (* (&42; user.name *)</div>&42;)</div>
25    <form action="(* (&42; loginUrl *)&42;)"
32 *)&42;)
35 <h1>(* <h1>(&42; story.title *)</h1>&42;)</h1>
36 <div>(* <div>(&42; story.text *)</div>&42;)</div>
37 (*(&42;
38   (* (&42; foreach comment in (story.comments)
41      <td>(* <td>(&42; encode(comment.title) *)</td>&42;)</td>
42      <td>(* <td>(&42; encode(comment.text) *)</td>&42;)</td>
44   *)&42;)
47 *)&42;)

Version 1 by hannes on 09. December 2005, 11:57

1==== Spec
2
3* Macros in skins are marked as (* *).
4* Macros can contain both named and unnamed parameters, in any combination.
5* Named parameters are denoted as name=value, unnamed parameters are denoted as value.
6* For string parameter values, single or double quotes are optional unless the value contains whitespace characters.
7* Macro parameters wrapped in ( ) are interpreted as nested macros.
8* Macro parameters wrappedn in {{ }} are interpreted as nested skins.
9* Skins and macros are both implemented as plain JS objects.
10* Macro parameters are passed in a way that allows sequential value lookup, sequential name lookup and named lookup:
11    var params = {
12      values: [],
13      names: [],
14      byName: {}
15    }
16* Nested skins and macros are passed to macros as skin and macro objects, respectively. In other words, macro evaluation and skin rendering is up to the containing macro.
17* Standard macros such as if/else, foreach, equals, greaterThan are implemented as plain macros in JS.
18
19==== Examples
20
21 (*
22  if (user) {{
23    <div>Logged in as (* user.name *)</div>
24  }} else {{
25    <form action="(* loginUrl *)">
26    <table><tr>
27      <td>Name</td><td><input name="name"></td>
28      <td>Password</td><td><input type="password" name="password"></td>
29    </tr></table>
30    </form>
31  }}
32 *)
33
34
35 <h1>(* story.title *)</h1>
36 <div>(* story.text *)</div>
37 (*
38  if (story.hasComments) {{
39  <table>
40  (* foreach comment in (story.comments)
41    {{
42    <tr>
43      <td>(* encode(comment.title) *)</td>
44      <td>(* encode(comment.text) *)</td>
45    </tr>
46    }}
47  *)
48  </table>
49  }}
50 *)