Bones/node_modules/string-template/compile.js

143 lines
3.8 KiB
JavaScript
Raw Normal View History

2017-05-17 13:45:25 -04:00
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'
}
}