Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80713 views
1
"use strict";
2
var Utils = require("./utils");
3
var Exception = require("./exception")["default"];
4
var COMPILER_REVISION = require("./base").COMPILER_REVISION;
5
var REVISION_CHANGES = require("./base").REVISION_CHANGES;
6
var createFrame = require("./base").createFrame;
7
8
function checkRevision(compilerInfo) {
9
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
10
currentRevision = COMPILER_REVISION;
11
12
if (compilerRevision !== currentRevision) {
13
if (compilerRevision < currentRevision) {
14
var runtimeVersions = REVISION_CHANGES[currentRevision],
15
compilerVersions = REVISION_CHANGES[compilerRevision];
16
throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
17
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
18
} else {
19
// Use the embedded version info since the runtime doesn't know about this revision yet
20
throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
21
"Please update your runtime to a newer version ("+compilerInfo[1]+").");
22
}
23
}
24
}
25
26
exports.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
27
28
function template(templateSpec, env) {
29
/* istanbul ignore next */
30
if (!env) {
31
throw new Exception("No environment passed to template");
32
}
33
if (!templateSpec || !templateSpec.main) {
34
throw new Exception('Unknown template object: ' + typeof templateSpec);
35
}
36
37
// Note: Using env.VM references rather than local var references throughout this section to allow
38
// for external users to override these as psuedo-supported APIs.
39
env.VM.checkRevision(templateSpec.compiler);
40
41
var invokePartialWrapper = function(partial, context, options) {
42
if (options.hash) {
43
context = Utils.extend({}, context, options.hash);
44
}
45
46
partial = env.VM.resolvePartial.call(this, partial, context, options);
47
var result = env.VM.invokePartial.call(this, partial, context, options);
48
49
if (result == null && env.compile) {
50
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
51
result = options.partials[options.name](context, options);
52
}
53
if (result != null) {
54
if (options.indent) {
55
var lines = result.split('\n');
56
for (var i = 0, l = lines.length; i < l; i++) {
57
if (!lines[i] && i + 1 === l) {
58
break;
59
}
60
61
lines[i] = options.indent + lines[i];
62
}
63
result = lines.join('\n');
64
}
65
return result;
66
} else {
67
throw new Exception("The partial " + options.name + " could not be compiled when running in runtime-only mode");
68
}
69
};
70
71
// Just add water
72
var container = {
73
strict: function(obj, name) {
74
if (!(name in obj)) {
75
throw new Exception('"' + name + '" not defined in ' + obj);
76
}
77
return obj[name];
78
},
79
lookup: function(depths, name) {
80
var len = depths.length;
81
for (var i = 0; i < len; i++) {
82
if (depths[i] && depths[i][name] != null) {
83
return depths[i][name];
84
}
85
}
86
},
87
lambda: function(current, context) {
88
return typeof current === 'function' ? current.call(context) : current;
89
},
90
91
escapeExpression: Utils.escapeExpression,
92
invokePartial: invokePartialWrapper,
93
94
fn: function(i) {
95
return templateSpec[i];
96
},
97
98
programs: [],
99
program: function(i, data, declaredBlockParams, blockParams, depths) {
100
var programWrapper = this.programs[i],
101
fn = this.fn(i);
102
if (data || depths || blockParams || declaredBlockParams) {
103
programWrapper = program(this, i, fn, data, declaredBlockParams, blockParams, depths);
104
} else if (!programWrapper) {
105
programWrapper = this.programs[i] = program(this, i, fn);
106
}
107
return programWrapper;
108
},
109
110
data: function(data, depth) {
111
while (data && depth--) {
112
data = data._parent;
113
}
114
return data;
115
},
116
merge: function(param, common) {
117
var ret = param || common;
118
119
if (param && common && (param !== common)) {
120
ret = Utils.extend({}, common, param);
121
}
122
123
return ret;
124
},
125
126
noop: env.VM.noop,
127
compilerInfo: templateSpec.compiler
128
};
129
130
var ret = function(context, options) {
131
options = options || {};
132
var data = options.data;
133
134
ret._setup(options);
135
if (!options.partial && templateSpec.useData) {
136
data = initData(context, data);
137
}
138
var depths,
139
blockParams = templateSpec.useBlockParams ? [] : undefined;
140
if (templateSpec.useDepths) {
141
depths = options.depths ? [context].concat(options.depths) : [context];
142
}
143
144
return templateSpec.main.call(container, context, container.helpers, container.partials, data, blockParams, depths);
145
};
146
ret.isTop = true;
147
148
ret._setup = function(options) {
149
if (!options.partial) {
150
container.helpers = container.merge(options.helpers, env.helpers);
151
152
if (templateSpec.usePartial) {
153
container.partials = container.merge(options.partials, env.partials);
154
}
155
} else {
156
container.helpers = options.helpers;
157
container.partials = options.partials;
158
}
159
};
160
161
ret._child = function(i, data, blockParams, depths) {
162
if (templateSpec.useBlockParams && !blockParams) {
163
throw new Exception('must pass block params');
164
}
165
if (templateSpec.useDepths && !depths) {
166
throw new Exception('must pass parent depths');
167
}
168
169
return program(container, i, templateSpec[i], data, 0, blockParams, depths);
170
};
171
return ret;
172
}
173
174
exports.template = template;function program(container, i, fn, data, declaredBlockParams, blockParams, depths) {
175
var prog = function(context, options) {
176
options = options || {};
177
178
return fn.call(container,
179
context,
180
container.helpers, container.partials,
181
options.data || data,
182
blockParams && [options.blockParams].concat(blockParams),
183
depths && [context].concat(depths));
184
};
185
prog.program = i;
186
prog.depth = depths ? depths.length : 0;
187
prog.blockParams = declaredBlockParams || 0;
188
return prog;
189
}
190
191
exports.program = program;function resolvePartial(partial, context, options) {
192
if (!partial) {
193
partial = options.partials[options.name];
194
} else if (!partial.call && !options.name) {
195
// This is a dynamic partial that returned a string
196
options.name = partial;
197
partial = options.partials[partial];
198
}
199
return partial;
200
}
201
202
exports.resolvePartial = resolvePartial;function invokePartial(partial, context, options) {
203
options.partial = true;
204
205
if(partial === undefined) {
206
throw new Exception("The partial " + options.name + " could not be found");
207
} else if(partial instanceof Function) {
208
return partial(context, options);
209
}
210
}
211
212
exports.invokePartial = invokePartial;function noop() { return ""; }
213
214
exports.noop = noop;function initData(context, data) {
215
if (!data || !('root' in data)) {
216
data = data ? createFrame(data) : {};
217
data.root = context;
218
}
219
return data;
220
}
221