Nanoseconds Produce Minutes
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

babel-temple

0.4.0 • Public • Published

Babel Temple

Tiny template engine coupled with babel-tower.

TOC

Babel Tower strings

variable substitution .

expect( Temple.render( "Hello ${name}!" , { name: "Bob" } ) ).to.be( "Hello Bob!" ) ;
expect( Temple.render( "Hello ${name1} and ${name2}!" , { name1: "Bob" , name2: "James" } ) ).to.be( "Hello Bob and James!" ) ;

post-filters .

expect( Temple.render( "Hello ${name//uc1}!" , { name: "bob" } ) ).to.be( "Hello Bob!" ) ;

complex syntax .

expect( Temple.render( "Hello ${list}[enum:nobody|$|, $| and $]!" , { list: [] } ) ).to.be( "Hello nobody!" ) ;
expect( Temple.render( "Hello ${list}[enum:nobody|$|, $| and $]!" , { list: [ "Bob" ] } ) ).to.be( "Hello Bob!" ) ;
expect( Temple.render( "Hello ${list}[enum:nobody|$|, $| and $]!" , { list: [ "Bob" , "James" ] } ) ).to.be( "Hello Bob and James!" ) ;
expect( Temple.render( "Hello ${list}[enum:nobody|$|, $| and $]!" , { list: [ "Bob" , "James" , "Sarah" ] } ) ).to.be( "Hello Bob, James and Sarah!" ) ;

'if' tag

simple 'if' syntax.

expect( Temple.render( "Just a little{{if $test}} test{{/}}." , { test: true } ) ).to.be( "Just a little test." ) ;
expect( Temple.render( "Just a little{{if $test}} test{{/}}." , { test: false } ) ).to.be( "Just a little." ) ;
 
expect( Temple.render( 'Just a little{{if $test = "bob"}} test{{/}}.' , { test: true } ) ).to.be( "Just a little." ) ;
expect( Temple.render( 'Just a little{{if $test = "bob"}} test{{/}}.' , { test: "bill" } ) ).to.be( "Just a little." ) ;
expect( Temple.render( 'Just a little{{if $test = "bob"}} test{{/}}.' , { test: "bob" } ) ).to.be( "Just a little test." ) ;
 
expect( Temple.render( 'Just a little{{if $test > 3}} test{{/}}.' , { test: 1 } ) ).to.be( "Just a little." ) ;
expect( Temple.render( 'Just a little{{if $test > 3}} test{{/}}.' , { test: 5 } ) ).to.be( "Just a little test." ) ;

'if-else' syntax.

expect( Temple.render( "Is it {{if $test}}a test{{/}}{{else}}real{{/}}?" , { test: true } ) ).to.be( "Is it a test?" ) ;
expect( Temple.render( "Is it {{if $test}}a test{{/}}{{else}}real{{/}}?" , { test: false } ) ).to.be( "Is it real?" ) ;
 
// Undocumented behavior.
// It may look strange but is intended: extra content in the middle are usually white-space or newline used for presentation
expect( Temple.render( "Is it {{if $test}}a test{{/}} () {{else}}real{{/}}?" , { test: true } ) ).to.be( "Is it a test () ?" ) ;
expect( Temple.render( "Is it {{if $test}}a test{{/}} () {{else}}real{{/}}?" , { test: false } ) ).to.be( "Is it real () ?" ) ;

'if-else' using the close-open syntactic sugar.

expect( Temple.render( "Is it {{if $test}}a test{{/else}}real{{/}}?" , { test: true } ) ).to.be( "Is it a test?" ) ;
expect( Temple.render( "Is it {{if $test}}a test{{/else}}real{{/}}?" , { test: false } ) ).to.be( "Is it real?" ) ;

'if-elseif' syntax.

expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}." , { value: 3 } ) ).to.be( "It is positive." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}." , { value: -3 } ) ).to.be( "It is negative." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}." , { value: 0 } ) ).to.be( "It is ." ) ;

'if-elseif' using the close-open syntactic sugar.

expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/}}." , { value: 3 } ) ).to.be( "It is positive." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/}}." , { value: -3 } ) ).to.be( "It is negative." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/}}." , { value: 0 } ) ).to.be( "It is ." ) ;

'if-elseif-else' syntax.

expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}{{else}}zero{{/}}." , { value: 3 } ) ).to.be( "It is positive." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}{{else}}zero{{/}}." , { value: -3 } ) ).to.be( "It is negative." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/}}{{elseif $value < 0}}negative{{/}}{{else}}zero{{/}}." , { value: 0 } ) ).to.be( "It is zero." ) ;

'if-elseif-else' using the close-open syntactic sugar.

expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/else}}zero{{/}}." , { value: 3 } ) ).to.be( "It is positive." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/else}}zero{{/}}." , { value: -3 } ) ).to.be( "It is negative." ) ;
expect( Temple.render( "It is {{if $value > 0 }}positive{{/elseif $value < 0}}negative{{/else}}zero{{/}}." , { value: 0 } ) ).to.be( "It is zero." ) ;

'if-elseif-else' syntax with multiple 'elseif' tags.

var template = Temple.parse( 'Hello {{if $name = "Robert"}}Bob{{/elseif $name = "Jack"}}Jack{{/elseif $name = "Bill"}}my friend{{/else}}stranger{{/}}!' ) ;
 
expect( template.render( { name: "Robert" } ) ).to.be( "Hello Bob!" ) ;
expect( template.render( { name: "Jack" } ) ).to.be( "Hello Jack!" ) ;
expect( template.render( { name: "Bill" } ) ).to.be( "Hello my friend!" ) ;
expect( template.render( { name: "Joe" } ) ).to.be( "Hello stranger!" ) ;

'foreach' tag

'foreach' on an array should iterate over each element.

var template ;
 
var ctx = {
    joe: [
        "Joe" ,
        "Doe" ,
        "New York"
    ]
} ;
 
template = Temple.parse( '{{foreach $joe => $key : $value}}${key}: ${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "0: Joe\n1: Doe\n2: New York\n" ) ;
 
template = Temple.parse( '{{foreach $joe => $value}}${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "Joe\nDoe\nNew York\n" ) ;

'foreach' on an object should iterate over each property.

var template ;
 
var ctx = {
    joe: {
        "first name": "Joe" ,
        "last name": "Doe" ,
        "city" : "New York"
    }
} ;
 
template = Temple.parse( '{{foreach $joe => $key : $value}}${key}: ${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "first name: Joe\nlast name: Doe\ncity: New York\n" ) ;
 
template = Temple.parse( '{{foreach $joe => $value}}${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "Joe\nDoe\nNew York\n" ) ;

'key' and 'value' variable should be shadowed inside the tag and restored after it.

var template ;
 
var ctx = {
    key: "A key" ,
    value: "12k€" ,
    joe: {
        "first name": "Joe" ,
        "last name": "Doe" ,
        "city" : "New York"
    }
} ;
 
template = Temple.parse( 'key: ${key}\nvalue: ${value}\n{{foreach $joe => $key : $value}}${key}: ${value}\n{{/}}key: ${key}\nvalue: ${value}\n' ) ;
expect( template.render( ctx ) ).to.be( "key: A key\nvalue: 12k€\nfirst name: Joe\nlast name: Doe\ncity: New York\nkey: A key\nvalue: 12k€\n" ) ;

'foreach' on a non-object should do nothing.

var template ;
 
var ctx = {
    joe: true ,
} ;
 
template = Temple.parse( '{{foreach $joe => $key : $value}}${key}: ${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "" ) ;
 
template = Temple.parse( '{{foreach $joe => $value}}${value}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "" ) ;
 
template = Temple.parse( 'some {{foreach $joe => $key : $value}}${key}: ${value}\n{{/}}text' ) ;
expect( template.render( ctx ) ).to.be( "some text" ) ;

'let' tag

'let' tag should create new variable in the current scope.

var template , ctx ;
 
template = Temple.parse( '{{let $greetings : "Hi"/}}${greetings} ${firstName} ${lastName}{{/}}' ) ;
 
ctx = {
    firstName: "Joe" ,
    lastName: "Doe"
} ;
 
expect( template.render( ctx ) ).to.be( "Hi Joe Doe" ) ;

only the current context is modified.

var template , ctx ;
 
template = Temple.parse( '{{use $sub}}{{let $greetings : "Hi"/}}${greetings} ${firstName} ${lastName}\n{{/}}${sub.greetings} ${sub.firstName} ${sub.lastName}\n{{/}}' ) ;
 
ctx = { sub: {
    greetings: "Hello" ,
    firstName: "Joe" ,
    lastName: "Doe"
} } ;
 
expect( template.render( ctx ) ).to.be( "Hi Joe Doe\nHello Joe Doe\n" ) ;
expect( ctx ).to.eql( { sub: { greetings: "Hello" , firstName: "Joe" , lastName: "Doe" } } ) ;

the original context should be preserved.

var template , ctx ;
 
template = Temple.parse( '{{let $greetings : "Hi"/}}${greetings} ${firstName} ${lastName}{{/}}' ) ;
 
ctx = {
    firstName: "Joe" ,
    lastName: "Doe"
} ;
 
expect( template.render( ctx ) ).to.be( "Hi Joe Doe" ) ;
expect( ctx ).to.eql( { firstName: "Joe" , lastName: "Doe" } ) ;

'use' tag

if the variable is an object, it should create a new context inside the tag and render it.

var template , ctx ;
 
template = Temple.parse( '{{use $path.to.var}}${firstName} ${lastName} of ${city}\n{{/}}' ) ;
 
ctx = { path: { to: { "var": {
    firstName: "Joe" ,
    lastName: "Doe" ,
    city : "New York"
} } } } ;
 
expect( template.render( ctx ) ).to.be( "Joe Doe of New York\n" ) ;

if the variable is an array, it should should iterate over it, using each element as the context.

var template , ctx ;
 
template = Temple.parse( '{{use $path.to.var}}${firstName} ${lastName} of ${city}\n{{/}}' ) ;
 
ctx = { path: { to: { "var": [
    {
        firstName: "Joe" ,
        lastName: "Doe" ,
        city : "New York"
    } ,
    {
        firstName: "Sandra" ,
        lastName: "Murphy" ,
        city : "Los Angeles"
    } 
] } } } ;
 
expect( template.render( ctx ) ).to.be( "Joe Doe of New York\nSandra Murphy of Los Angeles\n" ) ;

if the variable is a non-object truthy value, it should render its inner content.

var template , ctx ;
 
ctx = { path: { to: { "var": "some string" } } } ;
template = Temple.parse( '{{use $path.to.var}}${firstName} ${lastName} of ${city}\n{{/}}' ) ;
 
expect( template.render( ctx ) ).to.be( "(undefined) (undefined) of (undefined)\n" ) ;
 
template = Temple.parse( '{{use $path.to.var}}value: $\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "value: some string\n" ) ;

if the variable is a falsy value, it should not render its inner content.

var template , ctx ;
 
template = Temple.parse( '{{use $path.to.var}}${firstName} ${lastName} of ${city}\n{{/}}' ) ;
 
ctx = { path: { to: { "var": false } } } ;
 
expect( template.render( ctx ) ).to.be( "" ) ;

'use' syntactic sugar: direct variable.

var template , ctx ;
 
template = Temple.parse( '{{$path.to.var}}${firstName} ${lastName} of ${city}\n{{/}}' ) ;
 
ctx = { path: { to: { "var": [
    {
        firstName: "Joe" ,
        lastName: "Doe" ,
        city : "New York"
    } ,
    {
        firstName: "Sandra" ,
        lastName: "Murphy" ,
        city : "Los Angeles"
    } 
] } } } ;
 
expect( template.render( ctx ) ).to.be( "Joe Doe of New York\nSandra Murphy of Los Angeles\n" ) ;

'join' tag should be used to join rendering parts.

var template , ctx ;
 
template = Temple.parse( '{{$path.to.var}}${firstName} ${lastName}{{/join}} and {{/}}' ) ;
 
ctx = { path: { to: { "var": [] } } } ;
expect( template.render( ctx ) ).to.be( "" ) ;
 
ctx.path.to.var.push( { firstName: "Joe" , lastName: "Doe" } ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe" ) ;
 
ctx.path.to.var.push( { firstName: "Sandra" , lastName: "Murphy" } ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe and Sandra Murphy" ) ;
 
ctx.path.to.var.push( { firstName: "John" , lastName: "Peter" } ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe and Sandra Murphy and John Peter" ) ;

'empty' tag

if the variable is a falsy value, it should render its inner content.

var template , ctx ;
 
ctx = { path: { to: { "var": false } } } ;
template = Temple.parse( '{{empty $path.to.var}}This is empty.{{/}}' ) ;
 
expect( template.render( ctx ) ).to.be( "This is empty." ) ;

if the variable is a truthy value, it should not render its inner content.

var template , ctx ;
 
ctx = { path: { to: { "var": true } } } ;
template = Temple.parse( '{{empty $path.to.var}}This is empty.{{/}}' ) ;
 
expect( template.render( ctx ) ).to.be( "" ) ;

an 'empty' tag just after a 'use' tag can omit the variable.

var template , ctx ;
 
template = Temple.parse( '{{$path.to.var}}{{/empty}}This is empty.{{/}}' ) ;
 
ctx = { path: { to: { "var": false } } } ;
expect( template.render( ctx ) ).to.be( "This is empty." ) ;
 
ctx = { path: { to: { "var": true } } } ;
expect( template.render( ctx ) ).to.be( "" ) ;

partial rendering: 'call' tag

'call' tag should render a sub-template.

var template , partial , ctx ,
    lib = new Temple.Lib() ;
 
partial = Temple.parse( '${firstName} ${lastName} of ${city}\n' , { id: 'partial' , lib: lib } ) ;
 
ctx = { path: { to: { "var": [
    {
        firstName: "Joe" ,
        lastName: "Doe" ,
        city : "New York"
    } ,
    {
        firstName: "Sandra" ,
        lastName: "Murphy" ,
        city : "Los Angeles"
    } 
] } } } ;
 
template = Temple.parse( '{{$path.to.var}}{{call partial/}}{{/}}' , { lib: lib } ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe of New York\nSandra Murphy of Los Angeles\n" ) ;
 
template = Temple.parse( '{{call partial $path.to.var[0]/}}' , { lib: lib } ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe of New York\n" ) ;

'call' tag '@' syntax.

var template , partial , ctx ,
    lib = new Temple.Lib() ;
 
partial = Temple.parse( '${firstName} ${lastName} of ${city}\n' , { id: 'partial' , lib: lib } ) ;
 
ctx = { path: { to: { "var": [
    {
        firstName: "Joe" ,
        lastName: "Doe" ,
        city : "New York"
    } ,
    {
        firstName: "Sandra" ,
        lastName: "Murphy" ,
        city : "Los Angeles"
    } 
] } } } ;
 
template = Temple.parse( '{{@partial $path.to.var[1]/}}' , { lib: lib } ) ;
expect( template.render( ctx ) ).to.be( "Sandra Murphy of Los Angeles\n" ) ;

no root context preservation.

var template , partial , ctx ,
    lib = new Temple.Lib() ;
 
partial = Temple.parse( '${.greetings} ${firstName} ${lastName} of ${city}\n' , { id: 'partial' , lib: lib } ) ;
 
ctx = { 
    greetings: 'Hello' ,
    path: { to: { "var": [
        {
            firstName: "Joe" ,
            lastName: "Doe" ,
            city : "New York"
        } ,
        {
            firstName: "Sandra" ,
            lastName: "Murphy" ,
            city : "Los Angeles"
        }
    ]
} } } ;
 
template = Temple.parse( '{{$path.to.var}}{{call partial/}}{{/}}' , { lib: lib } ) ;
expect( template.render( ctx ) ).to.be( "(undefined) Joe Doe of New York\n(undefined) Sandra Murphy of Los Angeles\n" ) ;

Template library

should load all dependencies.

var template , partial , ctx ;
 
var lib = new Temple.Lib( {
    loadAsync: async function( id ) {
        //console.log( "id:" , id ) ;
        switch ( id ) {
            case 'description' :
                return '{{call greetings/}} ${firstName} ${lastName} of ${city}{{call punctuation}}\n' ;
            case 'greetings' :
                return 'Hello' ;
            case 'punctuation' :
                return '!!!' ;
            default :
                break ;
        }
    }
} ) ;
 
 
ctx = { path: { to: { "var": [
    {
        firstName: "Joe" ,
        lastName: "Doe" ,
        city : "New York"
    } ,
    {
        firstName: "Sandra" ,
        lastName: "Murphy" ,
        city : "Los Angeles"
    } 
] } } } ;
 
template = Temple.parse( '{{call greetings/}}!\n{{$path.to.var}}{{call description/}}\n{{/}}' , { lib: lib } ) ;
 
lib.loadDependenciesAsync().then( () => {
    expect( template.render( ctx ) ).to.be( "Hello!\nHello Joe Doe of New York!!!\nHello Sandra Murphy of Los Angeles!!!\n" ) ;
    done() ;
} )
.catch( error => done( error ) ) ;

root context

the root context should be accessible using the '$.' variable.

var template , ctx ;
 
ctx = {
    greetings: "Hello" ,
    path: { to: { "var": [
        {
            firstName: "Joe" ,
            lastName: "Doe" ,
            city : "New York"
        } ,
        {
            firstName: "Sandra" ,
            lastName: "Murphy" ,
            city : "Los Angeles"
        } 
    ] } }
} ;
 
template = Temple.parse( '{{$path.to.var}}${.greetings} ${firstName} ${lastName} of ${city}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "Hello Joe Doe of New York\nHello Sandra Murphy of Los Angeles\n" ) ;
 
template = Temple.parse( '{{$path}}{{$to.var}}${.greetings} ${firstName} ${lastName} of ${city}\n{{//}}' ) ;
expect( template.render( ctx ) ).to.be( "Hello Joe Doe of New York\nHello Sandra Murphy of Los Angeles\n" ) ;
 
template = Temple.parse( '{{$path}}{{$to}}{{$var}}${.greetings} ${firstName} ${lastName} of ${city}\n{{///}}' ) ;
expect( template.render( ctx ) ).to.be( "Hello Joe Doe of New York\nHello Sandra Murphy of Los Angeles\n" ) ;

close syntactic sugar syntax

close-open syntactic sugar.

expect( Temple.render( "Is it {{if $test}}a test{{/else}}real{{/}}?" , { test: true } ) ).to.be( "Is it a test?" ) ;
expect( Temple.render( "Is it {{if $test}}a test{{/else}}real{{/}}?" , { test: false } ) ).to.be( "Is it real?" ) ;

multiple close syntactic sugar.

var template , ctx ;
 
ctx = {
    path: { to: { "var": {
            firstName: "Joe" ,
            lastName: "Doe" ,
    } } }
} ;
 
template = Temple.parse( '{{$path}}{{$to}}{{$var}}${firstName} ${lastName}\n{{//}}${to.var.firstName} ${to.var.lastName}\n{{/}}' ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe\nJoe Doe\n" ) ;
 
template = Temple.parse( '{{$path}}{{$to}}{{$var}}${firstName} ${lastName}\n{{///}}${path.to.var.firstName} ${path.to.var.lastName}\n' ) ;
expect( template.render( ctx ) ).to.be( "Joe Doe\nJoe Doe\n" ) ;

escape syntax

escape.

expect( Temple.render( "Just a \\\\{} little{{if $test}} test{{/}}." , { test: true } ) ).to.be( "Just a \\a {} little test." ) ;
expect( Temple.render( "Just a \\\\{} little{{if $test}} test{{/}}." , { test: false } ) ).to.be( "Just a \\a {} little." ) ;

Keywords

install

npm i babel-temple

Downloadsweekly downloads

0

version

0.4.0

license

MIT

homepage

github.com

repository

Gitgithub

last publish

collaborators

  • avatar
Report a vulnerability