From efb2583e19f607635ebbf8a386b0f34acf56fded Mon Sep 17 00:00:00 2001 From: Sahab Yazdani Date: Wed, 27 Apr 2011 13:35:34 -0400 Subject: [PATCH] Code reorganization --- mustache.js | 369 +++++++++++++++++++++++++--------------------------- 1 file changed, 175 insertions(+), 194 deletions(-) diff --git a/mustache.js b/mustache.js index 7039739..a679435 100644 --- a/mustache.js +++ b/mustache.js @@ -101,6 +101,7 @@ var Mustache = (function(undefined) { } })(); + /* BEGIN Helpers */ function noop() {} var escapeCompiledRegex; @@ -116,17 +117,62 @@ var Mustache = (function(undefined) { return text.replace(escapeCompiledRegex, '\\$1'); } - - function isWhitespace(token) { - return token.match(/^\s+$/)!==null; + + function is_function(a) { + return a && typeof a === 'function'; } - function isNewline(token) { - return token.match(/\r?\n/)!==null; + function is_object(a) { + return a && typeof a === 'object'; } + function is_array(a) { + return Object.prototype.toString.call(a) === '[object Array]'; + } + + /* END Helpers */ + + /* BEGIN Compiler */ + + function compile(state, noReturn) { + var n, c, token; + + for (n = state.tokens.length;state.cursor=]?\s*\S*?\s*}?}})|({{=\S*?\s*\S*?=}})/; - function create_parser_state(template, partials, openTag, closeTag) { + function create_compiler_state(template, partials, openTag, closeTag) { openTag = openTag || '{{'; closeTag = closeTag || '}}'; @@ -146,16 +192,15 @@ var Mustache = (function(undefined) { , partials: partials || {} , openTag: openTag , closeTag: closeTag - , state: 'normal' + , parser: default_parser , pragmas: {} , code: code , send_code_func: function(f) { code.push(f); } }; - - // prefilter pragmas - pragmas(state); + + pragmas(state); // use pragmas to determine parsing behaviour // tokenize and initialize a cursor state.tokens = splitFunc.call(state.template, tokenizer); @@ -164,18 +209,60 @@ var Mustache = (function(undefined) { return state; } - function is_function(a) { - return a && typeof a === 'function'; - } - - function is_object(a) { - return a && typeof a === 'object'; - } + function pragmas(state) { + /* includes tag */ + function includes(needle, haystack) { + return haystack.indexOf('{{' + needle) !== -1; + } + + var directives = { + 'IMPLICIT-ITERATOR': function(options) { + state.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'}; + + if (options) { + state.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator']; + } + } + }; + + // no pragmas, easy escape + if(!includes("%", state.template)) { + return state.template; + } - function is_array(a) { - return Object.prototype.toString.call(a) === '[object Array]'; + state.template = state.template.replace(/{{%([\w-]+)(\s*)(.*?(?=}}))}}/, function(match, pragma, space, suffix) { + var options = undefined, + optionPairs, scratch, + i, n; + + if (suffix.length>0) { + optionPairs = suffix.split(','); + scratch; + + options = {}; + for (i=0, n=optionPairs.length; i/g,'>'); } - var prefix, postfix; - if (escape==='{') { - prefix = postfix = true; - } else if (escape==='&') { - prefix = true; + var escape, prefix, postfix; + if (mark==='{') { + escape = prefix = postfix = true; + } else if (mark==='&') { + escape = prefix = true; } var variable = get_variable_name(state, token, prefix, postfix); @@ -267,7 +346,7 @@ var Mustache = (function(undefined) { template = state.partials[variable]; // remember what the partial was state.partials[variable] = noop; // avoid infinite recursion - program = parse(create_parser_state( + program = compile(create_compiler_state( template , state.partials )); @@ -295,13 +374,6 @@ var Mustache = (function(undefined) { } 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 function create_context(_context) { if(is_object(_context)) { @@ -316,8 +388,11 @@ var Mustache = (function(undefined) { } } - var s = state.section, template = s.template_buffer.join('') - program = parse(create_section_state(template)); + var s = state.section, template = s.template_buffer.join(''), + program = compile(create_compiler_state(template, + state.partials, + state.openTag, + state.closeTag)); if (s.inverted) { state.send_code_func((function(program, variable){ return function(context, send_func) { @@ -347,7 +422,7 @@ var Mustache = (function(undefined) { var o = [], user_send_func = function(str) { o.push(str); }; - parse(create_parser_state(hosFragment, partials))(context, user_send_func); + compile(create_compiler_state(hosFragment, partials))(context, user_send_func); return o.join(''); })); @@ -357,55 +432,47 @@ var Mustache = (function(undefined) { };})(program, s.variable, template, state.partials)); } } + + /* BEGIN Parser */ - function pragmas(state) { - /* includes tag */ - function includes(needle, haystack) { - return haystack.indexOf('{{' + needle) !== -1; - } - - var directives = { - 'IMPLICIT-ITERATOR': function(options) { - state.pragmas['IMPLICIT-ITERATOR'] = {iterator: '.'}; - - if (options) { - state.pragmas['IMPLICIT-ITERATOR'].iterator = options['iterator']; - } - } - }; + var default_parser = { + '!': noop, + '#': begin_section, + '^': begin_section, + '/': function(state, token) { throw new Error('Unbalanced End Section tag: ' + token); }, + '&': interpolate, + '{': interpolate, + '>': partial, + '=': change_delimiter, + def: interpolate, + text: text + }; + + var scan_section_parser = { + '!': noop, + '#': begin_section, + '^': begin_section, + '/': end_section, + '&': buffer_section, + '{': buffer_section, + '>': buffer_section, + '=': change_delimiter, + def: buffer_section, + text: buffer_section + }; - // no pragmas, easy escape - if(!includes("%", state.template)) { - return state.template; - } - - state.template = state.template.replace(/{{%([\w-]+)(\s*)(.*?(?=}}))}}/, function(match, pragma, space, suffix) { - var options = undefined, - optionPairs, scratch, - i, n; - - if (suffix.length>0) { - optionPairs = suffix.split(','); - scratch; - - options = {}; - for (i=0, n=optionPairs.length; i': // partial - partial(state, token); - break; - case '=': // set delimiter change - change_delimiter(state, token); - break; - default: // escaped variable - interpolate(state, token); - break; - } - } else { - // plain jane text - state.send_code_func(function(view, send_func) { send_func(token); }); - } - } - , '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(state, token, false); - break; - case '^': // inverted section - begin_section(state, token, true); - break; - case '/': // end section - end_section(state, token); - break; - case '=': // set delimiter change - change_delimiter(state, token); - break; - default: // all others - state.section.template_buffer.push(token); - break; - } - } else { - state.section.template_buffer.push(token); - } - } - } + /* END Parser */ return({ name: "mustache.js", @@ -581,7 +562,7 @@ var Mustache = (function(undefined) { } } - var program = parse(create_parser_state(template, p)); + var program = compile(create_compiler_state(template, p)); return function(view, send_func) { var o = [], user_send_func = send_func || function(str) {