Skip to content

Commit

Permalink
Rename parserContext with state
Browse files Browse the repository at this point in the history
  • Loading branch information
thegrandpoobah committed Apr 27, 2011
1 parent cde6dc3 commit 45bc833
Showing 1 changed file with 82 additions and 84 deletions.
166 changes: 82 additions & 84 deletions mustache.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,11 @@ var Mustache = (function(undefined) {
return undefined;
}

function get_variable_name(parserContext, token, prefix, postfix) {
function get_variable_name(state, token, prefix, postfix) {
var fragment = token
.substring(
parserContext.openTag.length + (prefix ? 1 : 0)
, token.length - parserContext.closeTag.length - (postfix ? 1 : 0)
state.openTag.length + (prefix ? 1 : 0)
, token.length - state.closeTag.length - (postfix ? 1 : 0)
);

if (String.prototype.trim) {
Expand All @@ -226,7 +226,7 @@ var Mustache = (function(undefined) {
}
}

function interpolate(parserContext, token, escape) {
function interpolate(state, token, escape) {
function escapeHTML(str) {
return str.replace(/&/g,'&')
.replace(/</g,'&lt;')
Expand All @@ -240,8 +240,8 @@ var Mustache = (function(undefined) {
prefix = true;
}

var variable = get_variable_name(parserContext, token, prefix, postfix);
parserContext.send_code_func((function(variable, escape) { return function(context, send_func) {
var variable = get_variable_name(state, token, prefix, postfix);
state.send_code_func((function(variable, escape) { return function(context, send_func) {
var res = find_in_stack(variable, context);
if (res!==undefined) {
if (!escape) {
Expand All @@ -253,26 +253,26 @@ var Mustache = (function(undefined) {
};})(variable, escape));
}

function partial(parserContext, token) {
var variable = get_variable_name(parserContext, token, true),
function partial(state, token) {
var variable = get_variable_name(state, token, true),
template, program;

if (!parserContext.partials[variable]) {
if (!state.partials[variable]) {
throw new Error('Unknown partial \'' + variable + '\'');
}

if (!is_function(parserContext.partials[variable])) {
if (!is_function(state.partials[variable])) {
// if the partial has not been compiled yet, do so now

template = parserContext.partials[variable]; // remember what the partial was
parserContext.partials[variable] = noop; // avoid infinite recursion
template = state.partials[variable]; // remember what the partial was
state.partials[variable] = noop; // avoid infinite recursion

program = parse(create_parser_state(
template
, parserContext.partials
, state.partials
));

parserContext.partials[variable] = function(context, send_func) {
state.partials[variable] = function(context, send_func) {
var value = find_in_stack(variable, context);

if (value) {
Expand All @@ -291,17 +291,15 @@ var Mustache = (function(undefined) {
};
}

parserContext.send_code_func(function(context, send_func) { parserContext.partials[variable](context, send_func); });
state.send_code_func(function(context, send_func) { state.partials[variable](context, send_func); });
}

function section(parserContext) {
function create_section_context(template) {
var context = create_parser_state(template,
parserContext.partials,
parserContext.openTag,
parserContext.closeTag);

return context;
function section(state) {
function create_section_state(template) {
return create_parser_state(template,
state.partials,
state.openTag,
state.closeTag);
}

// by @langalex, support for arrays of strings
Expand All @@ -310,26 +308,26 @@ var Mustache = (function(undefined) {
return _context;
} else {
var ctx = {},
iterator = (parserContext.pragmas['IMPLICIT-ITERATOR'] || {iterator: '.'}).iterator;
iterator = (state.pragmas['IMPLICIT-ITERATOR'] || {iterator: '.'}).iterator;

ctx[iterator] = _context;

return ctx;
}
}

var s = parserContext.section, template = s.template_buffer.join('')
program = parse(create_section_context(template));
var s = state.section, template = s.template_buffer.join('')
program = parse(create_section_state(template));

if (s.inverted) {
parserContext.send_code_func((function(program, variable){ return function(context, send_func) {
state.send_code_func((function(program, variable){ return function(context, send_func) {
var value = find_in_stack(variable, context);
if (!value || is_array(value) && value.length === 0) { // false or empty list, render it
program(context, send_func);
}
};})(program, s.variable));
} else {
parserContext.send_code_func((function(program, variable, template, partials){ return function(context, send_func) {
state.send_code_func((function(program, variable, template, partials){ return function(context, send_func) {
var value = find_in_stack(variable, context);
if (is_array(value)) { // Enumerable, Let's loop!
for (var i=0, n=value.length; i<n; ++i) {
Expand All @@ -356,32 +354,32 @@ var Mustache = (function(undefined) {
} else if (value) { // truthy
program(context, send_func);
}
};})(program, s.variable, template, parserContext.partials));
};})(program, s.variable, template, state.partials));
}
}

function pragmas(parserContext) {
function pragmas(state) {
/* includes tag */
function includes(needle, haystack) {
return haystack.indexOf('{{' + needle) !== -1;
}

var directives = {
'IMPLICIT-ITERATOR': function(options) {
parserContext.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'};
state.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'};

if (options) {
parserContext.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator'];
state.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator'];
}
}
};

// no pragmas, easy escape
if(!includes("%", parserContext.template)) {
return parserContext.template;
if(!includes("%", state.template)) {
return state.template;
}

parserContext.template = parserContext.template.replace(/{{%([\w-]+)(\s*)(.*?(?=}}))}}/, function(match, pragma, space, suffix) {
state.template = state.template.replace(/{{%([\w-]+)(\s*)(.*?(?=}}))}}/, function(match, pragma, space, suffix) {
var options = undefined,
optionPairs, scratch,
i, n;
Expand Down Expand Up @@ -410,74 +408,74 @@ var Mustache = (function(undefined) {
});
}

function change_delimiter(parserContext, token) {
var matches = token.match(new RegExp(escape_regex(parserContext.openTag) + '=(\\S*?)\\s*(\\S*?)=' + escape_regex(parserContext.closeTag)));
function change_delimiter(state, token) {
var matches = token.match(new RegExp(escape_regex(state.openTag) + '=(\\S*?)\\s*(\\S*?)=' + escape_regex(state.closeTag)));

if ((matches || []).length!==3) {
throw new Error('Malformed change delimiter token: ' + token);
}

var context = create_parser_state(
parserContext.tokens.slice(parserContext.cursor+1).join('')
, parserContext.partials
state.tokens.slice(state.cursor+1).join('')
, state.partials
, matches[1]
, matches[2]);
context.code = parserContext.code;
context.send_code_func = parserContext.send_code_func;
context.code = state.code;
context.send_code_func = state.send_code_func;

parserContext.cursor = parserContext.tokens.length; // finish off this level
state.cursor = state.tokens.length; // finish off this level

parse(context, true);
}

function begin_section(parserContext, token, inverted) {
var variable = get_variable_name(parserContext, token, true);
function begin_section(state, token, inverted) {
var variable = get_variable_name(state, token, true);

if (parserContext.state==='normal') {
parserContext.state = 'scan_section';
parserContext.section = {
if (state.state==='normal') {
state.state = 'scan_section';
state.section = {
variable: variable
, template_buffer: []
, inverted: inverted
, child_sections: []
};
} else {
parserContext.section.child_sections.push(variable);
parserContext.section.template_buffer.push(token);
state.section.child_sections.push(variable);
state.section.template_buffer.push(token);
}
}

function end_section(parserContext, token) {
var variable = get_variable_name(parserContext, token, true);
function end_section(state, token) {
var variable = get_variable_name(state, token, true);

if (parserContext.section.child_sections.length > 0 &&
parserContext.section.child_sections[parserContext.section.child_sections.length-1] === variable) {
if (state.section.child_sections.length > 0 &&
state.section.child_sections[state.section.child_sections.length-1] === variable) {

parserContext.section.child_sections.pop();
parserContext.section.template_buffer.push(token);
} else if (parserContext.section.variable===variable) {
section(parserContext);
delete parserContext.section;
parserContext.state = 'normal';
state.section.child_sections.pop();
state.section.template_buffer.push(token);
} else if (state.section.variable===variable) {
section(state);
delete state.section;
state.state = 'normal';
} else {
throw new Error('Unexpected section end tag. Expected: ' + parserContext.section.variable);
throw new Error('Unexpected section end tag. Expected: ' + state.section.variable);
}
}

function parse(parserContext, noReturn) {
function parse(state, noReturn) {
var n, token;

for (n = parserContext.tokens.length;parserContext.cursor<n;++parserContext.cursor) {
token = parserContext.tokens[parserContext.cursor];
for (n = state.tokens.length;state.cursor<n;++state.cursor) {
token = state.tokens[state.cursor];
if (token==='' || token===undefined) {
continue;
}

stateMachine[parserContext.state](parserContext, token);
stateMachine[state.state](state, token);
}

if (!noReturn) {
var codeList = parserContext.code;
var codeList = state.code;
if (codeList.length === 0) {
return noop;
} else if (codeList.length === 1) {
Expand All @@ -493,66 +491,66 @@ var Mustache = (function(undefined) {
}

var stateMachine = {
'normal': function(parserContext, token) {
if (token.indexOf(parserContext.openTag)===0) {
'normal': function(state, token) {
if (token.indexOf(state.openTag)===0) {
// the token has the makings of a Mustache tag
// perform the appropriate action based on the state machine
switch (token.charAt(parserContext.openTag.length)) {
switch (token.charAt(state.openTag.length)) {
case '!': // comment
// comments are just discarded, nothing to do
break;
case '#': // section
begin_section(parserContext, token, false);
begin_section(state, token, false);
break;
case '^': // inverted section
begin_section(parserContext, token, true);
begin_section(state, token, true);
break;
case '/': // end section
// in normal flow, this operation is absolutely meaningless
throw new Error('Unbalanced End Section tag: ' + token);
case '&': // unescaped variable
case '{': // unescaped variable
interpolate(parserContext, token, token.charAt(parserContext.openTag.length));
interpolate(state, token, token.charAt(state.openTag.length));
break;
case '>': // partial
partial(parserContext, token);
partial(state, token);
break;
case '=': // set delimiter change
change_delimiter(parserContext, token);
change_delimiter(state, token);
break;
default: // escaped variable
interpolate(parserContext, token);
interpolate(state, token);
break;
}
} else {
// plain jane text
parserContext.send_code_func(function(view, send_func) { send_func(token); });
state.send_code_func(function(view, send_func) { send_func(token); });
}
}
, 'scan_section': function(parserContext, token) {
if (token.indexOf(parserContext.openTag)===0) {
switch (token.charAt(parserContext.openTag.length)) {
, 'scan_section': function(state, token) {
if (token.indexOf(state.openTag)===0) {
switch (token.charAt(state.openTag.length)) {
case '!': // comments
// comments are just discarded, nothing to do
break;
case '#': // section
begin_section(parserContext, token, false);
begin_section(state, token, false);
break;
case '^': // inverted section
begin_section(parserContext, token, true);
begin_section(state, token, true);
break;
case '/': // end section
end_section(parserContext, token);
end_section(state, token);
break;
case '=': // set delimiter change
change_delimiter(parserContext, token);
change_delimiter(state, token);
break;
default: // all others
parserContext.section.template_buffer.push(token);
state.section.template_buffer.push(token);
break;
}
} else {
parserContext.section.template_buffer.push(token);
state.section.template_buffer.push(token);
}
}
}
Expand Down

0 comments on commit 45bc833

Please sign in to comment.