tss

a minimal template engine

npm install tss
8 downloads in the last week
24 downloads in the last month
tss

tss is a minimal templage engine, unlike all other template system tss not use any pseudo langage into the template,

instead, to really separate design from code it is fully callback based

only one char define template keywords : §, nothing else need to be know

install tss

npm install tss

import tss

var tss = require("tss").tss;

how to & example

syntax is easy :

var filledTemplate = tss(template, data, callback);

callback use is optionnal, if there is not any, tss will just replace keywords with their associed data or with empty string ''

minimal example, not any use of callback

tss("hello §name§",{
    name : "world"
});

will return "hello world"

if data is an array, tss will loop itself on each value :

"<ul>" + tss("<li>§name§</li>",[
    { name : "john" },
    { name : "mike" },
    { name : "kate" }
]) + "</ul>";

will result in :

<ul>
    <li>john</li>
    <li>mike</li>
    <li>kate</li>
</ul>

callback can be an object with some function, or a "generic" single function, "this" in callback will always refer to the data object

callback object example :

tss("§greetings§ §name§",{
    name : "world",
    greetings : "hello"
},{
    name : function(name){
        return name.toUpperCase();
        // or this.name.toUpperCase();
    }
});

will return "hello WORLD"

single generic callback function example :

tss("hello §name§",{
    name : "world"
},function(keyword){
    switch(keyword){
        case 'name' : return this.name.toUpperCase(); break;
    }    return '';
});

keywords can be "virtual", not any dedicated data, but generated by callback

tss("hello §name§",{
    userName : "world"
},{
    name : function(){
        return this.userName.toUpperCase();
    }
});

that work with the two syntax :

tss("hello §name§",{
    userName : "world"
},function(keyword){
    switch(keyword){
        case 'name' : return this.userName.toUpperCase(); break;
    }    return '';
});

extract all handler and templates into dedicated data object for maximum reuse and abstraction :

var template = {
    user : {
        registered : 'hello user §id§ <b>§name§</b> <a href="/logout">logout</a>',
        unregistered : 'Hello unregistered user, <a href="/auth/google">login</a>',
        userpage : '<h1>user §id§</h1><section><h2>§name§</h2><p>§email§</p></section>'
    }
}

var handler = {
    user : {
        name:function(){
            switch(this.account){
                case 'google':
                    return this.profile.displayName;
                break;
            };    return 'anon';
        },
        mail:function(){
            switch(this.account){
                case 'google':
                    return this.profile.emails[0].value;
                break;
            };    return 'not any mail';
        }
    }
};

var html = tss(template.user.userpage,user,{
    name:handler.user.name,
    email:handler.user.mail
});

or directly :

var html = tss(template.user.userpage,user,handler.user);

async

default tss use is sync, but it can be used in an async way, for that purpose it will require async and async-replace npm packages

async tss can be used simply with :

tss.async(template, data, callback, done);

all data callback will get an extra parameter who is the job end callback

tss.async("hello §name§",{
    name : "world"
},{
    name : function(name,done){
        setTimeout(function(){
            done(null,'<i>'+name+'</i>');
        },1000);
    }
},function(err,data){
    console.log( "filled data : ", data);
});

for virtual keywords :

tss.async("hello §name§",{
    myname : "world"
},{
    name : function(done){
        var t = this;
        setTimeout(function(){
            done(null,'<i>'+t.myname+'</i>');
        },1000);
    }
},function(err,data){
    console.log( "filled data : ", data);
});

the use of this job end callback is optionnal, if your data callback return anything the job callback will not be used, you can mix async && sync data callback :

tss.async("hello <i>§name§</i>, glad to see you back §time§",{
     login : "kate",
    gender : "Miss"
},{
    name : function(){
        return this.gender + " " + this.login;
    },
    time : function(done){
        db.get("users:last-ping:"+this.login,function(err,time){
            time = (new Date()) - time; // from now
            time /= 1000*3600*24; // in day
            if(time > 90) return done(null, "from death");
            var timeString = (time > 7)?"after so long time !":"so fast.";
            done(null, timeString );
        });
    }
},function(err,data){
    res.send( data );
});

and if there is not any callback for a keyword, this one will just be done in a sync way :

function toUpperCase(s){ return s.toUpperCase(); }
var smiles = { cool:":)", great:":D" };

tss.async("§greetings§ §name§ this is a §what§ ! §smile§",{
      myname : "world",
        what : "test",
    greetings : "hello",
      feeling : "great"
},{
    name:function(done){
        var t = this;
        setTimeout(function(){
            done(null,'<i>'+t.myname+'</i>');
        },1000);
    },
    smile:function(){
        return smiles[this.feeling];
    },
    greetings:toUpperCase
},function(err,data){
    console.log(data);
});

that will log after a second :

HELLO <i>world</i> this is a test ! :D

finally, array data could be async too, and will be processed in parallel

tss.async("§a§",[
    { a:1 },
    { a:2 },
    { a:3 }
],function(keyword,done){
    var t = this;
    var time = t.a * 1000;
    setTimeout(function(){
        done(null,"\n#"+t.a+" took "+time+"ms to complete");
    },time);
},function(err,data){
    console.log(data);
});

who will log 3 second after :

#1 took 1000ms to complete
#2 took 2000ms to complete
#3 took 3000ms to complete

and with a keyword more :

tss.async("§a§ §hello§",[
    { a:1 },
    { a:2 },
    { a:3 }
],function(keyword,done){
    var t = this;
    var time = t.a * 1000;
    setTimeout(function(){
        done(null,"\n #"+t.a+" ("+keyword+") took "+time+"ms to complete");
    },time);
},function(err,data){
    console.log(data);
});

still output 3 second after :

#1 (a) took 1000ms to complete 
#1 (hello) took 1000ms to complete
#2 (a) took 2000ms to complete 
#2 (hello) took 2000ms to complete
#3 (a) took 3000ms to complete 
#3 (hello) took 3000ms to complete
npm loves you