-
Notifications
You must be signed in to change notification settings - Fork 1
/
ktl.js
96 lines (84 loc) · 3.09 KB
/
ktl.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
* KLT uses tags:
*
* {{ var }} - property of passed object
* {{ _ }} - verbatim passed object
* {{# array }} {{ _ }} {{#}} - array iteration
* {{ $ }} - index in array
* {{? condition}} data {{?}} - conditional
*/
var detlimer = /{{|}}/
var nestingTokens = {
'#': function (tokens) {
// build an iteration
var array = tokens[0].substring(1);
return "( function() { try{ return "+ array + ".map(function(_,$){ try{ " + build(tokens.splice(1)) + " } catch(e) { return \"\"} } ).join(\"\") } catch(e){ return \"\"; } })()";
},
'?': function (tokens) {
// build an condition
var condition = tokens[0].substring(1);
var elsePos = tokens.indexOf(':');
if ( elsePos === -1 ) {
return "(function() { try { if ("+condition+")"+build(tokens.splice(1))+";} catch(e){}; return \"\" } )()";
} else {
return "(function() { try { if ("+condition+")" +
build(tokens.splice(1,elsePos-1))+" else "+
build(tokens.splice(elsePos)) +
";} catch(e){}; return \"\" } )()";
}
}
}
function build(tokens) {
var body = [];
var idx;
function assessErrorPosition() {
return "on line "+(tokens.filter(function(k,i) {
return i<=idx
}).join('').split('\n').length);
}
for (idx = 0; idx < tokens.length; idx += 2) {
body.push(JSON.stringify(tokens[idx]));
var token = tokens[idx + 1];
if (token) {
var nesting = nestingTokens[token[0]];
if (nesting) {
if (token.length > 1) {
var depth = 1;
var nestor = token[0];
var ahead = idx + 1;
do {
ahead += 2;
if (ahead >= tokens.length) break;
if (tokens[ahead][0] === nestor) {
if (tokens[ahead].length === 1) {
depth -= 1;
} else {
depth += 1;
}
}
} while (depth > 0);
if (depth > 0) {
throw new SyntaxError("Missing closing " + nestor + " " + assessErrorPosition());
}
body.push("(" + nesting(tokens.slice(idx + 1, ahead)) + ")");
idx = ahead-1;
}
else {
throw new SyntaxError("Unexpeced closing tag: " + token + " "+ assessErrorPosition());
}
}
else {
body.push("(typeof(" + token + ")!==\"undefined\"?$$(" + token + "):\"\")");
}
}
}
var source = "{ $$=($ instanceof Function ? $ : $$)||function(a){return a;}; with(_||{}) { return " + body.join("+") + "; } }";
return source;
}
function compile(tokens) {
return new Function("_,$,$$", build(tokens));
}
function ktl(template) {
return compile(template.split(detlimer));
}
module.exports = ktl;