* Breaks up the given `template` string into a tree of tokens. If the `tags` * argument is given here it must be an array with two string values: the * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of * course, the default is to use mustaches (i.e. mustache.tags).
(template, tags)
| 101 | * which the closing tag for that section begins. |
| 102 | */ |
| 103 | function parseTemplate (template, tags) { |
| 104 | if (!template) |
| 105 | return []; |
| 106 | |
| 107 | var sections = []; // Stack to hold section tokens |
| 108 | var tokens = []; // Buffer to hold the tokens |
| 109 | var spaces = []; // Indices of whitespace tokens on the current line |
| 110 | var hasTag = false; // Is there a {{tag}} on the current line? |
| 111 | var nonSpace = false; // Is there a non-space char on the current line? |
| 112 | |
| 113 | // Strips all whitespace tokens array for the current line |
| 114 | // if there was a {{#tag}} on it and otherwise only space. |
| 115 | function stripSpace () { |
| 116 | if (hasTag && !nonSpace) { |
| 117 | while (spaces.length) |
| 118 | delete tokens[spaces.pop()]; |
| 119 | } else { |
| 120 | spaces = []; |
| 121 | } |
| 122 | |
| 123 | hasTag = false; |
| 124 | nonSpace = false; |
| 125 | } |
| 126 | |
| 127 | var openingTagRe, closingTagRe, closingCurlyRe; |
| 128 | function compileTags (tagsToCompile) { |
| 129 | if (typeof tagsToCompile === 'string') |
| 130 | tagsToCompile = tagsToCompile.split(spaceRe, 2); |
| 131 | |
| 132 | if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) |
| 133 | throw new Error('Invalid tags: ' + tagsToCompile); |
| 134 | |
| 135 | openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*'); |
| 136 | closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1])); |
| 137 | closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1])); |
| 138 | } |
| 139 | |
| 140 | compileTags(tags || mustache.tags); |
| 141 | |
| 142 | var scanner = new Scanner(template); |
| 143 | |
| 144 | var start, type, value, chr, token, openSection; |
| 145 | while (!scanner.eos()) { |
| 146 | start = scanner.pos; |
| 147 | |
| 148 | // Match any text between tags. |
| 149 | value = scanner.scanUntil(openingTagRe); |
| 150 | |
| 151 | if (value) { |
| 152 | for (var i = 0, valueLength = value.length; i < valueLength; ++i) { |
| 153 | chr = value.charAt(i); |
| 154 | |
| 155 | if (isWhitespace(chr)) { |
| 156 | spaces.push(tokens.length); |
| 157 | } else { |
| 158 | nonSpace = true; |
| 159 | } |
| 160 |
no test coverage detected