Skip to content

Commit

Permalink
Refactor Writer.renderTokens() for better readability.
Browse files Browse the repository at this point in the history
Split the old Writer.renderTokens() into several small functions with a single responsible.

Fixes janl#411
  • Loading branch information
phillipj committed Jan 7, 2015
1 parent 2ba7481 commit 6c616d0
Showing 1 changed file with 72 additions and 60 deletions.
132 changes: 72 additions & 60 deletions mustache.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,84 +444,96 @@
Writer.prototype.renderTokens = function (tokens, context, partials, originalTemplate) {
var buffer = '';

// This function is used to render an arbitrary template
// in the current context by higher-order sections.
var self = this;
function subRender(template) {
return self.render(template, context, partials);
}

var token, value;
var token, tokenRenderer;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
token = tokens[i];
tokenRenderer = this._getTokenRenderer(token[0]);

switch (token[0]) {
case '#':
value = context.lookup(token[1]);
if (tokenRenderer)
buffer += tokenRenderer.call(this, token, context, partials, originalTemplate);
}

if (!value)
continue;
return buffer;
};

if (isArray(value)) {
for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
}
} else if (typeof value === 'object' || typeof value === 'string') {
buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
} else if (isFunction(value)) {
if (typeof originalTemplate !== 'string')
throw new Error('Cannot use higher-order sections without the original template');
Writer.prototype._getTokenRenderer = function(tokenSymbol) {
return {
'#': this._renderSection,
'^': this._renderInverted,
'>': this._renderPartial,
'&': this._unescapedValue,
'name': this._escapedValue,
'text': this._rawValue
}[tokenSymbol];
};

// Extract the portion of the original template that the section contains.
value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
Writer.prototype._renderSection = function (token, context, partials, originalTemplate) {
var self = this;
var buffer = '';
var value = context.lookup(token[1]);

if (value != null)
buffer += value;
} else {
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
}
// This function is used to render an arbitrary template
// in the current context by higher-order sections.
function subRender(template) {
return self.render(template, context, partials);
}

break;
case '^':
value = context.lookup(token[1]);
if (!value)
return '';

// Use JavaScript's definition of falsy. Include empty arrays.
// See https://github.com/janl/mustache.js/issues/186
if (!value || (isArray(value) && value.length === 0))
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
if (isArray(value)) {
for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
}
} else if (typeof value === 'object' || typeof value === 'string') {
buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
} else if (isFunction(value)) {
if (typeof originalTemplate !== 'string')
throw new Error('Cannot use higher-order sections without the original template');

break;
case '>':
if (!partials)
continue;
// Extract the portion of the original template that the section contains.
value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);

value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
if (value != null)
buffer += value;
} else {
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
}

if (value != null)
buffer += this.renderTokens(this.parse(value), context, partials, value);
return buffer;
};

break;
case '&':
value = context.lookup(token[1]);
Writer.prototype._renderInverted = function(token, context, partials, originalTemplate) {
var value = context.lookup(token[1]);

if (value != null)
buffer += value;
// Use JavaScript's definition of falsy. Include empty arrays.
// See https://github.com/janl/mustache.js/issues/186
if (!value || (isArray(value) && value.length === 0))
return this.renderTokens(token[4], context, partials, originalTemplate);

break;
case 'name':
value = context.lookup(token[1]);
return '';
};

if (value != null)
buffer += mustache.escape(value);
Writer.prototype._renderPartial = function(token, context, partials, originalTemplate) {
if (!partials)
return '';

break;
case 'text':
buffer += token[1];
break;
}
}
var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
return (value != null) ? this.renderTokens(this.parse(value), context, partials, value) : '';
};

return buffer;
Writer.prototype._unescapedValue = function(token, context) {
var value = context.lookup(token[1]);
return (value != null) ? value : '';
};

Writer.prototype._escapedValue = function(token, context) {
var value = context.lookup(token[1]);
return (value != null) ? mustache.escape(value) : '';
};

Writer.prototype._rawValue = function(token) {
return token[1];
};

mustache.name = "mustache.js";
Expand Down

0 comments on commit 6c616d0

Please sign in to comment.