| var template = require("./index") |
| |
| var whitespaceRegex = /["'\\\n\r\u2028\u2029]/g |
| var nargs = /\{[0-9a-zA-Z]+\}/g |
| |
| var replaceTemplate = |
| " var args\n" + |
| " var result\n" + |
| " if (arguments.length === 1 && typeof arguments[0] === \"object\") {\n" + |
| " args = arguments[0]\n" + |
| " } else {\n" + |
| " args = arguments" + |
| " }\n\n" + |
| " if (!args || !(\"hasOwnProperty\" in args)) {\n" + |
| " args = {}\n" + |
| " }\n\n" + |
| " return {0}" |
| |
| var literalTemplate = "\"{0}\"" |
| var argTemplate = "(result = args.hasOwnProperty(\"{0}\") ? " + |
| "args[\"{0}\"] : null, \n " + |
| "(result === null || result === undefined) ? \"\" : result)" |
| |
| module.exports = compile |
| |
| function compile(string, inline) { |
| var replacements = string.match(nargs) |
| var interleave = string.split(nargs) |
| var replace = [] |
| |
| for (var i = 0; i < interleave.length; i++) { |
| var current = interleave[i]; |
| var replacement = replacements[i]; |
| var escapeLeft = current.charAt(current.length - 1) |
| var escapeRight = (interleave[i + 1] || "").charAt(0) |
| |
| if (replacement) { |
| replacement = replacement.substring(1, replacement.length - 1) |
| } |
| |
| if (escapeLeft === "{" && escapeRight === "}") { |
| replace.push(current + replacement) |
| } else { |
| replace.push(current); |
| if (replacement) { |
| replace.push({ name: replacement }) |
| } |
| } |
| } |
| |
| var prev = [""] |
| |
| for (var j = 0; j < replace.length; j++) { |
| var curr = replace[j] |
| |
| if (String(curr) === curr) { |
| var top = prev[prev.length - 1] |
| |
| if (String(top) === top) { |
| prev[prev.length - 1] = top + curr |
| } else { |
| prev.push(curr) |
| } |
| } else { |
| prev.push(curr) |
| } |
| } |
| |
| replace = prev |
| |
| if (inline) { |
| for (var k = 0; k < replace.length; k++) { |
| var token = replace[k] |
| |
| if (String(token) === token) { |
| replace[k] = template(literalTemplate, escape(token)) |
| } else { |
| replace[k] = template(argTemplate, escape(token.name)) |
| } |
| } |
| |
| var replaceCode = replace.join(" +\n ") |
| var compiledSource = template(replaceTemplate, replaceCode) |
| return new Function(compiledSource) |
| } |
| |
| return function template() { |
| var args |
| |
| if (arguments.length === 1 && typeof arguments[0] === "object") { |
| args = arguments[0] |
| } else { |
| args = arguments |
| } |
| |
| if (!args || !("hasOwnProperty" in args)) { |
| args = {} |
| } |
| |
| var result = [] |
| |
| for (var i = 0; i < replace.length; i++) { |
| if (i % 2 === 0) { |
| result.push(replace[i]) |
| } else { |
| var argName = replace[i].name |
| var arg = args.hasOwnProperty(argName) ? args[argName] : null |
| if (arg !== null || arg !== undefined) { |
| result.push(arg) |
| } |
| } |
| } |
| |
| return result.join("") |
| } |
| } |
| |
| function escape(string) { |
| string = '' + string; |
| |
| return string.replace(whitespaceRegex, escapedWhitespace); |
| } |
| |
| function escapedWhitespace(character) { |
| // Escape all characters not included in SingleStringCharacters and |
| // DoubleStringCharacters on |
| // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4 |
| switch (character) { |
| case '"': |
| case "'": |
| case '\\': |
| return '\\' + character |
| // Four possible LineTerminator characters need to be escaped: |
| case '\n': |
| return '\\n' |
| case '\r': |
| return '\\r' |
| case '\u2028': |
| return '\\u2028' |
| case '\u2029': |
| return '\\u2029' |
| } |
| } |