diff --git a/src/handlebars-utils.js b/src/handlebars-utils.js index 105bf1b..a6b6bef 100644 --- a/src/handlebars-utils.js +++ b/src/handlebars-utils.js @@ -35,32 +35,32 @@ HandlebarsUtils.rawEndBlockRegExp = /^\{\{\{\{\/([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\ /* '{{{' '~'? 'space'* '@'? 'space'* ('not {}~'+) 'space'* ('not {}~'+) '~'? non-greedy '}}}' and not follow by '}' */ HandlebarsUtils.RAW_EXPRESSION = 1; // {{{expression}}} // HandlebarsUtils.rawExpressionRegExp = /^\{\{\{\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>\[\\\]\^`\{\|\}\~]+)\s*?\}\}\}(?!})/; -HandlebarsUtils.rawExpressionRegExp = /^\{\{\{~?\s*@?\s*([^\s\}\{~]+)\s*([^\}\{~]*)~??\}\}\}(?!})/; +HandlebarsUtils.rawExpressionRegExp = /^\{\{\{~?\s*@?\s*([^\s\}\{~]+)\s*([^\}\{~]*)~?\}\}\}(?!})/; -/* '{{' '~'? 'space'* '@'? 'space'* ('not {}~'+) 'space'* ('not {}~'+) '~'? non-greedy '}}' and not follow by '}' */ +/* '{{' '~'? 'space'* '@'? 'space'* ('not {}~'+) '~'? non-greedy '}}' and not follow by '}' */ HandlebarsUtils.ESCAPE_EXPRESSION = 2; // {{expression}} -HandlebarsUtils.escapeExpressionRegExp = /^\{\{~?\s*@?\s*([^\s\}\{~]+)\s*([^\}\{~]*)~??\}\}(?!})/; +HandlebarsUtils.escapeExpressionRegExp = /^\{\{~?\s*@?\s*([^\}\{~]+)~?\}\}(?!})/; /* '{{' '~'? '>' '\s'* ('not \s, special-char'+) '\s'* 'not ~{}'* non-greedy '}}' and not follow by '}' */ HandlebarsUtils.PARTIAL_EXPRESSION = 3; // {{>.*}} -HandlebarsUtils.partialExpressionRegExp = /^\{\{~?>\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^~\}\{]*~??\}\}(?!})/; +HandlebarsUtils.partialExpressionRegExp = /^\{\{~?>\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^~\}\{]*~?\}\}(?!})/; /* '{{' '~'? '&' '\s'* ('not \s, special-char'+) '\s'* 'not ~{}'* non-greedy '}}' and not follow by '}' */ HandlebarsUtils.REFERENCE_EXPRESSION = 11; // {{&.*}} -HandlebarsUtils.referenceExpressionRegExp = /^\{\{~?&\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^~\}\{]*~??\}\}(?!})/; +HandlebarsUtils.referenceExpressionRegExp = /^\{\{~?&\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^~\}\{]*~?\}\}(?!})/; /* '{{' '~'? '# or ^' '\s'* ('not \s, special-char'+) '\s'* 'not {}~'* '~'? non-greedy '}}' and not follow by '}' */ HandlebarsUtils.BRANCH_EXPRESSION = 4; // {{#.*}}, {{^.*}} -HandlebarsUtils.branchExpressionRegExp = /^\{\{~?[#|\^]\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^\}\{~]*~??\}\}(?!})/; +HandlebarsUtils.branchExpressionRegExp = /^\{\{~?[#|\^]\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^\}\{~]*~?\}\}(?!})/; /* '{{' '~'? '/' '\s'* ('not \s, special-char'+) '\s'* 'not {}~'* '~'? non-greedy '}}' and not follow by '}' */ HandlebarsUtils.BRANCH_END_EXPRESSION = 5; // {{/.*}} -HandlebarsUtils.branchEndExpressionRegExp = /^\{\{~?\/\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^\}\{~]*~??\}\}(?!})/; +HandlebarsUtils.branchEndExpressionRegExp = /^\{\{~?\/\s*([^\s!"#%&'\(\)\*\+,\.\/;<=>@\[\\\]\^`\{\|\}\~]+)\s*[^\}\{~]*~?\}\}(?!})/; /* '{{' '~'? '\s'* 'else' '\s'* 'not {}~'* '~'? non-greedy '}}' and not follow by '}' */ HandlebarsUtils.ELSE_EXPRESSION = 6; // {{else}}, {{^}} -HandlebarsUtils.elseExpressionRegExp = /^\{\{~?\s*else\s*[^\}\{~]*~??\}\}(?!})/; +HandlebarsUtils.elseExpressionRegExp = /^\{\{~?\s*else\s*[^\}\{~]*~?\}\}(?!})/; /* '{{' '~'? '^'{1} '~'? non-greedy '}}' and not follow by '}' */ -HandlebarsUtils.elseShortFormExpressionRegExp = /^\{\{~?\^{1}~??\}\}(?!})/; +HandlebarsUtils.elseShortFormExpressionRegExp = /^\{\{~?\^{1}~?\}\}(?!})/; /* '{{' '~'? '!--' */ HandlebarsUtils.COMMENT_EXPRESSION_LONG_FORM = 7; // {{!--.*--}} @@ -121,7 +121,12 @@ HandlebarsUtils.isValidExpression = function(input, i, type) { break; case HandlebarsUtils.ESCAPE_EXPRESSION: re = HandlebarsUtils.escapeExpressionRegExp.exec(s); - if (re !== null && re[1] !== undefined) { + if (re) { + // NOTE: the re.index field is never been used. + var r = HandlebarsUtils.parseEscapeExpression(re[1]); + re[1] = r[1]; + re[2] = r[2]; + if (HandlebarsUtils.isReservedChar(re[1], 0)) { re.tag = false; re.isSingleID = false; @@ -177,6 +182,31 @@ HandlebarsUtils.isValidExpression = function(input, i, type) { return re; }; +// @function HandlebarsUtils.parseEscapeExpression +HandlebarsUtils.parseEscapeExpression = function(str) { + var j=0, inSquareBracket = false, + fstr = '', re = []; + + // the new regexp will capture the tailing space. + str = str.replace(/\s+$/, ''); + while(jexp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ 'PartialStatement', false, 11 ]}, - { syntax: '{{!exp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ 'CommentStatement', false, 11 ]}, + { syntax: '{{/exp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ false, false, '' ]}, + { syntax: '{{#exp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ false, false, '' ]}, + { syntax: '{{>exp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ 'PartialStatement', false, '' ]}, + { syntax: '{{!exp1}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ 'CommentStatement', false, '' ]}, // it is fine to pass util test, as Handlebars parser will fails the second &exp2 - { syntax: '{{exp1 &exp2}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'exp1',isSingleID: false, result: [ false, true, 11 ]}, + { syntax: '{{exp1 &exp2}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'exp1',isSingleID: false, result: [ false, true, '' ]}, // we skip this pattern - { syntax: '{{}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ false, false, 11 ]}, + { syntax: '{{}} ', type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: false, isSingleID: false, result: [ false, false, '' ]}, + + { syntax: '{{article.[a b].[c d] }} ', + type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'article.[a b].[c d]', isSingleID: true, result: [ 'MustacheStatement', true, '' ]}, + { syntax: '{{article.[a b].[c d] something }} ', + type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'article.[a b].[c d]', isSingleID: false, result: [ 'MustacheStatement', true, '' ]}, + { syntax: '{{article/[a b]}} ', + type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'article/[a b]', isSingleID: true, result: [ 'MustacheStatement', true, '' ]}, + { syntax: '{{article.[a\rb]}} ', + type: handlebarsUtils.ESCAPE_EXPRESSION, rstr: 'article.[a\rb]', isSingleID: true, result: [ 'MustacheStatement', true, '' ]}, ]; exports.escapeExpressionTestPatterns = escapeExpressionTestPatterns;