Skip to content
Alex Kit edited this page Mar 29, 2015 · 1 revision

Library supports HTML and Mask syntaxes. Both are parsed to the Mask AST. And you are free to choose which one to use. You can even mix them within one template.

Why do we support two languages?

HTML and Mask are similar but at the same time opposite to each other. HTML is a text-based markup, and Mask is element-based markup. We would encourage you to use Mask for the application structure. And HTML is convenient when you write texts for the application.

3 Interpolations

This is a complex topic to explain. Template rendering involves Data Models and Controllers. Interpolation quotes: (start ~[, end ]). Interpolations are used in TextNodes and inside attribute values.

3.1 Property accessor

~[ACCESSOR]
  • Resolvers
    • Lookup: MODEL → CONTROLLERS SCOPE → PARENT CONTROLLERS SCOPE → ...

       '~[PATH]'
    • Lookup: CURRENT NODES ATTRIBUTES

       '~[$a.PATH]'
    • Lookup: CONTROLLER → PARENT CONTROLLER → ...

       '~[$c.PATH]'
    • Sometimes it is needed to refer current model value. Use single . dot for this.

       var letters = ['A', 'B', 'C'];
       each (letters) {
       	// `each` statement creates new model scope
       	// so here, in the block, model is a string item (A, B, C)
       	'~[.]'
       }
h4 name='~[foo.name]' > 'Lorem ipsum: ~[foo.bar.qux]'

3.2 Expression

~[:EXPRESSION]

Internal engine is used to parse and evaluate expressions. No eval is used - so is much faster and safer. Expressions should start with : (colon)

h4 > '~[: user.name == null ? "uknown" : user.name]'
h4 > '~[: user.name || "uknown" ]'
h4 > 'Fn call example: ~[: foo(bar, "quux", 1) ]'

3.3 Helper

Custom helpers can preprocess expressions or strings

'~[HELPER_NAME: DATA]'

4 Compound statements

Same as in Javascript

if (EXPRESSION) {
	// nodes
}

📙 Read more...

5 Template merging

Powerful feature to combine 2 or more templates. Based on named placeholders, which start with @ symbol. This is like "Templates for a Template". Merging occures before render, and relates only to templates. Data models, controllers are not participate in this Phase. This feature is useful, when you want to encapsulate the template and not to repeat yourself all the time. Examples below show very basic merging template B into template A.

  • Merge nodes

     // A
     .container > @body;
     // B
     @body {
     	'Lorem nodes here'
     }
     // A+B
     .container {
     	'Lorem nodes here'
     }
  • Merge attribute

     // A
     @icon > i.fa.fa-@[attr.name] data-id='@attr.id';
     // B
     @icon name='plus' id='foo';
     // A+B
     i.fa.fa-plus data-id='foo';
  • Wrapp merged template. Use the placeholder keyword to insert current template.

     // A
     @header > h4 > @placeholder;
     @content > article > @placeholder;
     
     // B
     @content { 'Lorem nodes here' }
     // A + B
     article  { 'Lorem nodes here' }

    As template B does not contain @header section, h4 is not in the resulted template.

  • @if: conditional merging. Values for a condition are taken from the template B

     // A	
     @if (condition) {
     	'Lorem nodes here'
     }
  • @each: repeat same placeholders from template B.

     // A
     @each (panel) {
     	.panel name='@attr.name' > .panel-container {
     		h4  > @header;
     		div > @body;
     	}
     }
     // B
     @panel name = foo {
     	@header > 'Foo panel'
     	@body > 'Foo content'
     }
     @panel name = baz {
     	@header > 'Baz panel'
     	@body > 'Baz content'
     }
    
     // A + B
     .panel name='foo' > .panel-container {
     	h4  > 'Foo panel'
     	div > 'Foo content'
     }
     .panel name='baz' > .panel-container {
     	h4  > 'Baz panel'
     	div > 'Baz content'
     }

Small real world example.

Are you tired to repeat yourself all the time with twitters bootstrap buttons?

button.btn.btn-success x-tap='fooSignal' {
	span.glyphicon.glyphicon-plus;
	'Foo Text'
}

Create the component.

define actionBtn {
	button.btn.btn-@[attr.type || 'success'] x-tap='@attr.signal' {
		span.glyphicon.glyphicon-@[attr.icon];
		@placeholder;
	}	
}

And use it everywhere in the project

actionBtn 
	type   = warn 
	signal = editFooBar 
	icon   = pencil >  'Edit the FooBar'

First of all, it is more readable then the raw bootstrap example. And afterwards, we can change the implementation of the actionBtn any time, and add some features, like spinner indicator on click, etc.


🏁