Files
handlebars.js/lib/handlebars/runtime.js
T
2014-04-13 07:21:08 -05:00

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;
}