# all files / string-template/ compile.js

100% Statements 68/68
97.67% Branches 42/43
100% Functions 4/4
100% Lines 68/68

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    1431×

    1×
    1×

    1×

    1×
    1×

    1×

    1×
    76×
    76×
    76×

    76×
    228×
    228×
    228×
    228×

    228×
    152×

    228×
    6×

    222×
    222×
    146×

    76×

    76×
    374×

    374×
    228×

    228×
    82×

    146×

    146×

    76×

    76×
    38×
    184×

    184×
    111×

    73×

    38×
    38×
    38×

    38×
    39×

    39×
    22×

    17×

    39×
    1×

    39×

    39×
    187×
    113×

    74×
    74×
    74×
    74×

    39×

    1×
    184×
    184×

    1×

    16×

    1×

    12×

    1×

    1×

    1×

     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
                    Eif (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'
        }
    }