Skip to content

Commit 15b55a3

Browse files
committed
Move helpers into separate modules
1 parent 231a8d7 commit 15b55a3

File tree

10 files changed

+206
-173
lines changed

10 files changed

+206
-173
lines changed

lib/handlebars/base.js

+6-173
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import * as Utils from './utils';
1+
import {createFrame, extend, toString} from './utils';
22
import Exception from './exception';
3+
import {registerDefaultHelpers} from './helpers';
34

45
export const VERSION = '3.0.1';
56
export const COMPILER_REVISION = 6;
@@ -13,10 +14,7 @@ export const REVISION_CHANGES = {
1314
6: '>= 2.0.0-beta.1'
1415
};
1516

16-
const isArray = Utils.isArray,
17-
isFunction = Utils.isFunction,
18-
toString = Utils.toString,
19-
objectType = '[object Object]';
17+
const objectType = '[object Object]';
2018

2119
export function HandlebarsEnvironment(helpers, partials) {
2220
this.helpers = helpers || {};
@@ -34,7 +32,7 @@ HandlebarsEnvironment.prototype = {
3432
registerHelper: function(name, fn) {
3533
if (toString.call(name) === objectType) {
3634
if (fn) { throw new Exception('Arg not supported with multiple helpers'); }
37-
Utils.extend(this.helpers, name);
35+
extend(this.helpers, name);
3836
} else {
3937
this.helpers[name] = fn;
4038
}
@@ -45,7 +43,7 @@ HandlebarsEnvironment.prototype = {
4543

4644
registerPartial: function(name, partial) {
4745
if (toString.call(name) === objectType) {
48-
Utils.extend(this.partials, name);
46+
extend(this.partials, name);
4947
} else {
5048
if (typeof partial === 'undefined') {
5149
throw new Exception('Attempting to register a partial as undefined');
@@ -58,167 +56,6 @@ HandlebarsEnvironment.prototype = {
5856
}
5957
};
6058

61-
function registerDefaultHelpers(instance) {
62-
instance.registerHelper('helperMissing', function(/* [args, ]options */) {
63-
if (arguments.length === 1) {
64-
// A missing field in a {{foo}} construct.
65-
return undefined;
66-
} else {
67-
// Someone is actually trying to call something, blow up.
68-
throw new Exception('Missing helper: "' + arguments[arguments.length - 1].name + '"');
69-
}
70-
});
71-
72-
instance.registerHelper('blockHelperMissing', function(context, options) {
73-
let inverse = options.inverse,
74-
fn = options.fn;
75-
76-
if (context === true) {
77-
return fn(this);
78-
} else if (context === false || context == null) {
79-
return inverse(this);
80-
} else if (isArray(context)) {
81-
if (context.length > 0) {
82-
if (options.ids) {
83-
options.ids = [options.name];
84-
}
85-
86-
return instance.helpers.each(context, options);
87-
} else {
88-
return inverse(this);
89-
}
90-
} else {
91-
if (options.data && options.ids) {
92-
let data = createFrame(options.data);
93-
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
94-
options = {data: data};
95-
}
96-
97-
return fn(context, options);
98-
}
99-
});
100-
101-
instance.registerHelper('each', function(context, options) {
102-
if (!options) {
103-
throw new Exception('Must pass iterator to #each');
104-
}
105-
106-
let fn = options.fn,
107-
inverse = options.inverse,
108-
i = 0,
109-
ret = '',
110-
data,
111-
contextPath;
112-
113-
if (options.data && options.ids) {
114-
contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
115-
}
116-
117-
if (isFunction(context)) { context = context.call(this); }
118-
119-
if (options.data) {
120-
data = createFrame(options.data);
121-
}
122-
123-
function execIteration(field, index, last) {
124-
if (data) {
125-
data.key = field;
126-
data.index = index;
127-
data.first = index === 0;
128-
data.last = !!last;
129-
130-
if (contextPath) {
131-
data.contextPath = contextPath + field;
132-
}
133-
}
134-
135-
ret = ret + fn(context[field], {
136-
data: data,
137-
blockParams: Utils.blockParams([context[field], field], [contextPath + field, null])
138-
});
139-
}
140-
141-
if (context && typeof context === 'object') {
142-
if (isArray(context)) {
143-
for (let j = context.length; i < j; i++) {
144-
execIteration(i, i, i === context.length - 1);
145-
}
146-
} else {
147-
let priorKey;
148-
149-
for (let key in context) {
150-
if (context.hasOwnProperty(key)) {
151-
// We're running the iterations one step out of sync so we can detect
152-
// the last iteration without have to scan the object twice and create
153-
// an itermediate keys array.
154-
if (priorKey !== undefined) {
155-
execIteration(priorKey, i - 1);
156-
}
157-
priorKey = key;
158-
i++;
159-
}
160-
}
161-
if (priorKey) {
162-
execIteration(priorKey, i - 1, true);
163-
}
164-
}
165-
}
166-
167-
if (i === 0) {
168-
ret = inverse(this);
169-
}
170-
171-
return ret;
172-
});
173-
174-
instance.registerHelper('if', function(conditional, options) {
175-
if (isFunction(conditional)) { conditional = conditional.call(this); }
176-
177-
// Default behavior is to render the positive path if the value is truthy and not empty.
178-
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
179-
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
180-
if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
181-
return options.inverse(this);
182-
} else {
183-
return options.fn(this);
184-
}
185-
});
186-
187-
instance.registerHelper('unless', function(conditional, options) {
188-
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
189-
});
190-
191-
instance.registerHelper('with', function(context, options) {
192-
if (isFunction(context)) { context = context.call(this); }
193-
194-
let fn = options.fn;
195-
196-
if (!Utils.isEmpty(context)) {
197-
let data = options.data;
198-
if (options.data && options.ids) {
199-
data = createFrame(options.data);
200-
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
201-
}
202-
203-
return fn(context, {
204-
data: data,
205-
blockParams: Utils.blockParams([context], [data && data.contextPath])
206-
});
207-
} else {
208-
return options.inverse(this);
209-
}
210-
});
211-
212-
instance.registerHelper('log', function(message, options) {
213-
let level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
214-
instance.log(level, message);
215-
});
216-
217-
instance.registerHelper('lookup', function(obj, field) {
218-
return obj && obj[field];
219-
});
220-
}
221-
22259
export let logger = {
22360
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
22461

@@ -240,8 +77,4 @@ export let logger = {
24077

24178
export let log = logger.log;
24279

243-
export function createFrame(object) {
244-
let frame = Utils.extend({}, object);
245-
frame._parent = object;
246-
return frame;
247-
}
80+
export {createFrame};

lib/handlebars/helpers.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import registerBlockHelperMissing from './helpers/block-helper-missing';
2+
import registerEach from './helpers/each';
3+
import registerHelperMissing from './helpers/helper-missing';
4+
import registerIf from './helpers/if';
5+
import registerLog from './helpers/log';
6+
import registerLookup from './helpers/lookup';
7+
import registerWith from './helpers/with';
8+
9+
export function registerDefaultHelpers(instance) {
10+
registerBlockHelperMissing(instance);
11+
registerEach(instance);
12+
registerHelperMissing(instance);
13+
registerIf(instance);
14+
registerLog(instance);
15+
registerLookup(instance);
16+
registerWith(instance);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {appendContextPath, createFrame, isArray} from '../utils';
2+
3+
export default function(instance) {
4+
instance.registerHelper('blockHelperMissing', function(context, options) {
5+
let inverse = options.inverse,
6+
fn = options.fn;
7+
8+
if (context === true) {
9+
return fn(this);
10+
} else if (context === false || context == null) {
11+
return inverse(this);
12+
} else if (isArray(context)) {
13+
if (context.length > 0) {
14+
if (options.ids) {
15+
options.ids = [options.name];
16+
}
17+
18+
return instance.helpers.each(context, options);
19+
} else {
20+
return inverse(this);
21+
}
22+
} else {
23+
if (options.data && options.ids) {
24+
let data = createFrame(options.data);
25+
data.contextPath = appendContextPath(options.data.contextPath, options.name);
26+
options = {data: data};
27+
}
28+
29+
return fn(context, options);
30+
}
31+
});
32+
}

lib/handlebars/helpers/each.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import {appendContextPath, blockParams, createFrame, isArray, isFunction} from '../utils';
2+
import Exception from '../exception';
3+
4+
export default function(instance) {
5+
instance.registerHelper('each', function(context, options) {
6+
if (!options) {
7+
throw new Exception('Must pass iterator to #each');
8+
}
9+
10+
let fn = options.fn,
11+
inverse = options.inverse,
12+
i = 0,
13+
ret = '',
14+
data,
15+
contextPath;
16+
17+
if (options.data && options.ids) {
18+
contextPath = appendContextPath(options.data.contextPath, options.ids[0]) + '.';
19+
}
20+
21+
if (isFunction(context)) { context = context.call(this); }
22+
23+
if (options.data) {
24+
data = createFrame(options.data);
25+
}
26+
27+
function execIteration(field, index, last) {
28+
if (data) {
29+
data.key = field;
30+
data.index = index;
31+
data.first = index === 0;
32+
data.last = !!last;
33+
34+
if (contextPath) {
35+
data.contextPath = contextPath + field;
36+
}
37+
}
38+
39+
ret = ret + fn(context[field], {
40+
data: data,
41+
blockParams: blockParams([context[field], field], [contextPath + field, null])
42+
});
43+
}
44+
45+
if (context && typeof context === 'object') {
46+
if (isArray(context)) {
47+
for (let j = context.length; i < j; i++) {
48+
execIteration(i, i, i === context.length - 1);
49+
}
50+
} else {
51+
let priorKey;
52+
53+
for (let key in context) {
54+
if (context.hasOwnProperty(key)) {
55+
// We're running the iterations one step out of sync so we can detect
56+
// the last iteration without have to scan the object twice and create
57+
// an itermediate keys array.
58+
if (priorKey !== undefined) {
59+
execIteration(priorKey, i - 1);
60+
}
61+
priorKey = key;
62+
i++;
63+
}
64+
}
65+
if (priorKey) {
66+
execIteration(priorKey, i - 1, true);
67+
}
68+
}
69+
}
70+
71+
if (i === 0) {
72+
ret = inverse(this);
73+
}
74+
75+
return ret;
76+
});
77+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Exception from '../exception';
2+
3+
export default function(instance) {
4+
instance.registerHelper('helperMissing', function(/* [args, ]options */) {
5+
if (arguments.length === 1) {
6+
// A missing field in a {{foo}} construct.
7+
return undefined;
8+
} else {
9+
// Someone is actually trying to call something, blow up.
10+
throw new Exception('Missing helper: "' + arguments[arguments.length - 1].name + '"');
11+
}
12+
});
13+
}

lib/handlebars/helpers/if.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {isEmpty, isFunction} from '../utils';
2+
3+
export default function(instance) {
4+
instance.registerHelper('if', function(conditional, options) {
5+
if (isFunction(conditional)) { conditional = conditional.call(this); }
6+
7+
// Default behavior is to render the positive path if the value is truthy and not empty.
8+
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
9+
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
10+
if ((!options.hash.includeZero && !conditional) || isEmpty(conditional)) {
11+
return options.inverse(this);
12+
} else {
13+
return options.fn(this);
14+
}
15+
});
16+
17+
instance.registerHelper('unless', function(conditional, options) {
18+
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
19+
});
20+
}

lib/handlebars/helpers/log.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default function(instance) {
2+
instance.registerHelper('log', function(message, options) {
3+
let level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
4+
instance.log(level, message);
5+
});
6+
}

lib/handlebars/helpers/lookup.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function(instance) {
2+
instance.registerHelper('lookup', function(obj, field) {
3+
return obj && obj[field];
4+
});
5+
}

0 commit comments

Comments
 (0)