Make the Handlebars environment into an object
The idea is that the environment wraps up the mutable stuff in Handlebars (like the helpers) and that you could theoretically create a new one at any time and pass it in to Handlebars.template. Every test makes a new environment and uses it in template compilation.
This commit is contained in:
+9
-2
@@ -1,4 +1,4 @@
|
|||||||
import { base as handlebars } from "./handlebars/base";
|
import { HandlebarsEnvironment } from "./handlebars/base";
|
||||||
|
|
||||||
// Each of these augment the Handlebars object. No need to setup here.
|
// Each of these augment the Handlebars object. No need to setup here.
|
||||||
// (This is done to easily share code between commonjs and browse envs)
|
// (This is done to easily share code between commonjs and browse envs)
|
||||||
@@ -8,7 +8,14 @@ import { template } from "./handlebars/runtime";
|
|||||||
|
|
||||||
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
|
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
|
||||||
var create = function() {
|
var create = function() {
|
||||||
var hb = handlebars();
|
var hb = {},
|
||||||
|
env = new HandlebarsEnvironment();
|
||||||
|
|
||||||
|
// support new environments in global namespace mode
|
||||||
|
hb.HandlebarsEnvironment = HandlebarsEnvironment;
|
||||||
|
|
||||||
|
hb.registerHelper = env.registerHelper.bind(env);
|
||||||
|
hb.registerPartial = env.registerPartial.bind(env);
|
||||||
|
|
||||||
hb.SafeString = SafeString;
|
hb.SafeString = SafeString;
|
||||||
hb.Exception = Exception;
|
hb.Exception = Exception;
|
||||||
|
|||||||
+32
-33
@@ -1,6 +1,6 @@
|
|||||||
/*jshint eqnull: true */
|
/*jshint eqnull: true */
|
||||||
|
|
||||||
import { Exception, extend } from "./utils";
|
import { Exception, extend, isEmpty } from "./utils";
|
||||||
|
|
||||||
var K = function() { return this; };
|
var K = function() { return this; };
|
||||||
|
|
||||||
@@ -14,40 +14,41 @@ export var REVISION_CHANGES = {
|
|||||||
4: '>= 1.0.0'
|
4: '>= 1.0.0'
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Make this a class
|
var toString = Object.prototype.toString,
|
||||||
export function base(helpers, partials) {
|
functionType = '[object Function]',
|
||||||
|
objectType = '[object Object]';
|
||||||
|
|
||||||
var exports = {};
|
export function HandlebarsEnvironment(helpers, partials) {
|
||||||
|
this.helpers = helpers || {};
|
||||||
|
this.partials = partials || {};
|
||||||
|
|
||||||
var helpers = helpers || {};
|
registerDefaultHelpers(this);
|
||||||
var partials = partials || {};
|
}
|
||||||
|
|
||||||
exports.helpers = helpers;
|
HandlebarsEnvironment.prototype = {
|
||||||
exports.partials = partials;
|
constructor: HandlebarsEnvironment,
|
||||||
|
|
||||||
var toString = Object.prototype.toString,
|
registerHelper: function(name, fn, inverse) {
|
||||||
functionType = '[object Function]',
|
|
||||||
objectType = '[object Object]';
|
|
||||||
|
|
||||||
exports.registerHelper = function(name, fn, inverse) {
|
|
||||||
if (toString.call(name) === objectType) {
|
if (toString.call(name) === objectType) {
|
||||||
if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
|
if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
|
||||||
extend(helpers, name);
|
extend(this.helpers, name);
|
||||||
} else {
|
} else {
|
||||||
if (inverse) { fn.not = inverse; }
|
if (inverse) { fn.not = inverse; }
|
||||||
helpers[name] = fn;
|
this.helpers[name] = fn;
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
|
||||||
exports.registerPartial = function(name, str) {
|
registerPartial: function(name, str) {
|
||||||
if (toString.call(name) === objectType) {
|
if (toString.call(name) === objectType) {
|
||||||
extend(partials, name);
|
extend(this.partials, name);
|
||||||
} else {
|
} else {
|
||||||
partials[name] = str;
|
this.partials[name] = str;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
exports.registerHelper('helperMissing', function(arg) {
|
function registerDefaultHelpers(instance) {
|
||||||
|
instance.registerHelper('helperMissing', function(arg) {
|
||||||
if(arguments.length === 2) {
|
if(arguments.length === 2) {
|
||||||
return undefined;
|
return undefined;
|
||||||
} else {
|
} else {
|
||||||
@@ -55,7 +56,7 @@ export function base(helpers, partials) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('blockHelperMissing', function(context, options) {
|
instance.registerHelper('blockHelperMissing', function(context, options) {
|
||||||
var inverse = options.inverse || function() {}, fn = options.fn;
|
var inverse = options.inverse || function() {}, fn = options.fn;
|
||||||
|
|
||||||
var type = toString.call(context);
|
var type = toString.call(context);
|
||||||
@@ -68,7 +69,7 @@ export function base(helpers, partials) {
|
|||||||
return inverse(this);
|
return inverse(this);
|
||||||
} else if(type === "[object Array]") {
|
} else if(type === "[object Array]") {
|
||||||
if(context.length > 0) {
|
if(context.length > 0) {
|
||||||
return Handlebars.helpers.each(context, options);
|
return instance.helpers.each(context, options);
|
||||||
} else {
|
} else {
|
||||||
return inverse(this);
|
return inverse(this);
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,7 @@ export function base(helpers, partials) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('each', function(context, options) {
|
instance.registerHelper('each', function(context, options) {
|
||||||
var fn = options.fn, inverse = options.inverse;
|
var fn = options.fn, inverse = options.inverse;
|
||||||
var i = 0, ret = "", data;
|
var i = 0, ret = "", data;
|
||||||
|
|
||||||
@@ -112,34 +113,32 @@ export function base(helpers, partials) {
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('if', function(conditional, options) {
|
instance.registerHelper('if', function(conditional, options) {
|
||||||
var type = toString.call(conditional);
|
var type = toString.call(conditional);
|
||||||
if(type === functionType) { conditional = conditional.call(this); }
|
if(type === functionType) { conditional = conditional.call(this); }
|
||||||
|
|
||||||
if(!conditional || Handlebars.Utils.isEmpty(conditional)) {
|
if(!conditional || isEmpty(conditional)) {
|
||||||
return options.inverse(this);
|
return options.inverse(this);
|
||||||
} else {
|
} else {
|
||||||
return options.fn(this);
|
return options.fn(this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('unless', function(conditional, options) {
|
instance.registerHelper('unless', function(conditional, options) {
|
||||||
return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
|
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('with', function(context, options) {
|
instance.registerHelper('with', function(context, options) {
|
||||||
var type = toString.call(context);
|
var type = toString.call(context);
|
||||||
if(type === functionType) { context = context.call(this); }
|
if(type === functionType) { context = context.call(this); }
|
||||||
|
|
||||||
if (!Handlebars.Utils.isEmpty(context)) return options.fn(context);
|
if (!isEmpty(context)) return options.fn(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.registerHelper('log', function(context, options) {
|
instance.registerHelper('log', function(context, options) {
|
||||||
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
|
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
|
||||||
Handlebars.log(level, context);
|
Handlebars.log(level, context);
|
||||||
});
|
});
|
||||||
|
|
||||||
return exports;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var levels = {
|
var levels = {
|
||||||
|
|||||||
@@ -443,17 +443,17 @@ export function compile(input, options) {
|
|||||||
|
|
||||||
var compiled;
|
var compiled;
|
||||||
|
|
||||||
function compile() {
|
function compileInput() {
|
||||||
var ast = parse(input);
|
var ast = parse(input);
|
||||||
var environment = new Compiler().compile(ast, options);
|
var environment = new Compiler().compile(ast, options);
|
||||||
var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
|
var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
|
||||||
return template(templateSpec);
|
return template(templateSpec, options.env || Handlebars, compile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template is only compiled on first use and cached after that point.
|
// Template is only compiled on first use and cached after that point.
|
||||||
return function(context, options) {
|
return function(context, options) {
|
||||||
if (!compiled) {
|
if (!compiled) {
|
||||||
compiled = compile();
|
compiled = compileInput();
|
||||||
}
|
}
|
||||||
return compiled.call(this, context, options);
|
return compiled.call(this, context, options);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,17 +3,14 @@ import { COMPILER_REVISION, REVISION_CHANGES } from "./base";
|
|||||||
|
|
||||||
// TODO: Remove this line and break up compilePartial
|
// TODO: Remove this line and break up compilePartial
|
||||||
|
|
||||||
export function template(templateSpec, Hbars) {
|
export function template(templateSpec, Hbars, compile) {
|
||||||
// TODO: Make this less global
|
if (compile) {
|
||||||
Hbars = Hbars || Handlebars;
|
|
||||||
|
|
||||||
if (Hbars.compile) {
|
|
||||||
var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
|
var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
|
||||||
var result = invokePartial.apply(this, arguments);
|
var result = invokePartial.apply(this, arguments);
|
||||||
if (result) { return result; }
|
if (result) { return result; }
|
||||||
|
|
||||||
var options = { helpers: helpers, partials: partials, data: data };
|
var options = { helpers: helpers, partials: partials, data: data };
|
||||||
partials[name] = Hbars.compile(partial, { data: data !== undefined });
|
partials[name] = compile(partial, { data: data !== undefined });
|
||||||
return partials[name](context, options);
|
return partials[name](context, options);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -24,6 +21,10 @@ export function template(templateSpec, Hbars) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Hbars) {
|
||||||
|
throw new Error("YUNO HANDLEBARS");
|
||||||
|
}
|
||||||
|
|
||||||
// Just add water
|
// Just add water
|
||||||
var container = {
|
var container = {
|
||||||
escapeExpression: escapeExpression,
|
escapeExpression: escapeExpression,
|
||||||
@@ -56,9 +57,6 @@ export function template(templateSpec, Hbars) {
|
|||||||
return function(context, options) {
|
return function(context, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
Hbars = Hbars || require("handlebars");
|
|
||||||
|
|
||||||
// TODO: Why does templateSpec require a reference to the global Handlebars?
|
|
||||||
var result = templateSpec.call(container, Hbars, context, options.helpers, options.partials, options.data);
|
var result = templateSpec.call(container, Hbars, context, options.helpers, options.partials, options.data);
|
||||||
|
|
||||||
var compilerInfo = container.compilerInfo || [],
|
var compilerInfo = container.compilerInfo || [],
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
global.handlebarsEnv = null;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
global.handlebarsEnv = new Handlebars.HandlebarsEnvironment();
|
||||||
|
});
|
||||||
|
|
||||||
describe("basic context", function() {
|
describe("basic context", function() {
|
||||||
it("most basic", function() {
|
it("most basic", function() {
|
||||||
shouldCompileTo("{{foo}}", { foo: "foo" }, "foo");
|
shouldCompileTo("{{foo}}", { foo: "foo" }, "foo");
|
||||||
|
|||||||
Vendored
+5
-3
@@ -3,12 +3,14 @@ require('./common');
|
|||||||
global.Handlebars = require('../../zomg/lib/handlebars');
|
global.Handlebars = require('../../zomg/lib/handlebars');
|
||||||
|
|
||||||
global.CompilerContext = {
|
global.CompilerContext = {
|
||||||
compile: function(template, options) {
|
compile: function(template, options, env) {
|
||||||
|
env = env || handlebarsEnv;
|
||||||
var templateSpec = Handlebars.precompile(template, options);
|
var templateSpec = Handlebars.precompile(template, options);
|
||||||
console.log(templateSpec);
|
return Handlebars.template(eval('(' + templateSpec + ')'), env);
|
||||||
return Handlebars.template(eval('(' + templateSpec + ')'));
|
|
||||||
},
|
},
|
||||||
compileWithPartial: function(template, options) {
|
compileWithPartial: function(template, options) {
|
||||||
|
options = options || {};
|
||||||
|
options.env = handlebarsEnv;
|
||||||
return Handlebars.compile(template, options);
|
return Handlebars.compile(template, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Vendored
+3
-3
@@ -5,11 +5,11 @@ global.Handlebars = require('../../dist/handlebars.runtime');
|
|||||||
var compiler = require('../../lib/handlebars');
|
var compiler = require('../../lib/handlebars');
|
||||||
|
|
||||||
global.CompilerContext = {
|
global.CompilerContext = {
|
||||||
compile: function(template, options) {
|
compile: function(template, options, env) {
|
||||||
var templateSpec = compiler.precompile(template, options);
|
var templateSpec = compiler.precompile(template, options);
|
||||||
return Handlebars.template(eval('(' + templateSpec + ')'));
|
return Handlebars.template(eval('(' + templateSpec + ')'), env);
|
||||||
},
|
},
|
||||||
compileWithPartial: function(template, options) {
|
compileWithPartial: function(template, options, env) {
|
||||||
return compiler.compile(template, options);
|
return compiler.compile(template, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-8
@@ -176,15 +176,12 @@ describe('helpers', function() {
|
|||||||
var helpers = Handlebars.helpers;
|
var helpers = Handlebars.helpers;
|
||||||
try {
|
try {
|
||||||
Handlebars.helpers = {};
|
Handlebars.helpers = {};
|
||||||
Handlebars.registerHelper('if', helpers['if']);
|
|
||||||
Handlebars.registerHelper('world', function() { return "world!"; });
|
|
||||||
Handlebars.registerHelper('test_helper', function() { return 'found it!'; });
|
|
||||||
|
|
||||||
//Handlebars.registerHelper({
|
Handlebars.registerHelper({
|
||||||
//'if': helpers['if'],
|
'if': helpers['if'],
|
||||||
//world: function() { return "world!"; },
|
world: function() { return "world!"; },
|
||||||
//test_helper: function() { return 'found it!'; }
|
test_helper: function() { return 'found it!'; }
|
||||||
//});
|
});
|
||||||
|
|
||||||
shouldCompileTo(
|
shouldCompileTo(
|
||||||
"{{test_helper}} {{#if cruel}}Goodbye {{cruel}} {{world}}!{{/if}}",
|
"{{test_helper}} {{#if cruel}}Goodbye {{cruel}} {{world}}!{{/if}}",
|
||||||
|
|||||||
Reference in New Issue
Block a user