You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.8 KiB
143 lines
3.8 KiB
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' |
|
} |
|
}
|
|
|