171 lines
5.1 KiB
JavaScript
171 lines
5.1 KiB
JavaScript
module Utils from "./utils";
|
|
import Exception from "./exception";
|
|
import { COMPILER_REVISION, REVISION_CHANGES, createFrame } from "./base";
|
|
|
|
export function checkRevision(compilerInfo) {
|
|
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
|
|
currentRevision = COMPILER_REVISION;
|
|
|
|
if (compilerRevision !== currentRevision) {
|
|
if (compilerRevision < currentRevision) {
|
|
var runtimeVersions = REVISION_CHANGES[currentRevision],
|
|
compilerVersions = REVISION_CHANGES[compilerRevision];
|
|
throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
|
|
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
|
|
} else {
|
|
// Use the embedded version info since the runtime doesn't know about this revision yet
|
|
throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
|
|
"Please update your runtime to a newer version ("+compilerInfo[1]+").");
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: Remove this line and break up compilePartial
|
|
|
|
export function template(templateSpec, env) {
|
|
if (!env) {
|
|
throw new Exception("No environment passed to template");
|
|
}
|
|
|
|
// Note: Using env.VM references rather than local var references throughout this section to allow
|
|
// for external users to override these as psuedo-supported APIs.
|
|
env.VM.checkRevision(templateSpec.compiler);
|
|
|
|
var invokePartialWrapper = function(partial, name, context, hash, helpers, partials, data) {
|
|
if (hash) {
|
|
context = Utils.extend({}, context, hash);
|
|
}
|
|
|
|
var result = env.VM.invokePartial.call(this, partial, name, context, helpers, partials, data);
|
|
if (result != null) { return result; }
|
|
|
|
if (env.compile) {
|
|
var options = { helpers: helpers, partials: partials, data: data };
|
|
partials[name] = env.compile(partial, { data: data !== undefined }, env);
|
|
return partials[name](context, options);
|
|
} else {
|
|
throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
|
|
}
|
|
};
|
|
|
|
// Just add water
|
|
var container = {
|
|
escapeExpression: Utils.escapeExpression,
|
|
invokePartial: invokePartialWrapper,
|
|
|
|
fn: function(i) {
|
|
return templateSpec[i];
|
|
},
|
|
|
|
programs: [],
|
|
program: function(i, data) {
|
|
var programWrapper = this.programs[i],
|
|
fn = this.fn(i);
|
|
if(data) {
|
|
programWrapper = program(this, i, fn, data);
|
|
} else if (!programWrapper) {
|
|
programWrapper = this.programs[i] = program(this, i, fn);
|
|
}
|
|
return programWrapper;
|
|
},
|
|
programWithDepth: env.VM.programWithDepth,
|
|
|
|
data: function(data, depth) {
|
|
while (data && depth--) {
|
|
data = data._parent;
|
|
}
|
|
return data;
|
|
},
|
|
merge: function(param, common) {
|
|
var ret = param || common;
|
|
|
|
if (param && common && (param !== common)) {
|
|
ret = Utils.extend({}, common, param);
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
noop: env.VM.noop,
|
|
compilerInfo: templateSpec.compiler
|
|
};
|
|
|
|
var ret = function(context, options) {
|
|
options = options || {};
|
|
var helpers,
|
|
partials,
|
|
data = options.data;
|
|
|
|
ret._setup(options);
|
|
if (!options.partial && templateSpec.useData) {
|
|
data = initData(context, data);
|
|
}
|
|
return templateSpec.main.call(container, context, container.helpers, container.partials, data);
|
|
};
|
|
|
|
ret._setup = function(options) {
|
|
if (!options.partial) {
|
|
container.helpers = container.merge(options.helpers, env.helpers);
|
|
|
|
if (templateSpec.usePartial) {
|
|
container.partials = container.merge(options.partials, env.partials);
|
|
}
|
|
} else {
|
|
container.helpers = options.helpers;
|
|
container.partials = options.partials;
|
|
}
|
|
};
|
|
|
|
ret._child = function(i) {
|
|
return container.programWithDepth(i);
|
|
};
|
|
return ret;
|
|
}
|
|
|
|
export function programWithDepth(i, data /*, $depth */) {
|
|
/*jshint -W040 */
|
|
var args = Array.prototype.slice.call(arguments, 2),
|
|
container = this,
|
|
fn = container.fn(i);
|
|
|
|
var prog = function(context, options) {
|
|
options = options || {};
|
|
|
|
return fn.apply(container, [context, container.helpers, container.partials, options.data || data].concat(args));
|
|
};
|
|
prog.program = i;
|
|
prog.depth = args.length;
|
|
return prog;
|
|
}
|
|
|
|
export function program(container, i, fn, data) {
|
|
var prog = function(context, options) {
|
|
options = options || {};
|
|
|
|
return fn.call(container, context, container.helpers, container.partials, options.data || data);
|
|
};
|
|
prog.program = i;
|
|
prog.depth = 0;
|
|
return prog;
|
|
}
|
|
|
|
export function invokePartial(partial, name, context, helpers, partials, data) {
|
|
var options = { partial: true, helpers: helpers, partials: partials, data: data };
|
|
|
|
if(partial === undefined) {
|
|
throw new Exception("The partial " + name + " could not be found");
|
|
} else if(partial instanceof Function) {
|
|
return partial(context, options);
|
|
}
|
|
}
|
|
|
|
export function noop() { return ""; }
|
|
|
|
function initData(context, data) {
|
|
if (!data || !('root' in data)) {
|
|
data = data ? createFrame(data) : {};
|
|
data.root = context;
|
|
}
|
|
return data;
|
|
}
|