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, indent, 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 && env.compile) { var options = { helpers: helpers, partials: partials, data: data }; partials[name] = env.compile(partial, { data: data !== undefined }, env); result = partials[name](context, options); } if (result != null) { if (indent) { var lines = result.split('\n'); for (var i = 0, l = lines.length; i < l; i++) { if (!lines[i] && i + 1 === l) { break; } lines[i] = indent + lines[i]; } result = lines.join('\n'); } return result; } else { throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); } }; // Just add water var container = { lambda: function(current, context) { return typeof current === 'function' ? current.call(context) : current; }, 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; }