/*! mths.be/jsesc v0.5.0 by @mathias */ ;(function(root) {

// Detect free variables `exports`
var freeExports = typeof exports == 'object' && exports;

// Detect free variable `module`
var freeModule = typeof module == 'object' && module &&
        module.exports == freeExports && module;

// Detect free variable `global`, from Node.js or Browserified code,
// and use it as `root`
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
        root = freeGlobal;
}

/*--------------------------------------------------------------------------*/

var object = {};
var hasOwnProperty = object.hasOwnProperty;
var forOwn = function(object, callback) {
        var key;
        for (key in object) {
                if (hasOwnProperty.call(object, key)) {
                        callback(key, object[key]);
                }
        }
};

var extend = function(destination, source) {
        if (!source) {
                return destination;
        }
        forOwn(source, function(key, value) {
                destination[key] = value;
        });
        return destination;
};

var forEach = function(array, callback) {
        var length = array.length;
        var index = -1;
        while (++index < length) {
                callback(array[index]);
        }
};

var toString = object.toString;
var isArray = function(value) {
        return toString.call(value) == '[object Array]';
};
var isObject = function(value) {
        // This is a very simple check, but it’s good enough for what we need.
        return toString.call(value) == '[object Object]';
};
var isString = function(value) {
        return typeof value == 'string' ||
                toString.call(value) == '[object String]';
};
var isFunction = function(value) {
        // In a perfect world, the `typeof` check would be sufficient. However,
        // in Chrome 1–12, `typeof /x/ == 'object'`, and in IE 6–8
        // `typeof alert == 'object'` and similar for other host objects.
        return typeof value == 'function' ||
                toString.call(value) == '[object Function]';
};

/*--------------------------------------------------------------------------*/

// http://mathiasbynens.be/notes/javascript-escapes#single
var singleEscapes = {
        '"': '\\"',
        '\'': '\\\'',
        '\\': '\\\\',
        '\b': '\\b',
        '\f': '\\f',
        '\n': '\\n',
        '\r': '\\r',
        '\t': '\\t'
        // `\v` is omitted intentionally, because in IE < 9, '\v' == 'v'.
        // '\v': '\\x0B'
};
var regexSingleEscape = /["'\\\b\f\n\r\t]/;

var regexDigit = /[0-9]/;
var regexWhitelist = /[ !#-&\(-\[\]-~]/;

var jsesc = function(argument, options) {
        // Handle options
        var defaults = {
                'escapeEverything': false,
                'quotes': 'single',
                'wrap': false,
                'es6': false,
                'json': false,
                'compact': true,
                'indent': '\t',
                '__indent__': ''
        };
        var json = options && options.json;
        if (json) {
                defaults.quotes = 'double';
                defaults.wrap = true;
        }
        options = extend(defaults, options);
        if (options.quotes != 'single' && options.quotes != 'double') {
                options.quotes = 'single';
        }
        var quote = options.quotes == 'double' ? '"' : '\'';
        var compact = options.compact;
        var indent = options.indent;
        var oldIndent;
        var newLine = compact ? '' : '\n';
        var result;
        var isEmpty = true;

        if (json && argument && isFunction(argument.toJSON)) {
                argument = argument.toJSON();
        }

        if (!isString(argument)) {
                if (isArray(argument)) {
                        result = [];
                        options.wrap = true;
                        oldIndent = options.__indent__;
                        indent += oldIndent;
                        options.__indent__ = indent;
                        forEach(argument, function(value) {
                                isEmpty = false;
                                result.push(
                                        (compact ? '' : indent) +
                                        jsesc(value, options)
                                );
                        });
                        if (isEmpty) {
                                return '[]';
                        }
                        return '[' + newLine + result.join(',' + newLine) + newLine +
                                (compact ? '' : oldIndent) + ']';
                } else if (!isObject(argument)) {
                        if (json) {
                                // For some values (e.g. `undefined`, `function` objects),
                                // `JSON.stringify(value)` returns `undefined` (which isn’t valid
                                // JSON) instead of `'null'`.
                                return JSON.stringify(argument) || 'null';
                        }
                        return String(argument);
                } else { // it’s an object
                        result = [];
                        options.wrap = true;
                        oldIndent = options.__indent__;
                        indent += oldIndent;
                        options.__indent__ = indent;
                        forOwn(argument, function(key, value) {
                                isEmpty = false;
                                result.push(
                                        (compact ? '' : indent) +
                                        jsesc(key, options) + ':' +
                                        (compact ? '' : ' ') +
                                        jsesc(value, options)
                                );
                        });
                        if (isEmpty) {
                                return '{}';
                        }
                        return '{' + newLine + result.join(',' + newLine) + newLine +
                                (compact ? '' : oldIndent) + '}';
                }
        }

        var string = argument;
        // Loop over each code unit in the string and escape it
        var index = -1;
        var length = string.length;
        var first;
        var second;
        var codePoint;
        result = '';
        while (++index < length) {
                var character = string.charAt(index);
                if (options.es6) {
                        first = string.charCodeAt(index);
                        if ( // check if it’s the start of a surrogate pair
                                first >= 0xD800 && first <= 0xDBFF && // high surrogate
                                length > index + 1 // there is a next code unit
                        ) {
                                second = string.charCodeAt(index + 1);
                                if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
                                        // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
                                        codePoint = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
                                        result += '\\u{' + codePoint.toString(16).toUpperCase() + '}';
                                        index++;
                                        continue;
                                }
                        }
                }
                if (!options.escapeEverything) {
                        if (regexWhitelist.test(character)) {
                                // It’s a printable ASCII character that is not `"`, `'` or `\`,
                                // so don’t escape it.
                                result += character;
                                continue;
                        }
                        if (character == '"') {
                                result += quote == character ? '\\"' : character;
                                continue;
                        }
                        if (character == '\'') {
                                result += quote == character ? '\\\'' : character;
                                continue;
                        }
                }
                if (
                        character == '\0' &&
                        !json &&
                        !regexDigit.test(string.charAt(index + 1))
                ) {
                        result += '\\0';
                        continue;
                }
                if (regexSingleEscape.test(character)) {
                        // no need for a `hasOwnProperty` check here
                        result += singleEscapes[character];
                        continue;
                }
                var charCode = character.charCodeAt(0);
                var hexadecimal = charCode.toString(16).toUpperCase();
                var longhand = hexadecimal.length > 2 || json;
                var escaped = '\\' + (longhand ? 'u' : 'x') +
                        ('0000' + hexadecimal).slice(longhand ? -4 : -2);
                result += escaped;
                continue;
        }
        if (options.wrap) {
                result = quote + result + quote;
        }
        return result;
};

jsesc.version = '0.5.0';

/*--------------------------------------------------------------------------*/

// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
        typeof define == 'function' &&
        typeof define.amd == 'object' &&
        define.amd
) {
        define(function() {
                return jsesc;
        });
}       else if (freeExports && !freeExports.nodeType) {
        if (freeModule) { // in Node.js or RingoJS v0.8.0+
                freeModule.exports = jsesc;
        } else { // in Narwhal or RingoJS v0.7.0-
                freeExports.jsesc = jsesc;
        }
} else { // in Rhino or a web browser
        root.jsesc = jsesc;
}

}(this));