-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandlebars-renderer.js
179 lines (144 loc) · 4.08 KB
/
handlebars-renderer.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
var Promise = require('bluebird'),
fs = Promise.promisifyAll(require('fs')),
Handlebars = require('handlebars'),
S = require('string'),
globAsync = Promise.promisify(require('glob'));
function remove(array, value) {
var index = array.indexOf(value);
if (index > -1) {
array.splice(index, 1);
}
}
var Renderer = {
loadedPartials: {},
loadedHelpers: {},
_waitingPromises: [],
};
function validateGlobFilter(filter) {
return new Promise(function(resolve, reject) {
if (typeof filter !== 'string') {
reject(new Error('Fitler has to be a string, but is of type "'+(typeof filter)+'"'));
} else {
resolve(filter);
}
});
}
/**
* The waiting list takes care about all promiese that need to be resolved
* before rendering can start.
*/
Renderer._registerWaitingPromise = function(promise) {
this._waitingPromises.push(promise);
promise.then(function() {
remove(this._waitingPromises, promise);
})
.catch(function() {
remove(this._waitingPromises, promise);
});
}
Renderer.loadPartials = function(prefix, filter, cb) {
if (arguments.length === 1) {
filter = prefix;
prefix = "";
}
var promise = validateGlobFilter(filter)
.then(globAsync)
.bind(this)
.each(function(helper) {
var match = helper.match(/\/([^\/]*)\.mustache$/);
return this.loadPartial(helper, S(match[1]).camelize().s, prefix);
});
//we need to wait untill all partials are loaded
this._registerWaitingPromise(promise);
};
Renderer.loadPartial = function(path, name, prefix) {
return fs.readFileAsync(path)
.then(function(data) {
Handlebars.registerPartial(prefix + name, String(data));
});
};
Renderer.loadHelpers = function(filter) {
var promise = validateGlobFilter(filter)
.then(globAsync)
.bind(this)
.each(function(helper) {
var match = helper.match(/\/([^\/]*)\.js$/);
return this.loadHelper(helper, S(match[1]).camelize().s);
});
//we need to wait until all helpers are loaded
this._registerWaitingPromise(promise);
};
Renderer.loadHelper = function(path, name) {
return new Promise((function(resolve, reject) {
try {
if (this.loadedHelpers[name]) {
if (this.loadedHelpers[name] !== path) {
console.warn(name + " overwritten by: " + path);
};
} else {
this.loadedHelpers[name] = path;
Handlebars.registerHelper(name, require(path));
}
resolve();
} catch (e) {
reject(e);
}
}).bind(this));
}
//TODO cache templates (with sopport to clear templates)
function getTemplates(tpls) {
var keys = Object.keys(tpls),
loadList = [];
return Promise.resolve(keys)
.map(function(name) {
return getTemplate(tpls[name]);
})
.then(function(result) {
var list = {};
result.forEach(function(value, idx) {
list[keys[idx]] = value;
});
return list;
});
}
function getTemplate(path) {
if (path instanceof Template) {
var template = Handlebars.compile(String(path.string));
return Promise.resolve(template);
} else {
return fs.readFileAsync(path)
.then(function(data) {
return Handlebars.compile(String(data));
})
}
}
Renderer.setup = function(options) {
console.warn('deprecated: handlebars-renderer.setup() not required anymore');
};
//load default helpers
Renderer.loadHelpers(__dirname + "/lib/helpers/*.js");
function Template(string) {
this.string = string;
};
Renderer.Template = Template;
Renderer.__express = function(path, opt, cb) {
var pTemplates = getTemplates({
layout: opt.settings.layouts + "/" + (opt.settings.layout || 'main') + ".mustache",
content: path
});
//TODO what why the slice(0) whats the purpose of this?????
var promises = Renderer._waitingPromises.slice(0);
//TODO what is done here we wait or the tempaltes but still what is going on here???
promises.unshift(pTemplates);
Promise.all(promises)
.get(0)
.then(function(tpls) {
opt.bodyContent = new Handlebars.SafeString(tpls.content(opt));
cb(null, tpls.layout(opt));
})
.catch(function(e) {
cb(e);
})
.done();
};
module.exports = Renderer;