6f22ec1e01
This only worked when a function returned a function, which was then evaluated. This seems like unexpected behavior so this was dropped.
229 lines
6.1 KiB
JavaScript
229 lines
6.1 KiB
JavaScript
module Utils from "./utils";
|
|
import Exception from "./exception";
|
|
|
|
export var VERSION = "2.0.0-alpha.4";
|
|
export var COMPILER_REVISION = 5;
|
|
|
|
export var REVISION_CHANGES = {
|
|
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
|
|
2: '== 1.0.0-rc.3',
|
|
3: '== 1.0.0-rc.4',
|
|
4: '== 1.x.x',
|
|
5: '>= 2.0.0'
|
|
};
|
|
|
|
var isArray = Utils.isArray,
|
|
isFunction = Utils.isFunction,
|
|
toString = Utils.toString,
|
|
objectType = '[object Object]';
|
|
|
|
export function HandlebarsEnvironment(helpers, partials) {
|
|
this.helpers = helpers || {};
|
|
this.partials = partials || {};
|
|
|
|
registerDefaultHelpers(this);
|
|
}
|
|
|
|
HandlebarsEnvironment.prototype = {
|
|
constructor: HandlebarsEnvironment,
|
|
|
|
logger: logger,
|
|
log: log,
|
|
|
|
registerHelper: function(name, fn) {
|
|
if (toString.call(name) === objectType) {
|
|
if (fn) { throw new Exception('Arg not supported with multiple helpers'); }
|
|
Utils.extend(this.helpers, name);
|
|
} else {
|
|
this.helpers[name] = fn;
|
|
}
|
|
},
|
|
unregisterHelper: function(name) {
|
|
delete this.helpers[name];
|
|
},
|
|
|
|
registerPartial: function(name, str) {
|
|
if (toString.call(name) === objectType) {
|
|
Utils.extend(this.partials, name);
|
|
} else {
|
|
this.partials[name] = str;
|
|
}
|
|
},
|
|
unregisterPartial: function(name) {
|
|
delete this.partials[name];
|
|
}
|
|
};
|
|
|
|
function registerDefaultHelpers(instance) {
|
|
instance.registerHelper('helperMissing', function(/* [args, ]options */) {
|
|
if(arguments.length === 1) {
|
|
// A missing field in a {{foo}} constuct.
|
|
return undefined;
|
|
} else {
|
|
// Someone is actually trying to call something, blow up.
|
|
throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'");
|
|
}
|
|
});
|
|
|
|
instance.registerHelper('blockHelperMissing', function(context, options) {
|
|
var inverse = options.inverse,
|
|
fn = options.fn;
|
|
|
|
if(context === true) {
|
|
return fn(this);
|
|
} else if(context === false || context == null) {
|
|
return inverse(this);
|
|
} else if (isArray(context)) {
|
|
if(context.length > 0) {
|
|
if (options.ids) {
|
|
options.ids = [options.name];
|
|
}
|
|
|
|
return instance.helpers.each(context, options);
|
|
} else {
|
|
return inverse(this);
|
|
}
|
|
} else {
|
|
if (options.data && options.ids) {
|
|
var data = createFrame(options.data);
|
|
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
|
|
options = {data: data};
|
|
}
|
|
|
|
return fn(context, options);
|
|
}
|
|
});
|
|
|
|
instance.registerHelper('each', function(context, options) {
|
|
if (!options) {
|
|
throw new Exception('Must pass iterator to #each');
|
|
}
|
|
|
|
var fn = options.fn, inverse = options.inverse;
|
|
var i = 0, ret = "", data;
|
|
|
|
var contextPath;
|
|
if (options.data && options.ids) {
|
|
contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
|
|
}
|
|
|
|
if (isFunction(context)) { context = context.call(this); }
|
|
|
|
if (options.data) {
|
|
data = createFrame(options.data);
|
|
}
|
|
|
|
if(context && typeof context === 'object') {
|
|
if (isArray(context)) {
|
|
for(var j = context.length; i<j; i++) {
|
|
if (data) {
|
|
data.index = i;
|
|
data.first = (i === 0);
|
|
data.last = (i === (context.length-1));
|
|
|
|
if (contextPath) {
|
|
data.contextPath = contextPath + i;
|
|
}
|
|
}
|
|
ret = ret + fn(context[i], { data: data });
|
|
}
|
|
} else {
|
|
for(var key in context) {
|
|
if(context.hasOwnProperty(key)) {
|
|
if(data) {
|
|
data.key = key;
|
|
data.index = i;
|
|
data.first = (i === 0);
|
|
|
|
if (contextPath) {
|
|
data.contextPath = contextPath + key;
|
|
}
|
|
}
|
|
ret = ret + fn(context[key], {data: data});
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(i === 0){
|
|
ret = inverse(this);
|
|
}
|
|
|
|
return ret;
|
|
});
|
|
|
|
instance.registerHelper('if', function(conditional, options) {
|
|
if (isFunction(conditional)) { conditional = conditional.call(this); }
|
|
|
|
// Default behavior is to render the positive path if the value is truthy and not empty.
|
|
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
|
|
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
|
|
if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
|
|
return options.inverse(this);
|
|
} else {
|
|
return options.fn(this);
|
|
}
|
|
});
|
|
|
|
instance.registerHelper('unless', function(conditional, options) {
|
|
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
|
|
});
|
|
|
|
instance.registerHelper('with', function(context, options) {
|
|
if (isFunction(context)) { context = context.call(this); }
|
|
|
|
var fn = options.fn;
|
|
|
|
if (!Utils.isEmpty(context)) {
|
|
if (options.data && options.ids) {
|
|
var data = createFrame(options.data);
|
|
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
|
|
options = {data:data};
|
|
}
|
|
|
|
return fn(context, options);
|
|
} else {
|
|
return options.inverse(this);
|
|
}
|
|
});
|
|
|
|
instance.registerHelper('log', function(context, options) {
|
|
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
|
|
instance.log(level, context);
|
|
});
|
|
|
|
instance.registerHelper('lookup', function(obj, field, options) {
|
|
return obj && obj[field];
|
|
});
|
|
}
|
|
|
|
export var logger = {
|
|
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
|
|
|
|
// State enum
|
|
DEBUG: 0,
|
|
INFO: 1,
|
|
WARN: 2,
|
|
ERROR: 3,
|
|
level: 3,
|
|
|
|
// can be overridden in the host environment
|
|
log: function(level, obj) {
|
|
if (logger.level <= level) {
|
|
var method = logger.methodMap[level];
|
|
if (typeof console !== 'undefined' && console[method]) {
|
|
console[method].call(console, obj);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
export function log(level, obj) { logger.log(level, obj); }
|
|
|
|
export var createFrame = function(object) {
|
|
var frame = Utils.extend({}, object);
|
|
frame._parent = object;
|
|
return frame;
|
|
};
|