summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/handlebars/base.js179
-rw-r--r--lib/handlebars/helpers.js17
-rw-r--r--lib/handlebars/helpers/block-helper-missing.js32
-rw-r--r--lib/handlebars/helpers/each.js77
-rw-r--r--lib/handlebars/helpers/helper-missing.js13
-rw-r--r--lib/handlebars/helpers/if.js20
-rw-r--r--lib/handlebars/helpers/log.js6
-rw-r--r--lib/handlebars/helpers/lookup.js5
-rw-r--r--lib/handlebars/helpers/with.js24
-rw-r--r--lib/handlebars/utils.js6
10 files changed, 206 insertions, 173 deletions
diff --git a/lib/handlebars/base.js b/lib/handlebars/base.js
index 756fb77..cc3d2fa 100644
--- a/lib/handlebars/base.js
+++ b/lib/handlebars/base.js
@@ -1,5 +1,6 @@
-import * as Utils from './utils';
+import {createFrame, extend, toString} from './utils';
import Exception from './exception';
+import {registerDefaultHelpers} from './helpers';
export const VERSION = '3.0.1';
export const COMPILER_REVISION = 6;
@@ -13,10 +14,7 @@ export const REVISION_CHANGES = {
6: '>= 2.0.0-beta.1'
};
-const isArray = Utils.isArray,
- isFunction = Utils.isFunction,
- toString = Utils.toString,
- objectType = '[object Object]';
+const objectType = '[object Object]';
export function HandlebarsEnvironment(helpers, partials) {
this.helpers = helpers || {};
@@ -34,7 +32,7 @@ HandlebarsEnvironment.prototype = {
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);
+ extend(this.helpers, name);
} else {
this.helpers[name] = fn;
}
@@ -45,7 +43,7 @@ HandlebarsEnvironment.prototype = {
registerPartial: function(name, partial) {
if (toString.call(name) === objectType) {
- Utils.extend(this.partials, name);
+ extend(this.partials, name);
} else {
if (typeof partial === 'undefined') {
throw new Exception('Attempting to register a partial as undefined');
@@ -58,167 +56,6 @@ HandlebarsEnvironment.prototype = {
}
};
-function registerDefaultHelpers(instance) {
- instance.registerHelper('helperMissing', function(/* [args, ]options */) {
- if (arguments.length === 1) {
- // A missing field in a {{foo}} construct.
- 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) {
- let 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) {
- let 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');
- }
-
- let fn = options.fn,
- inverse = options.inverse,
- i = 0,
- ret = '',
- data,
- 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);
- }
-
- function execIteration(field, index, last) {
- if (data) {
- data.key = field;
- data.index = index;
- data.first = index === 0;
- data.last = !!last;
-
- if (contextPath) {
- data.contextPath = contextPath + field;
- }
- }
-
- ret = ret + fn(context[field], {
- data: data,
- blockParams: Utils.blockParams([context[field], field], [contextPath + field, null])
- });
- }
-
- if (context && typeof context === 'object') {
- if (isArray(context)) {
- for (let j = context.length; i < j; i++) {
- execIteration(i, i, i === context.length - 1);
- }
- } else {
- let priorKey;
-
- for (let key in context) {
- if (context.hasOwnProperty(key)) {
- // We're running the iterations one step out of sync so we can detect
- // the last iteration without have to scan the object twice and create
- // an itermediate keys array.
- if (priorKey !== undefined) {
- execIteration(priorKey, i - 1);
- }
- priorKey = key;
- i++;
- }
- }
- if (priorKey) {
- execIteration(priorKey, i - 1, true);
- }
- }
- }
-
- 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); }
-
- let fn = options.fn;
-
- if (!Utils.isEmpty(context)) {
- let data = options.data;
- if (options.data && options.ids) {
- data = createFrame(options.data);
- data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
- }
-
- return fn(context, {
- data: data,
- blockParams: Utils.blockParams([context], [data && data.contextPath])
- });
- } else {
- return options.inverse(this);
- }
- });
-
- instance.registerHelper('log', function(message, options) {
- let level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
- instance.log(level, message);
- });
-
- instance.registerHelper('lookup', function(obj, field) {
- return obj && obj[field];
- });
-}
-
export let logger = {
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
@@ -240,8 +77,4 @@ export let logger = {
export let log = logger.log;
-export function createFrame(object) {
- let frame = Utils.extend({}, object);
- frame._parent = object;
- return frame;
-}
+export {createFrame};
diff --git a/lib/handlebars/helpers.js b/lib/handlebars/helpers.js
new file mode 100644
index 0000000..7a4365a
--- /dev/null
+++ b/lib/handlebars/helpers.js
@@ -0,0 +1,17 @@
+import registerBlockHelperMissing from './helpers/block-helper-missing';
+import registerEach from './helpers/each';
+import registerHelperMissing from './helpers/helper-missing';
+import registerIf from './helpers/if';
+import registerLog from './helpers/log';
+import registerLookup from './helpers/lookup';
+import registerWith from './helpers/with';
+
+export function registerDefaultHelpers(instance) {
+ registerBlockHelperMissing(instance);
+ registerEach(instance);
+ registerHelperMissing(instance);
+ registerIf(instance);
+ registerLog(instance);
+ registerLookup(instance);
+ registerWith(instance);
+}
diff --git a/lib/handlebars/helpers/block-helper-missing.js b/lib/handlebars/helpers/block-helper-missing.js
new file mode 100644
index 0000000..6639ddb
--- /dev/null
+++ b/lib/handlebars/helpers/block-helper-missing.js
@@ -0,0 +1,32 @@
+import {appendContextPath, createFrame, isArray} from '../utils';
+
+export default function(instance) {
+ instance.registerHelper('blockHelperMissing', function(context, options) {
+ let 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) {
+ let data = createFrame(options.data);
+ data.contextPath = appendContextPath(options.data.contextPath, options.name);
+ options = {data: data};
+ }
+
+ return fn(context, options);
+ }
+ });
+}
diff --git a/lib/handlebars/helpers/each.js b/lib/handlebars/helpers/each.js
new file mode 100644
index 0000000..9fc5a09
--- /dev/null
+++ b/lib/handlebars/helpers/each.js
@@ -0,0 +1,77 @@
+import {appendContextPath, blockParams, createFrame, isArray, isFunction} from '../utils';
+import Exception from '../exception';
+
+export default function(instance) {
+ instance.registerHelper('each', function(context, options) {
+ if (!options) {
+ throw new Exception('Must pass iterator to #each');
+ }
+
+ let fn = options.fn,
+ inverse = options.inverse,
+ i = 0,
+ ret = '',
+ data,
+ contextPath;
+
+ if (options.data && options.ids) {
+ contextPath = appendContextPath(options.data.contextPath, options.ids[0]) + '.';
+ }
+
+ if (isFunction(context)) { context = context.call(this); }
+
+ if (options.data) {
+ data = createFrame(options.data);
+ }
+
+ function execIteration(field, index, last) {
+ if (data) {
+ data.key = field;
+ data.index = index;
+ data.first = index === 0;
+ data.last = !!last;
+
+ if (contextPath) {
+ data.contextPath = contextPath + field;
+ }
+ }
+
+ ret = ret + fn(context[field], {
+ data: data,
+ blockParams: blockParams([context[field], field], [contextPath + field, null])
+ });
+ }
+
+ if (context && typeof context === 'object') {
+ if (isArray(context)) {
+ for (let j = context.length; i < j; i++) {
+ execIteration(i, i, i === context.length - 1);
+ }
+ } else {
+ let priorKey;
+
+ for (let key in context) {
+ if (context.hasOwnProperty(key)) {
+ // We're running the iterations one step out of sync so we can detect
+ // the last iteration without have to scan the object twice and create
+ // an itermediate keys array.
+ if (priorKey !== undefined) {
+ execIteration(priorKey, i - 1);
+ }
+ priorKey = key;
+ i++;
+ }
+ }
+ if (priorKey) {
+ execIteration(priorKey, i - 1, true);
+ }
+ }
+ }
+
+ if (i === 0) {
+ ret = inverse(this);
+ }
+
+ return ret;
+ });
+}
diff --git a/lib/handlebars/helpers/helper-missing.js b/lib/handlebars/helpers/helper-missing.js
new file mode 100644
index 0000000..ec32e82
--- /dev/null
+++ b/lib/handlebars/helpers/helper-missing.js
@@ -0,0 +1,13 @@
+import Exception from '../exception';
+
+export default function(instance) {
+ instance.registerHelper('helperMissing', function(/* [args, ]options */) {
+ if (arguments.length === 1) {
+ // A missing field in a {{foo}} construct.
+ return undefined;
+ } else {
+ // Someone is actually trying to call something, blow up.
+ throw new Exception('Missing helper: "' + arguments[arguments.length - 1].name + '"');
+ }
+ });
+}
diff --git a/lib/handlebars/helpers/if.js b/lib/handlebars/helpers/if.js
new file mode 100644
index 0000000..11d08df
--- /dev/null
+++ b/lib/handlebars/helpers/if.js
@@ -0,0 +1,20 @@
+import {isEmpty, isFunction} from '../utils';
+
+export default function(instance) {
+ 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) || 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});
+ });
+}
diff --git a/lib/handlebars/helpers/log.js b/lib/handlebars/helpers/log.js
new file mode 100644
index 0000000..ab83604
--- /dev/null
+++ b/lib/handlebars/helpers/log.js
@@ -0,0 +1,6 @@
+export default function(instance) {
+ instance.registerHelper('log', function(message, options) {
+ let level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
+ instance.log(level, message);
+ });
+}
diff --git a/lib/handlebars/helpers/lookup.js b/lib/handlebars/helpers/lookup.js
new file mode 100644
index 0000000..a52e77a
--- /dev/null
+++ b/lib/handlebars/helpers/lookup.js
@@ -0,0 +1,5 @@
+export default function(instance) {
+ instance.registerHelper('lookup', function(obj, field) {
+ return obj && obj[field];
+ });
+}
diff --git a/lib/handlebars/helpers/with.js b/lib/handlebars/helpers/with.js
new file mode 100644
index 0000000..7418cd0
--- /dev/null
+++ b/lib/handlebars/helpers/with.js
@@ -0,0 +1,24 @@
+import {appendContextPath, blockParams, createFrame, isEmpty, isFunction} from '../utils';
+
+export default function(instance) {
+ instance.registerHelper('with', function(context, options) {
+ if (isFunction(context)) { context = context.call(this); }
+
+ let fn = options.fn;
+
+ if (!isEmpty(context)) {
+ let data = options.data;
+ if (options.data && options.ids) {
+ data = createFrame(options.data);
+ data.contextPath = appendContextPath(options.data.contextPath, options.ids[0]);
+ }
+
+ return fn(context, {
+ data: data,
+ blockParams: blockParams([context], [data && data.contextPath])
+ });
+ } else {
+ return options.inverse(this);
+ }
+ });
+}
diff --git a/lib/handlebars/utils.js b/lib/handlebars/utils.js
index c522394..c7a5762 100644
--- a/lib/handlebars/utils.js
+++ b/lib/handlebars/utils.js
@@ -91,6 +91,12 @@ export function isEmpty(value) {
}
}
+export function createFrame(object) {
+ let frame = extend({}, object);
+ frame._parent = object;
+ return frame;
+}
+
export function blockParams(params, ids) {
params.path = ids;
return params;