Skip to content

Commit

Permalink
Merge pull request #712 from wycats/track-ids
Browse files Browse the repository at this point in the history
Add trackIds compiler flag
  • Loading branch information
kpdecker committed Jan 18, 2014
2 parents 103e5f8 + 5a0bcb9 commit 88c52de
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 6 deletions.
37 changes: 35 additions & 2 deletions lib/handlebars/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,22 @@ function registerDefaultHelpers(instance) {
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 {
return fn(context);
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);
}
});

Expand All @@ -89,6 +99,11 @@ function registerDefaultHelpers(instance) {
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) {
Expand All @@ -102,6 +117,10 @@ function registerDefaultHelpers(instance) {
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 });
}
Expand All @@ -112,6 +131,10 @@ function registerDefaultHelpers(instance) {
data.key = key;
data.index = i;
data.first = (i === 0);

if (contextPath) {
data.contextPath = contextPath + key;
}
}
ret = ret + fn(context[key], {data: data});
i++;
Expand Down Expand Up @@ -147,7 +170,17 @@ function registerDefaultHelpers(instance) {
instance.registerHelper('with', function(context, options) {
if (isFunction(context)) { context = context.call(this); }

if (!Utils.isEmpty(context)) return options.fn(context);
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);
}
});

instance.registerHelper('log', function(context, options) {
Expand Down
6 changes: 5 additions & 1 deletion lib/handlebars/compiler/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ var AST = {

var original = "",
dig = [],
depth = 0;
depth = 0,
depthString = '';

for(var i=0,l=parts.length; i<l; i++) {
var part = parts[i].part;
Expand All @@ -160,6 +161,7 @@ var AST = {
throw new Exception("Invalid path: " + original, this);
} else if (part === "..") {
depth++;
depthString += '../';
} else {
this.isScoped = true;
}
Expand All @@ -172,6 +174,7 @@ var AST = {
this.parts = dig;
this.string = dig.join('.');
this.depth = depth;
this.idName = depthString + this.string;

// an ID is simple if it only has one part, and that part is not
// `..` or `this`.
Expand All @@ -191,6 +194,7 @@ var AST = {
this.type = "DATA";
this.id = id;
this.stringModeValue = id.stringModeValue;
this.idName = '@' + id.stringModeValue;
},

StringNode: function(string, locInfo) {
Expand Down
4 changes: 4 additions & 0 deletions lib/handlebars/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Compiler.prototype = {
this.depths = {list: []};
this.options = options;
this.stringParams = options.stringParams;
this.trackIds = options.trackIds;

// These changes will propagate to the other compiler components
var knownHelpers = this.options.knownHelpers;
Expand Down Expand Up @@ -395,6 +396,9 @@ Compiler.prototype = {
this.sexpr(val);
}
} else {
if (this.trackIds) {
this.opcode('pushId', val.type, val.idName || val.stringModeValue);
}
this.accept(val);
}
},
Expand Down
39 changes: 36 additions & 3 deletions lib/handlebars/compiler/javascript-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ JavaScriptCompiler.prototype = {
this.environment = environment;
this.options = options || {};
this.stringParams = this.options.stringParams;
this.trackIds = this.options.trackIds;

log('debug', this.environment.disassemble() + "\n\n");

Expand Down Expand Up @@ -418,6 +419,9 @@ JavaScriptCompiler.prototype = {
emptyHash: function() {
this.pushStackLiteral('{}');

if (this.trackIds) {
this.push('{}'); // hashIds
}
if (this.stringParams) {
this.push('{}'); // hashContexts
this.push('{}'); // hashTypes
Expand All @@ -427,12 +431,15 @@ JavaScriptCompiler.prototype = {
if (this.hash) {
this.hashes.push(this.hash);
}
this.hash = {values: [], types: [], contexts: []};
this.hash = {values: [], types: [], contexts: [], ids: []};
},
popHash: function() {
var hash = this.hash;
this.hash = this.hashes.pop();

if (this.trackIds) {
this.push('{' + hash.ids.join(',') + '}');
}
if (this.stringParams) {
this.push('{' + hash.contexts.join(',') + '}');
this.push('{' + hash.types.join(',') + '}');
Expand Down Expand Up @@ -589,8 +596,12 @@ JavaScriptCompiler.prototype = {
assignToHash: function(key) {
var value = this.popStack(),
context,
type;
type,
id;

if (this.trackIds) {
id = this.popStack();
}
if (this.stringParams) {
type = this.popStack();
context = this.popStack();
Expand All @@ -603,9 +614,22 @@ JavaScriptCompiler.prototype = {
if (type) {
hash.types.push("'" + key + "': " + type);
}
if (id) {
hash.ids.push("'" + key + "': " + id);
}
hash.values.push("'" + key + "': (" + value + ")");
},

pushId: function(type, name) {
if (type === 'ID' || type === 'DATA') {
this.pushString(name);
} else if (type === 'sexpr') {
this.pushStackLiteral('true');
} else {
this.pushStackLiteral('null');
}
},

// HELPERS

compiler: JavaScriptCompiler,
Expand Down Expand Up @@ -844,11 +868,14 @@ JavaScriptCompiler.prototype = {
},

setupOptions: function(helper, paramSize, params) {
var options = {}, contexts = [], types = [], param, inverse, program;
var options = {}, contexts = [], types = [], ids = [], param, inverse, program;

options.name = this.quotedString(helper);
options.hash = this.popStack();

if (this.trackIds) {
options.hashIds = this.popStack();
}
if (this.stringParams) {
options.hashTypes = this.popStack();
options.hashContexts = this.popStack();
Expand Down Expand Up @@ -878,12 +905,18 @@ JavaScriptCompiler.prototype = {
param = this.popStack();
params.push(param);

if (this.trackIds) {
ids.push(this.popStack());
}
if (this.stringParams) {
types.push(this.popStack());
contexts.push(this.popStack());
}
}

if (this.trackIds) {
options.ids = "[" + ids.join(",") + "]";
}
if (this.stringParams) {
options.types = "[" + types.join(",") + "]";
options.contexts = "[" + contexts.join(",") + "]";
Expand Down
4 changes: 4 additions & 0 deletions lib/handlebars/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,7 @@ export function isEmpty(value) {
return false;
}
}

export function appendContextPath(contextPath, id) {
return (contextPath ? contextPath + '.' : '') + id;
}
Loading

0 comments on commit 88c52de

Please # to comment.