This would be tremendously helpful in particular to build a library of widgets and reuse them in templates. A basic example would be something like this (syntax to be refined):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- Define a base template. -->
<a ws-template="Button" ws-attr="Attr">${Text}</a>

<!-- Use the above template within another template. -->
<div ws-template="Page">
  <ws-Button>
    <Attr id="button-in-page" ws-onclick="BtnClick" />
    <Text>Click me!</Text>
  </ws-Button>
</div>

<!-- Resulting HTML: -->
<div>
  <a id="button-in-page" onclick="F# code filled as BtnClick">Click me!</a>
</div>

Here Page fills all of Button's holes, and notably it fills Attr using holes of its own; in the end the Page template has one hole, BtnClick. If Page left any of Button's holes unfilled, then it would "inherit" them.

This is a big feature with some intricacies that need to be addressed: What's the syntax to invoke a template? Ideas: <TemplateName>: looks nice, but ambiguous if TemplateName is a valid HTML element name. <.TemplateName> looks weird but would have the advantage of consistency when we introduce templates that can reference across files (ticket to come) which would then be written as <FileName.TemplateName>. <ws-TemplateName> (like in the example above) looks consistent with the rest of the DSL. Cross-file could be written as <ws-FileName.TemplateName>. I think this is the best solution. What's the syntax to fill the various types of holes that we have? ${X}: attribute X="value"? child element <X>value</X> (like in the example above)? I think we can allow both. ws-hole="X" or ws-replace="X": child element named <X>content...</X>, whose children are the content. Do we also want a syntax to provide an element that is itself the content, something like <X-div>...</X-div> maybe? ws-attr="X": child element <X attrs... /> with attributes on it. ws-onfoo="X": the only thing I can think of is using an attribute X="Y" to define that this can be filled by a hole named Y in the containing template; and if it's not there, then the containing template has a hole named X. ws-var="X": same as onfoo="X".

  • loic.denuziere

    After discussing with Andras, we think it will be more consistent with these changes:

    • ${X} text holes: only filled by a child element <X>value</X>, not by an attribute.
    • Unfilled holes are not inherited.
    • All types of holes can be "mapped" into holes for the containing template as described for ws-onfoo.

    This gives a much more consistent scheme:

    • Attributes on the <ws-...> element always define hole mappings.
    • Child elements always define hole fillings.
    • A hole that is neither mapped nor filled is simply ignored.