| @@ -372,9 +372,7 @@ | |||||
| tags = tags || exports.tags; | tags = tags || exports.tags; | ||||
| if (typeof tags === 'string') tags = tags.split(spaceRe); | if (typeof tags === 'string') tags = tags.split(spaceRe); | ||||
| if (tags.length !== 2) { | |||||
| throw new Error('Invalid tags: ' + tags.join(', ')); | |||||
| } | |||||
| if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', ')); | |||||
| var tagRes = escapeTags(tags); | var tagRes = escapeTags(tags); | ||||
| var scanner = new Scanner(template); | var scanner = new Scanner(template); | ||||
| @@ -403,8 +401,9 @@ | |||||
| var start, type, value, chr, token; | var start, type, value, chr, token; | ||||
| while (!scanner.eos()) { | while (!scanner.eos()) { | ||||
| start = scanner.pos; | start = scanner.pos; | ||||
| value = scanner.scanUntil(tagRes[0]); | |||||
| // Match any text between tags. | |||||
| value = scanner.scanUntil(tagRes[0]); | |||||
| if (value) { | if (value) { | ||||
| for (var i = 0, len = value.length; i < len; ++i) { | for (var i = 0, len = value.length; i < len; ++i) { | ||||
| chr = value.charAt(i); | chr = value.charAt(i); | ||||
| @@ -423,74 +422,54 @@ | |||||
| } | } | ||||
| } | } | ||||
| start = scanner.pos; | |||||
| // Match the opening tag. | // Match the opening tag. | ||||
| if (!scanner.scan(tagRes[0])) break; | if (!scanner.scan(tagRes[0])) break; | ||||
| hasTag = true; | hasTag = true; | ||||
| // Get the tag type. | |||||
| type = scanner.scan(tagRe) || 'name'; | type = scanner.scan(tagRe) || 'name'; | ||||
| // Skip any whitespace between tag and value. | |||||
| scanner.scan(whiteRe); | scanner.scan(whiteRe); | ||||
| // Extract the tag value. | |||||
| if (type === "=") { | |||||
| // Get the tag value. | |||||
| if (type === '=') { | |||||
| value = scanner.scanUntil(eqRe); | value = scanner.scanUntil(eqRe); | ||||
| scanner.scan(eqRe); | scanner.scan(eqRe); | ||||
| scanner.scanUntil(tagRes[1]); | scanner.scanUntil(tagRes[1]); | ||||
| } else if (type === "{") { | |||||
| var closeRe = new RegExp("\\s*" + escapeRe("}" + tags[1])); | |||||
| value = scanner.scanUntil(closeRe); | |||||
| } else if (type === '{') { | |||||
| value = scanner.scanUntil(new RegExp('\\s*' + escapeRe('}' + tags[1]))); | |||||
| scanner.scan(curlyRe); | scanner.scan(curlyRe); | ||||
| scanner.scanUntil(tagRes[1]); | scanner.scanUntil(tagRes[1]); | ||||
| type = "&"; | |||||
| type = '&'; | |||||
| } else { | } else { | ||||
| value = scanner.scanUntil(tagRes[1]); | value = scanner.scanUntil(tagRes[1]); | ||||
| } | } | ||||
| // Match the closing tag. | // Match the closing tag. | ||||
| if (!scanner.scan(tagRes[1])) { | |||||
| throw new Error('Unclosed tag at ' + scanner.pos); | |||||
| } | |||||
| // Check section nesting. | |||||
| if (type === '/') { | |||||
| if (sections.length === 0) { | |||||
| throw new Error('Unopened section "' + value + '" at ' + start); | |||||
| } | |||||
| var section = sections.pop(); | |||||
| if (section[1] !== value) { | |||||
| throw new Error('Unclosed section "' + section[1] + '" at ' + start); | |||||
| } | |||||
| } | |||||
| if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos); | |||||
| token = [type, value, start, scanner.pos]; | token = [type, value, start, scanner.pos]; | ||||
| tokens.push(token); | tokens.push(token); | ||||
| if (type === '#' || type === '^') { | if (type === '#' || type === '^') { | ||||
| sections.push(token); | sections.push(token); | ||||
| } else if (type === "name" || type === "{" || type === "&") { | |||||
| } else if (type === '/') { | |||||
| // Check section nesting. | |||||
| if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start); | |||||
| var openSection = sections.pop(); | |||||
| if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); | |||||
| } else if (type === 'name' || type === '{' || type === '&') { | |||||
| nonSpace = true; | nonSpace = true; | ||||
| } else if (type === "=") { | |||||
| } else if (type === '=') { | |||||
| // Set the tags for the next time around. | // Set the tags for the next time around. | ||||
| tags = value.split(spaceRe); | tags = value.split(spaceRe); | ||||
| if (tags.length !== 2) { | |||||
| throw new Error('Invalid tags at ' + start + ': ' + tags.join(', ')); | |||||
| } | |||||
| if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', ')); | |||||
| tagRes = escapeTags(tags); | tagRes = escapeTags(tags); | ||||
| } | } | ||||
| } | } | ||||
| // Make sure there are no open sections when we're done. | // Make sure there are no open sections when we're done. | ||||
| var section = sections.pop(); | |||||
| if (section) { | |||||
| throw new Error('Unclosed section "' + section[1] + '" at ' + scanner.pos); | |||||
| } | |||||
| var openSection = sections.pop(); | |||||
| if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); | |||||
| tokens = squashTokens(tokens); | tokens = squashTokens(tokens); | ||||