Installation

Installion of curls is very simple:

npm install @jlpenny/curls

Then in order to use it in your module, simply use:

var Transpiler = require('@jlpenny/curls');

Transpiling is done by running a transpiler function, which returns a Javascript function to which you can pass variables.

Transpiler.transpiler('Hello {{world}}')({world: 'dlrow'};);

Language features

Variables

Variables are returned simply by enclosing them in the curly brackets:

{{varname}}

Functions

You can run functions, simply space-separate your arguments:

{{func arg1 arg2}}

What about running a function in a function? No problem, simply enclose all nested expressions with parenthesis:

{{func1 (func2 arg1) arg2}}

You can even pass objects like this:

{{func (key=value key2=value)}}

Block expressions

You can iterate through an array:

{{#each array}}
    {{this.key}}
{{/each}}
{{#each array as el}}
    {{el.key}}
{{/each}}

You can iterate through an array and extract its object properties:

{{#with array}}
    {{key}}
{{/with}}

You can do an if statement too!

{{#if var > 5}}
    Var is greater than 5
{{/if}}

If you want to search through and sort an array of objects (for example, if you are querying a list of blog posts), you can use #where:

{{#where posts (category='test' _by=title _order='desc')}}
    {{this.title}}
{{/where}}

Partials

Partials are pieces of sub-templates which you can pass an object to. The most basic partials can be defined using Javascript:

Transpiler.partial('myTest', '{{x}'})

You can then call it in your template like this: {{>myTest (x=5)}}. That should print "5". Very simple!

You can also put partials in templates themselves, using the partial block expression:

{{#partial partialName}}
    Hello {{x}}!
{{/partial}}

{{>partialName (x='world')}}

No matter where a partial is defined in the template, it'll be accessible anywhere from the scope it's in.

Partial block expressions

If you want to pass some locally scoped partials to another partial, you can do this too:

{{#>page}}
    {{#partial header}}
        Header
    {{/partial}}
    {{#partial footer}}
        Footer
    {{/partial}}
{{/page}}

Now you'll learn how to set 'globals' in the transpiler, and write your own block expressions.

Globals

Globals are variables/functions that will always be available no matter what objects are passed to the render function. For example, to implement Math.pow in curls:

Transpiler.set('pow', (a, b) => Math.pow(a,b))

Pretty simple! Okay, what about block expressions?

Transpiler.block('times', (block, context, times) => {
    let ret = 'Printing ' + times + ' times...';
    for(let i = 0; i < times; i++) ret += block();
    return ret;
})

The print function just tells the renderer to add something to the buffer, and the block() function runs the enclosed code inside the block, so now you can do this:

{{#times 10}}
    This will display 10 times.
{{/times}}

Transpiler details

The transpiler itself is a lexer/parser/transpiler set that simply converts the blocks of curls code straight into JavaScript. The lexer generates tokens, the parser validates and arranges them into 'token opcodes' which are then fed to the transpiler, which generates JavaScript.

Although transpiling to JavaScript and using eval functions is certainly a scary thing, thanks to the analysis and validation done by the lexer and parser, only valid JavaScript should be generated. No monkey business.