UNPKG

3.27 kBJavaScriptView Raw
1
2var slice = Array.prototype.slice
3
4 , reHelperFuncHead = /vash\.helpers\.([^= ]+?)\s*=\s*function([^(]*?)\(([^)]*?)\)\s*{/
5 , reHelperFuncTail = /\}$/
6
7 , reBatchSeparator = /^\/\/\s*@\s*batch\s*=\s*(.*?)$/
8
9// The logic for compiling a giant batch of templates or several
10// helpers is nearly exactly the same. The only difference is the
11// actual compilation method called, and the regular expression that
12// determines how the giant string is split into named, uncompiled
13// template strings.
14module.exports = function compile(type, compile, str, options){
15
16 var separator = type === 'helper'
17 ? reHelperFuncHead
18 : reBatchSeparator;
19
20 var tpls = splitByNamedTpl(separator, str, function(ma, name){
21 return name.replace(/^\s+|\s+$/, '');
22 }, type === 'helper' ? true : false);
23
24 if(tpls){
25 Object.keys(tpls).forEach(function(path){
26 tpls[path] = type === 'helper'
27 ? compileSingleHelper(compile, tpls[path], options)
28 : compile('@{' + tpls[path] + '}', options);
29 });
30
31 tpls.toClientString = function(){
32 return Object.keys(tpls).reduce(function(prev, curr){
33 if(curr === 'toClientString'){
34 return prev;
35 }
36 return prev + tpls[curr].toClientString() + '\n';
37 }, '')
38 }
39 }
40
41 return tpls;
42}
43
44// Given a separator regex and a function to transform the regex result
45// into a name, take a string, split it, and group the rejoined strings
46// into an object.
47// This is useful for taking a string, such as
48//
49// // tpl1
50// what what
51// and more
52//
53// // tpl2
54// what what again
55//
56// and returning:
57//
58// {
59// tpl1: 'what what\nand more\n',
60// tpl2: 'what what again'
61// }
62var splitByNamedTpl = function(reSeparator, markup, resultHandler, keepSeparator){
63
64 var lines = markup.split(/[\n\r]/g)
65 ,tpls = {}
66 ,paths = []
67 ,currentPath = ''
68
69 lines.forEach(function(line, i){
70
71 var pathResult = reSeparator.exec(line)
72 ,handlerResult = pathResult ? resultHandler.apply(pathResult, pathResult) : null
73
74 if(handlerResult){
75 currentPath = handlerResult;
76 tpls[currentPath] = [];
77 }
78
79 if((!handlerResult || keepSeparator) && line){
80 tpls[currentPath].push(line);
81 }
82 });
83
84 Object.keys(tpls).forEach(function(key){
85 tpls[key] = tpls[key].join('\n');
86 })
87
88 return tpls;
89}
90
91var compileSingleHelper = function(compile, str, options){
92
93 options = options || {};
94
95 // replace leading/trailing spaces, and parse the function head
96 var def = str.replace(/^[\s\n\r]+|[\s\n\r]+$/, '').match(reHelperFuncHead)
97 // split the function arguments, kill all whitespace
98 ,args = def[3].split(',').map(function(arg){ return arg.replace(' ', '') })
99 ,name = def[1]
100 ,body = str
101 .replace( reHelperFuncHead, '' )
102 .replace( reHelperFuncTail, '' )
103
104 // Wrap body in @{} to simulate it actually being inside a function
105 // definition, since we manually stripped it. Without this, statements
106 // such as `this.what = "what";` that are at the beginning of the body
107 // will be interpreted as markup.
108 body = '@{' + body + '}';
109
110 // `args` and `asHelper` inform `vash.compile/link` that this is a helper
111 options.args = args;
112 options.asHelper = name;
113 return compile(body, options);
114}