| @@ -212,11 +212,11 @@ var Mustache = (function(undefined) { | |||||
| return undefined; | return undefined; | ||||
| } | } | ||||
| function get_variable_name(parserContext, token, prefix, postfix) { | |||||
| function get_variable_name(state, token, prefix, postfix) { | |||||
| var fragment = token | var fragment = token | ||||
| .substring( | .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) { | if (String.prototype.trim) { | ||||
| @@ -226,7 +226,7 @@ var Mustache = (function(undefined) { | |||||
| } | } | ||||
| } | } | ||||
| function interpolate(parserContext, token, escape) { | |||||
| function interpolate(state, token, escape) { | |||||
| function escapeHTML(str) { | function escapeHTML(str) { | ||||
| return str.replace(/&/g,'&') | return str.replace(/&/g,'&') | ||||
| .replace(/</g,'<') | .replace(/</g,'<') | ||||
| @@ -240,8 +240,8 @@ var Mustache = (function(undefined) { | |||||
| prefix = true; | 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); | var res = find_in_stack(variable, context); | ||||
| if (res!==undefined) { | if (res!==undefined) { | ||||
| if (!escape) { | if (!escape) { | ||||
| @@ -253,26 +253,26 @@ var Mustache = (function(undefined) { | |||||
| };})(variable, escape)); | };})(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; | template, program; | ||||
| if (!parserContext.partials[variable]) { | |||||
| if (!state.partials[variable]) { | |||||
| throw new Error('Unknown partial \'' + 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 | // 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( | program = parse(create_parser_state( | ||||
| template | 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); | var value = find_in_stack(variable, context); | ||||
| if (value) { | if (value) { | ||||
| @@ -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 | // by @langalex, support for arrays of strings | ||||
| @@ -310,7 +308,7 @@ var Mustache = (function(undefined) { | |||||
| return _context; | return _context; | ||||
| } else { | } else { | ||||
| var ctx = {}, | var ctx = {}, | ||||
| iterator = (parserContext.pragmas['IMPLICIT-ITERATOR'] || {iterator: '.'}).iterator; | |||||
| iterator = (state.pragmas['IMPLICIT-ITERATOR'] || {iterator: '.'}).iterator; | |||||
| ctx[iterator] = _context; | ctx[iterator] = _context; | ||||
| @@ -318,18 +316,18 @@ var Mustache = (function(undefined) { | |||||
| } | } | ||||
| } | } | ||||
| 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) { | 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); | var value = find_in_stack(variable, context); | ||||
| if (!value || is_array(value) && value.length === 0) { // false or empty list, render it | if (!value || is_array(value) && value.length === 0) { // false or empty list, render it | ||||
| program(context, send_func); | program(context, send_func); | ||||
| } | } | ||||
| };})(program, s.variable)); | };})(program, s.variable)); | ||||
| } else { | } 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); | var value = find_in_stack(variable, context); | ||||
| if (is_array(value)) { // Enumerable, Let's loop! | if (is_array(value)) { // Enumerable, Let's loop! | ||||
| for (var i=0, n=value.length; i<n; ++i) { | for (var i=0, n=value.length; i<n; ++i) { | ||||
| @@ -356,11 +354,11 @@ var Mustache = (function(undefined) { | |||||
| } else if (value) { // truthy | } else if (value) { // truthy | ||||
| program(context, send_func); | program(context, send_func); | ||||
| } | } | ||||
| };})(program, s.variable, template, parserContext.partials)); | |||||
| };})(program, s.variable, template, state.partials)); | |||||
| } | } | ||||
| } | } | ||||
| function pragmas(parserContext) { | |||||
| function pragmas(state) { | |||||
| /* includes tag */ | /* includes tag */ | ||||
| function includes(needle, haystack) { | function includes(needle, haystack) { | ||||
| return haystack.indexOf('{{' + needle) !== -1; | return haystack.indexOf('{{' + needle) !== -1; | ||||
| @@ -368,20 +366,20 @@ var Mustache = (function(undefined) { | |||||
| var directives = { | var directives = { | ||||
| 'IMPLICIT-ITERATOR': function(options) { | 'IMPLICIT-ITERATOR': function(options) { | ||||
| parserContext.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'}; | |||||
| state.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'}; | |||||
| if (options) { | if (options) { | ||||
| parserContext.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator']; | |||||
| state.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator']; | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| // no pragmas, easy escape | // 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, | var options = undefined, | ||||
| optionPairs, scratch, | optionPairs, scratch, | ||||
| i, n; | i, n; | ||||
| @@ -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) { | if ((matches || []).length!==3) { | ||||
| throw new Error('Malformed change delimiter token: ' + token); | throw new Error('Malformed change delimiter token: ' + token); | ||||
| } | } | ||||
| var context = create_parser_state( | 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[1] | ||||
| , matches[2]); | , 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); | 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 | variable: variable | ||||
| , template_buffer: [] | , template_buffer: [] | ||||
| , inverted: inverted | , inverted: inverted | ||||
| , child_sections: [] | , child_sections: [] | ||||
| }; | }; | ||||
| } else { | } 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 { | } 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; | 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) { | if (token==='' || token===undefined) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| stateMachine[parserContext.state](parserContext, token); | |||||
| stateMachine[state.state](state, token); | |||||
| } | } | ||||
| if (!noReturn) { | if (!noReturn) { | ||||
| var codeList = parserContext.code; | |||||
| var codeList = state.code; | |||||
| if (codeList.length === 0) { | if (codeList.length === 0) { | ||||
| return noop; | return noop; | ||||
| } else if (codeList.length === 1) { | } else if (codeList.length === 1) { | ||||
| @@ -493,66 +491,66 @@ var Mustache = (function(undefined) { | |||||
| } | } | ||||
| var stateMachine = { | 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 | // the token has the makings of a Mustache tag | ||||
| // perform the appropriate action based on the state machine | // perform the appropriate action based on the state machine | ||||
| switch (token.charAt(parserContext.openTag.length)) { | |||||
| switch (token.charAt(state.openTag.length)) { | |||||
| case '!': // comment | case '!': // comment | ||||
| // comments are just discarded, nothing to do | // comments are just discarded, nothing to do | ||||
| break; | break; | ||||
| case '#': // section | case '#': // section | ||||
| begin_section(parserContext, token, false); | |||||
| begin_section(state, token, false); | |||||
| break; | break; | ||||
| case '^': // inverted section | case '^': // inverted section | ||||
| begin_section(parserContext, token, true); | |||||
| begin_section(state, token, true); | |||||
| break; | break; | ||||
| case '/': // end section | case '/': // end section | ||||
| // in normal flow, this operation is absolutely meaningless | // in normal flow, this operation is absolutely meaningless | ||||
| throw new Error('Unbalanced End Section tag: ' + token); | throw new Error('Unbalanced End Section tag: ' + token); | ||||
| case '&': // unescaped variable | case '&': // unescaped variable | ||||
| case '{': // unescaped variable | case '{': // unescaped variable | ||||
| interpolate(parserContext, token, token.charAt(parserContext.openTag.length)); | |||||
| interpolate(state, token, token.charAt(state.openTag.length)); | |||||
| break; | break; | ||||
| case '>': // partial | case '>': // partial | ||||
| partial(parserContext, token); | |||||
| partial(state, token); | |||||
| break; | break; | ||||
| case '=': // set delimiter change | case '=': // set delimiter change | ||||
| change_delimiter(parserContext, token); | |||||
| change_delimiter(state, token); | |||||
| break; | break; | ||||
| default: // escaped variable | default: // escaped variable | ||||
| interpolate(parserContext, token); | |||||
| interpolate(state, token); | |||||
| break; | break; | ||||
| } | } | ||||
| } else { | } else { | ||||
| // plain jane text | // 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 | case '!': // comments | ||||
| // comments are just discarded, nothing to do | // comments are just discarded, nothing to do | ||||
| break; | break; | ||||
| case '#': // section | case '#': // section | ||||
| begin_section(parserContext, token, false); | |||||
| begin_section(state, token, false); | |||||
| break; | break; | ||||
| case '^': // inverted section | case '^': // inverted section | ||||
| begin_section(parserContext, token, true); | |||||
| begin_section(state, token, true); | |||||
| break; | break; | ||||
| case '/': // end section | case '/': // end section | ||||
| end_section(parserContext, token); | |||||
| end_section(state, token); | |||||
| break; | break; | ||||
| case '=': // set delimiter change | case '=': // set delimiter change | ||||
| change_delimiter(parserContext, token); | |||||
| change_delimiter(state, token); | |||||
| break; | break; | ||||
| default: // all others | default: // all others | ||||
| parserContext.section.template_buffer.push(token); | |||||
| state.section.template_buffer.push(token); | |||||
| break; | break; | ||||
| } | } | ||||
| } else { | } else { | ||||
| parserContext.section.template_buffer.push(token); | |||||
| state.section.template_buffer.push(token); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||