pax_global_header 0000666 0000000 0000000 00000000064 12374353214 0014516 g ustar 00root root 0000000 0000000 52 comment=8d47e39a463b1a954b8ca6661b7804166a773154
jsesc-0.5.0/ 0000775 0000000 0000000 00000000000 12374353214 0012627 5 ustar 00root root 0000000 0000000 jsesc-0.5.0/.gitattributes 0000664 0000000 0000000 00000000114 12374353214 0015516 0 ustar 00root root 0000000 0000000 # Automatically normalize line endings for all text-based files
* text=auto
jsesc-0.5.0/.gitignore 0000664 0000000 0000000 00000000347 12374353214 0014623 0 ustar 00root root 0000000 0000000 # Coverage report
coverage
# Installed npm modules
node_modules
# Folder view configuration files
.DS_Store
Desktop.ini
# Thumbnail cache files
._*
Thumbs.db
# Files that might appear on external disks
.Spotlight-V100
.Trashes
jsesc-0.5.0/.travis.yml 0000664 0000000 0000000 00000002562 12374353214 0014745 0 ustar 00root root 0000000 0000000 language: node_js
node_js:
- "0.10"
before_script:
- "npm install -g grunt-cli"
# Narwhal uses a hardcoded path to openjdk v6, so use that version
- "sudo apt-get update -qq"
- "sudo apt-get install -qq openjdk-6-jre"
- "PACKAGE=rhino1_7R3; wget http://ftp.mozilla.org/pub/mozilla.org/js/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
- "PACKAGE=rhino1_7R3; echo -e '#!/bin/sh\\njava -jar /opt/'$PACKAGE'/js.jar $@' | sudo tee /usr/local/bin/rhino && sudo chmod +x /usr/local/bin/rhino"
- "PACKAGE=ringojs-0.9; wget http://ringojs.org/downloads/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
- "PACKAGE=ringojs-0.9; sudo ln -s /opt/$PACKAGE/bin/ringo /usr/local/bin/ringo && sudo chmod +x /usr/local/bin/ringo"
- "PACKAGE=v0.3.2; wget https://github.com/280north/narwhal/archive/$PACKAGE.zip && sudo unzip $PACKAGE -d /opt/ && rm $PACKAGE.zip"
- "PACKAGE=narwhal-0.3.2; sudo ln -s /opt/$PACKAGE/bin/narwhal /usr/local/bin/narwhal && sudo chmod +x /usr/local/bin/narwhal"
# If the enviroment stores rt.jar in a different directory, find it and symlink the directory
- "PREFIX=/usr/lib/jvm; if [ ! -d $PREFIX/java-6-openjdk ]; then for d in $PREFIX/java-6-openjdk-*; do if [ -e $d/jre/lib/rt.jar ]; then sudo ln -s $d $PREFIX/java-6-openjdk; break; fi; done; fi"
script:
- "grunt ci"
after_script:
- "grunt shell:cover-coveralls"
jsesc-0.5.0/Gruntfile.js 0000664 0000000 0000000 00000003671 12374353214 0015133 0 ustar 00root root 0000000 0000000 module.exports = function(grunt) {
grunt.initConfig({
'shell': {
'options': {
'stdout': true,
'stderr': true,
'failOnError': true
},
'cover-html': {
'command': 'istanbul cover --report "html" --verbose --dir "coverage" "tests/tests.js"'
},
'cover-coveralls': {
'command': 'istanbul cover --verbose --dir "coverage" "tests/tests.js" && cat coverage/lcov.info | coveralls; rm -rf coverage/lcov*'
},
'test-narwhal': {
'command': 'echo "Testing in Narwhal..."; export NARWHAL_OPTIMIZATION=-1; narwhal "tests/tests.js"'
},
'test-phantomjs': {
'command': 'echo "Testing in PhantomJS..."; phantomjs "tests/tests.js"'
},
// Rhino 1.7R4 has a bug that makes it impossible to test in.
// https://bugzilla.mozilla.org/show_bug.cgi?id=775566
// To test, use Rhino 1.7R3, or wait (heh) for the 1.7R5 release.
'test-rhino': {
'command': 'echo "Testing in Rhino..."; rhino -opt -1 "tests.js"',
'options': {
'execOptions': {
'cwd': 'tests'
}
}
},
'test-ringo': {
'command': 'echo "Testing in Ringo..."; ringo -o -1 "tests/tests.js"'
},
'test-node': {
'command': 'echo "Testing in Node..."; node "tests/tests.js"'
},
'test-browser': {
'command': 'echo "Testing in a browser..."; open "tests/index.html"'
}
},
'template': {
'build': {
'options': {
// Generate the regular expressions dynamically using Regenerate
'data': require('./src/data.js')
},
'files': {
'jsesc.js': ['src/jsesc.js']
}
}
}
});
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-template');
grunt.registerTask('cover', 'shell:cover-html');
grunt.registerTask('ci', [
'shell:test-narwhal',
'shell:test-phantomjs',
'shell:test-rhino',
'shell:test-ringo',
'shell:test-node'
]);
grunt.registerTask('test', [
'ci',
'shell:test-browser'
]);
grunt.registerTask('default', [
'template',
'shell:test-node'
]);
};
jsesc-0.5.0/LICENSE-MIT.txt 0000664 0000000 0000000 00000002064 12374353214 0015103 0 ustar 00root root 0000000 0000000 Copyright Mathias Bynens
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
jsesc-0.5.0/README.md 0000664 0000000 0000000 00000030237 12374353214 0014113 0 ustar 00root root 0000000 0000000 # jsesc [](https://travis-ci.org/mathiasbynens/jsesc) [](https://coveralls.io/r/mathiasbynens/jsesc) [](https://gemnasium.com/mathiasbynens/jsesc)
This is a JavaScript library for [escaping JavaScript strings](http://mathiasbynens.be/notes/javascript-escapes) while generating the shortest possible valid ASCII-only output. [Here’s an online demo.](http://mothereff.in/js-escapes)
This can be used to avoid [mojibake](http://en.wikipedia.org/wiki/Mojibake) and other encoding issues, or even to [avoid errors](https://twitter.com/annevk/status/380000829643571200) when passing JSON-formatted data (which may contain U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR, or [lone surrogates](http://esdiscuss.org/topic/code-points-vs-unicode-scalar-values#content-14)) to a JavaScript parser or an UTF-8 encoder, respectively.
Feel free to fork if you see possible improvements!
## Installation
Via [Bower](http://bower.io/):
```bash
bower install jsesc
```
Via [Component](https://github.com/component/component):
```bash
component install mathiasbynens/jsesc
```
Via [npm](http://npmjs.org/):
```bash
npm install jsesc
```
In a browser:
```html
```
In [Node.js](http://nodejs.org/) and [RingoJS](http://ringojs.org/):
```js
var jsesc = require('jsesc');
```
In [Narwhal](http://narwhaljs.org/):
```js
var jsesc = require('jsesc').jsesc;
```
In [Rhino](http://www.mozilla.org/rhino/):
```js
load('jsesc.js');
```
Using an AMD loader like [RequireJS](http://requirejs.org/):
```js
require(
{
'paths': {
'jsesc': 'path/to/jsesc'
}
},
['jsesc'],
function(jsesc) {
console.log(jsesc);
}
);
```
## API
### `jsesc(value, options)`
This function takes a value and returns an escaped version of the value where any characters that are not printable ASCII symbols are escaped using the shortest possible (but valid) [escape sequences for use in JavaScript strings](http://mathiasbynens.be/notes/javascript-escapes). The first supported value type is strings:
```js
jsesc('Ich ♥ Bücher');
// → 'Ich \\u2665 B\\xFCcher'
jsesc('foo 𝌆 bar');
// → 'foo \\uD834\\uDF06 bar'
```
Instead of a string, the `value` can also be an array, or an object. In such cases, `jsesc` will return a stringified version of the value where any characters that are not printable ASCII symbols are escaped in the same way.
```js
// Escaping an array
jsesc([
'Ich ♥ Bücher', 'foo 𝌆 bar'
]);
// → '[\'Ich \\u2665 B\\xFCcher\',\'foo \\uD834\\uDF06 bar\']'
// Escaping an object
jsesc({
'Ich ♥ Bücher': 'foo 𝌆 bar'
});
// → '{\'Ich \\u2665 B\\xFCcher\':\'foo \\uD834\\uDF06 bar\'}'
```
The optional `options` argument accepts an object with the following options:
#### `quotes`
The default value for the `quotes` option is `'single'`. This means that any occurences of `'` in the input string will be escaped as `\'`, so that the output can be used in a string literal wrapped in single quotes.
```js
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.');
// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'single'
});
// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
// → "Lorem ipsum \"dolor\" sit \\'amet\\' etc."
```
If you want to use the output as part of a string literal wrapped in double quotes, set the `quotes` option to `'double'`.
```js
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'double'
});
// → 'Lorem ipsum \\"dolor\\" sit \'amet\' etc.'
// → "Lorem ipsum \\\"dolor\\\" sit 'amet' etc."
```
This setting also affects the output for arrays and objects:
```js
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'quotes': 'double'
});
// → '{"Ich \\u2665 B\\xFCcher":"foo \\uD834\\uDF06 bar"}'
jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
'quotes': 'double'
});
// → '["Ich \\u2665 B\\xFCcher","foo \\uD834\\uDF06 bar"]'
```
#### `wrap`
The `wrap` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output will be a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified through the `quotes` setting.
```js
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'single',
'wrap': true
});
// → '\'Lorem ipsum "dolor" sit \\\'amet\\\' etc.\''
// → "\'Lorem ipsum \"dolor\" sit \\\'amet\\\' etc.\'"
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'double',
'wrap': true
});
// → '"Lorem ipsum \\"dolor\\" sit \'amet\' etc."'
// → "\"Lorem ipsum \\\"dolor\\\" sit \'amet\' etc.\""
```
#### `es6`
The `es6` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, any astral Unicode symbols in the input will be escaped using [ECMAScript 6 Unicode code point escape sequences](http://mathiasbynens.be/notes/javascript-escapes#unicode-code-point) instead of using separate escape sequences for each surrogate half. If backwards compatibility with ES5 environments is a concern, don’t enable this setting. If the `json` setting is enabled, the value for the `es6` setting is ignored (as if it was `false`).
```js
// By default, the `es6` option is disabled:
jsesc('foo 𝌆 bar 💩 baz');
// → 'foo \\uD834\\uDF06 bar \\uD83D\\uDCA9 baz'
// To explicitly disable it:
jsesc('foo 𝌆 bar 💩 baz', {
'es6': false
});
// → 'foo \\uD834\\uDF06 bar \\uD83D\\uDCA9 baz'
// To enable it:
jsesc('foo 𝌆 bar 💩 baz', {
'es6': true
});
// → 'foo \\u{1D306} bar \\u{1F4A9} baz'
```
#### `escapeEverything`
The `escapeEverything` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, all the symbols in the output will be escaped, even printable ASCII symbols.
```js
jsesc('lolwat"foo\'bar', {
'escapeEverything': true
});
// → '\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72'
// → "\\x6C\\x6F\\x6C\\x77\\x61\\x74\\\"\\x66\\x6F\\x6F\\'\\x62\\x61\\x72"
```
This setting also affects the output for arrays and objects:
```js
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'escapeEverything': true
});
// → '{\'\x49\x63\x68\x20\u2665\x20\x42\xFC\x63\x68\x65\x72\':\'\x66\x6F\x6F\x20\uD834\uDF06\x20\x62\x61\x72\'}'
// → "{'\x49\x63\x68\x20\u2665\x20\x42\xFC\x63\x68\x65\x72':'\x66\x6F\x6F\x20\uD834\uDF06\x20\x62\x61\x72'}"
jsesc([ 'Ich ♥ Bücher': 'foo 𝌆 bar' ], {
'escapeEverything': true
});
// → '[\'\x49\x63\x68\x20\u2665\x20\x42\xFC\x63\x68\x65\x72\',\'\x66\x6F\x6F\x20\uD834\uDF06\x20\x62\x61\x72\']'
```
#### `compact`
The `compact` option takes a boolean value (`true` or `false`), and defaults to `true` (enabled). When enabled, the output for arrays and objects will be as compact as possible; it won’t be formatted nicely.
```js
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'compact': true // this is the default
});
// → '{\'Ich \u2665 B\xFCcher\':\'foo \uD834\uDF06 bar\'}'
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'compact': false
});
// → '{\n\t\'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
'compact': false
});
// → '[\n\t\'Ich \u2665 B\xFCcher\',\n\t\'foo \uD834\uDF06 bar\'\n]'
```
This setting has no effect on the output for strings.
#### `indent`
The `indent` option takes a string value, and defaults to `'\t'`. When the `compact` setting is enabled (`true`), the value of the `indent` option is used to format the output for arrays and objects.
```js
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'compact': false,
'indent': '\t' // this is the default
});
// → '{\n\t\'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
'compact': false,
'indent': ' '
});
// → '{\n \'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
jsesc([ 'Ich ♥ Bücher', 'foo 𝌆 bar' ], {
'compact': false,
'indent': ' '
});
// → '[\n \'Ich \u2665 B\xFCcher\',\n\ t\'foo \uD834\uDF06 bar\'\n]'
```
This setting has no effect on the output for strings.
#### `json`
The `json` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output is valid JSON. [Hexadecimal character escape sequences](http://mathiasbynens.be/notes/javascript-escapes#hexadecimal) and [the `\v` or `\0` escape sequences](http://mathiasbynens.be/notes/javascript-escapes#single) will not be used. Setting `json: true` implies `quotes: 'double', wrap: true, es6: false`, although these values can still be overridden if needed — but in such cases, the output won’t be valid JSON anymore.
```js
jsesc('foo\x00bar\xFF\uFFFDbaz', {
'json': true
});
// → '"foo\\u0000bar\\u00FF\\uFFFDbaz"'
jsesc({ 'foo\x00bar\xFF\uFFFDbaz': 'foo\x00bar\xFF\uFFFDbaz' }, {
'json': true
});
// → '{"foo\\u0000bar\\u00FF\\uFFFDbaz":"foo\\u0000bar\\u00FF\\uFFFDbaz"}'
jsesc([ 'foo\x00bar\xFF\uFFFDbaz', 'foo\x00bar\xFF\uFFFDbaz' ], {
'json': true
});
// → '["foo\\u0000bar\\u00FF\\uFFFDbaz","foo\\u0000bar\\u00FF\\uFFFDbaz"]'
// Values that are acceptable in JSON but aren’t strings, arrays, or object
// literals can’t be escaped, so they’ll just be preserved:
jsesc([ 'foo\x00bar', [1, '©', { 'foo': true, 'qux': null }], 42 ], {
'json': true
});
// → '["foo\\u0000bar",[1,"\\u00A9",{"foo":true,"qux":null}],42]'
// Values that aren’t allowed in JSON are run through `JSON.stringify()`:
jsesc([ undefined, -Infinity ], {
'json': true
});
// → '[null,null]'
```
**Note:** Using this option on objects or arrays that contain non-string values relies on `JSON.stringify()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](http://bestiejs.github.io/json3/).
### `jsesc.version`
A string representing the semantic version number.
### Using the `jsesc` binary
To use the `jsesc` binary in your shell, simply install jsesc globally using npm:
```bash
npm install -g jsesc
```
After that you will be able to escape strings from the command line:
```bash
$ jsesc 'föo ♥ bår 𝌆 baz'
f\xF6o \u2665 b\xE5r \uD834\uDF06 baz
```
To escape arrays or objects containing string values, use the `-o`/`--object` option:
```bash
$ jsesc --object '{ "föo": "♥", "bår": "𝌆 baz" }'
{'f\xF6o':'\u2665','b\xE5r':'\uD834\uDF06 baz'}
```
To prettify the output in such cases, use the `-p`/`--pretty` option:
```bash
$ jsesc --pretty '{ "föo": "♥", "bår": "𝌆 baz" }'
{
'f\xF6o': '\u2665',
'b\xE5r': '\uD834\uDF06 baz'
}
```
For valid JSON output, use the `-j`/`--json` option:
```bash
$ jsesc --json --pretty '{ "föo": "♥", "bår": "𝌆 baz" }'
{
"f\u00F6o": "\u2665",
"b\u00E5r": "\uD834\uDF06 baz"
}
```
Read a local JSON file, escape any non-ASCII symbols, and save the result to a new file:
```bash
$ jsesc --json --object < data-raw.json > data-escaped.json
```
Or do the same with an online JSON file:
```bash
$ curl -sL "http://git.io/aorKgQ" | jsesc --json --object > data-escaped.json
```
See `jsesc --help` for the full list of options.
## Support
This library has been tested in at least Chrome 27-29, Firefox 3-22, Safari 4-6, Opera 10-12, IE 6-10, Node.js v0.10.0, Narwhal 0.3.2, RingoJS 0.8-0.9, PhantomJS 1.9.0, and Rhino 1.7RC4.
**Note:** Using the `json` option on objects or arrays that contain non-string values relies on `JSON.parse()`. For legacy environments like IE ≤ 7, use [a `JSON` polyfill](http://bestiejs.github.io/json3/).
## Unit tests & code coverage
After cloning this repository, run `npm install` to install the dependencies needed for development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`.
Once that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, and web browsers as well, use `grunt test`.
To generate the code coverage report, use `grunt cover`.
## Author
| [](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](http://mathiasbynens.be/) |
## License
This library is available under the [MIT](http://mths.be/mit) license.
jsesc-0.5.0/bin/ 0000775 0000000 0000000 00000000000 12374353214 0013377 5 ustar 00root root 0000000 0000000 jsesc-0.5.0/bin/jsesc 0000775 0000000 0000000 00000006725 12374353214 0014446 0 ustar 00root root 0000000 0000000 #!/usr/bin/env node
(function() {
var fs = require('fs');
var stringEscape = require('../jsesc.js');
var strings = process.argv.splice(2);
var stdin = process.stdin;
var data;
var timeout;
var isObject = false;
var options = {};
var log = console.log;
var main = function() {
var option = strings[0];
if (/^(?:-h|--help|undefined)$/.test(option)) {
log(
'jsesc v%s - http://mths.be/jsesc',
stringEscape.version
);
log([
'\nUsage:\n',
'\tjsesc [string]',
'\tjsesc [-s | --single-quotes] [string]',
'\tjsesc [-d | --double-quotes] [string]',
'\tjsesc [-w | --wrap] [string]',
'\tjsesc [-e | --escape-everything] [string]',
'\tjsesc [-6 | --es6] [string]',
'\tjsesc [-j | --json] [string]',
'\tjsesc [-o | --object] [stringified_object]', // `JSON.parse()` the argument
'\tjsesc [-p | --pretty] [string]', // `compact: false`
'\tjsesc [-v | --version]',
'\tjsesc [-h | --help]',
'\nExamples:\n',
'\tjsesc \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tjsesc --json \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tjsesc --json --escape-everything \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tjsesc --double-quotes --wrap \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\techo \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\' | jsesc'
].join('\n'));
return process.exit(1);
}
if (/^(?:-v|--version)$/.test(option)) {
log('v%s', stringEscape.version);
return process.exit(1);
}
strings.forEach(function(string) {
// Process options
if (/^(?:-s|--single-quotes)$/.test(string)) {
options.quotes = 'single';
return;
}
if (/^(?:-d|--double-quotes)$/.test(string)) {
options.quotes = 'double';
return;
}
if (/^(?:-w|--wrap)$/.test(string)) {
options.wrap = true;
return;
}
if (/^(?:-6|--es6)$/.test(string)) {
options.es6 = true;
return;
}
if (/^(?:-e|--escape-everything)$/.test(string)) {
options.escapeEverything = true;
return;
}
if (/^(?:-j|--json)$/.test(string)) {
options.json = true;
return;
}
if (/^(?:-o|--object)$/.test(string)) {
isObject = true;
return;
}
if (/^(?:-p|--pretty)$/.test(string)) {
isObject = true;
options.compact = false;
return;
}
// Process string(s)
var result;
try {
if (isObject) {
string = JSON.parse(string);
}
result = stringEscape(string, options);
log(result);
} catch(error) {
log(error.message + '\n');
log('Error: failed to escape.');
log('If you think this is a bug in jsesc, please report it:');
log('https://github.com/mathiasbynens/jsesc/issues/new');
log(
'\nStack trace using jsesc@%s:\n',
stringEscape.version
);
log(error.stack);
return process.exit(1);
}
});
// Return with exit status 0 outside of the `forEach` loop, in case
// multiple strings were passed in.
return process.exit(0);
};
if (stdin.isTTY) {
// handle shell arguments
main();
} else {
// Either the script is called from within a non-TTY context,
// or `stdin` content is being piped in.
if (!process.stdout.isTTY) { // called from a non-TTY context
timeout = setTimeout(function() {
// if no piped data arrived after a while, handle shell arguments
main();
}, 250);
}
data = '';
stdin.on('data', function(chunk) {
clearTimeout(timeout);
data += chunk;
});
stdin.on('end', function() {
strings.push(data.trim());
main();
});
stdin.resume();
}
}());
jsesc-0.5.0/bower.json 0000664 0000000 0000000 00000000325 12374353214 0014640 0 ustar 00root root 0000000 0000000 {
"name": "jsesc",
"version": "0.5.0",
"main": "jsesc.js",
"ignore": [
"bin",
"coverage",
"man",
"src",
"tests",
".*",
"component.json",
"Gruntfile.js",
"node_modules",
"package.json"
]
}
jsesc-0.5.0/component.json 0000664 0000000 0000000 00000000527 12374353214 0015530 0 ustar 00root root 0000000 0000000 {
"name": "jsesc",
"version": "0.5.0",
"description": "A JavaScript library for escaping JavaScript strings while generating the shortest possible ASCII-only output.",
"repo": "mathiasbynens/jsesc",
"license": "MIT",
"scripts": [
"jsesc.js"
],
"main": "jsesc.js",
"keywords": [
"string",
"escape",
"javascript",
"tool"
]
}
jsesc-0.5.0/jsesc.js 0000664 0000000 0000000 00000016075 12374353214 0014305 0 ustar 00root root 0000000 0000000 /*! http://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));
jsesc-0.5.0/man/ 0000775 0000000 0000000 00000000000 12374353214 0013402 5 ustar 00root root 0000000 0000000 jsesc-0.5.0/man/jsesc.1 0000664 0000000 0000000 00000005274 12374353214 0014603 0 ustar 00root root 0000000 0000000 .Dd October 25, 2013
.Dt jsesc 1
.Sh NAME
.Nm jsesc
.Nd escape strings for use in JavaScript string literals
.Sh SYNOPSIS
.Nm
.Op Fl s | -single-quotes Ar string
.br
.Op Fl d | -double-quotes Ar string
.br
.Op Fl w | -wrap Ar string
.br
.Op Fl 6 | -es6 Ar string
.br
.Op Fl e | -escape-everything Ar string
.br
.Op Fl j | -json Ar string
.br
.Op Fl p | -object Ar string
.br
.Op Fl p | -pretty Ar string
.br
.Op Fl v | -version
.br
.Op Fl h | -help
.Sh DESCRIPTION
.Nm
escapes strings for use in JavaScript string literals while generating the shortest possible valid ASCII-only output.
.Sh OPTIONS
.Bl -ohang -offset
.It Sy "-s, --single-quotes"
Escape any occurences of ' in the input string as \\', so that the output can be used in a JavaScript string literal wrapped in single quotes.
.It Sy "-d, --double-quotes"
Escape any occurences of " in the input string as \\", so that the output can be used in a JavaScript string literal wrapped in double quotes.
.It Sy "-w, --wrap"
Make sure the output is a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified using the
.Ar -s | --single-quotes
or
.Ar -d | --double-quotes
settings.
.It Sy "-6, --es6"
Escape any astral Unicode symbols using ECMAScript 6 Unicode code point escape sequences.
.It Sy "-e, --escape-everything"
Escape all the symbols in the output, even printable ASCII symbols.
.It Sy "-j, --json"
Make sure the output is valid JSON. Hexadecimal character escape sequences and the \\v or \\0 escape sequences will not be used. Setting this flag enables the
.Ar -d | --double-quotes
and
.Ar -w | --wrap
settings.
.It Sy "-o, --object"
Treat the input as a JavaScript object rather than a string. Accepted values are flat arrays containing only string values, and flat objects containing only string values.
.It Sy "-p, --pretty"
Pretty-print the output for objects, using whitespace to make it more readable. Setting this flag enables the
.Ar -o | --object
setting.
.It Sy "-v, --version"
Print jsesc's version.
.It Sy "-h, --help"
Show the help screen.
.El
.Sh EXIT STATUS
The
.Nm jsesc
utility exits with one of the following values:
.Pp
.Bl -tag -width flag -compact
.It Li 0
.Nm
successfully escaped the given string and printed the result.
.It Li 1
.Nm
wasn't instructed to escape anything (for example, the
.Ar --help
flag was set); or, an error occurred.
.El
.Sh EXAMPLES
.Bl -ohang -offset
.It Sy "jsesc 'foo bar baz'"
Print an escaped version of the given string.
.It Sy echo\ 'foo bar baz'\ |\ jsesc
Print an escaped version of the string that gets piped in.
.El
.Sh BUGS
jsesc's bug tracker is located at .
.Sh AUTHOR
Mathias Bynens
.Sh WWW
jsesc-0.5.0/package.json 0000664 0000000 0000000 00000002063 12374353214 0015116 0 ustar 00root root 0000000 0000000 {
"name": "jsesc",
"version": "0.5.0",
"description": "A JavaScript library for escaping JavaScript strings while generating the shortest possible valid output.",
"homepage": "http://mths.be/jsesc",
"main": "jsesc.js",
"bin": "bin/jsesc",
"man": "man/jsesc.1",
"keywords": [
"string",
"escape",
"javascript",
"tool"
],
"licenses": [
{
"type": "MIT",
"url": "http://mths.be/mit"
}
],
"author": {
"name": "Mathias Bynens",
"url": "http://mathiasbynens.be/"
},
"repository": {
"type": "git",
"url": "https://github.com/mathiasbynens/jsesc.git"
},
"bugs": {
"url": "https://github.com/mathiasbynens/jsesc/issues"
},
"files": [
"LICENSE-MIT.txt",
"jsesc.js",
"bin/",
"man/"
],
"directories": {
"test": "tests"
},
"scripts": {
"test": "node tests/tests.js"
},
"devDependencies": {
"coveralls": "^2.10.0",
"grunt": "^0.4.5",
"grunt-shell": "^0.7.0",
"grunt-template": "^0.2.3",
"istanbul": "^0.3.0",
"qunit-extras": "^1.2.0",
"qunitjs": "~1.11.0",
"regenerate": "^0.6.2",
"requirejs": "^2.1.14"
}
}
jsesc-0.5.0/src/ 0000775 0000000 0000000 00000000000 12374353214 0013416 5 ustar 00root root 0000000 0000000 jsesc-0.5.0/src/data.js 0000664 0000000 0000000 00000000524 12374353214 0014666 0 ustar 00root root 0000000 0000000 var regenerate = require('regenerate');
var fs = require('fs');
var set = regenerate()
.addRange(0x20, 0x7E) // printable ASCII symbols
.remove('"') // not `"`
.remove('\'') // not `'`
.remove('\\'); // not `\`
module.exports = {
'whitelist': set.toString(),
'version': require('../package.json').version
};
jsesc-0.5.0/src/jsesc.js 0000664 0000000 0000000 00000016117 12374353214 0015071 0 ustar 00root root 0000000 0000000 /*! http://mths.be/jsesc v<%= version %> 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 = /<%= whitelist %>/;
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 = '<%= version %>';
/*--------------------------------------------------------------------------*/
// 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));
jsesc-0.5.0/tests/ 0000775 0000000 0000000 00000000000 12374353214 0013771 5 ustar 00root root 0000000 0000000 jsesc-0.5.0/tests/index.html 0000664 0000000 0000000 00000001644 12374353214 0015773 0 ustar 00root root 0000000 0000000
jsesc test suite
jsesc-0.5.0/tests/tests.js 0000664 0000000 0000000 00000055117 12374353214 0015502 0 ustar 00root root 0000000 0000000 (function(root) {
'use strict';
var noop = Function.prototype;
var load = (typeof require == 'function' && !(root.define && define.amd)) ?
require :
(!root.document && root.java && root.load) || noop;
var QUnit = (function() {
return root.QUnit || (
root.addEventListener || (root.addEventListener = noop),
root.setTimeout || (root.setTimeout = noop),
root.QUnit = load('../node_modules/qunitjs/qunit/qunit.js') || root.QUnit,
addEventListener === noop && delete root.addEventListener,
root.QUnit
);
}());
var qe = load('../node_modules/qunit-extras/qunit-extras.js');
if (qe) {
qe.runInContext(root);
}
// Extend `Object.prototype` to see if this library can handle it.
Object.prototype['\u2665'] = '...';
/** The `regenerate` object to test */
var jsesc = root.jsesc || (root.jsesc = (
jsesc = load('../jsesc.js') || root.jsesc,
jsesc = jsesc.jsesc || jsesc
));
/*--------------------------------------------------------------------------*/
// Quick and dirty test to see if we’re in PhantomJS or Node
var isNode = typeof process != 'undefined' && process.argv &&
process.argv[0] == 'node';
var runExtendedTests = root.phantom || isNode;
// explicitly call `QUnit.module()` instead of `module()`
// in case we are in a CLI environment
QUnit.module('jsesc');
test('common usage', function() {
equal(
typeof jsesc.version,
'string',
'`jsesc.version` must be a string'
);
equal(
jsesc('\0\x31'),
'\\x001',
'`\\0` followed by `1`'
);
equal(
jsesc('\0\x38'),
'\\x008',
'`\\0` followed by `8`'
);
equal(
jsesc('\0\x39'),
'\\x009',
'`\\0` followed by `9`'
);
equal(
jsesc('\0a'),
'\\0a',
'`\\0` followed by `a`'
);
equal(
jsesc('foo"bar\'baz', {
'quotes': 'LOLWAT' // invalid setting
}),
'foo"bar\\\'baz',
'Invalid `quotes` setting'
);
equal(
jsesc('\\x00'),
'\\\\x00',
'`\\\\x00` shouldn’t be changed to `\\\\0`'
);
equal(
jsesc('a\\x00'),
'a\\\\x00',
'`a\\\\x00` shouldn’t be changed to `\\\\0`'
);
equal(
jsesc('\\\x00'),
'\\\\\\0',
'`\\\\\\x00` should be changed to `\\\\\\0`'
);
equal(
jsesc('\\\\x00'),
'\\\\\\\\x00',
'`\\\\\\\\x00` shouldn’t be changed to `\\\\\\\\0`'
);
equal(
jsesc('lolwat"foo\'bar', {
'escapeEverything': true
}),
'\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72',
'escapeEverything'
);
equal(
jsesc('a\uD834\uDF06b', {
'es6': true
}),
'a\\u{1D306}b',
'es6'
);
equal(
jsesc('a\uD834\uDF06b\uD83D\uDCA9c', {
'es6': true
}),
'a\\u{1D306}b\\u{1F4A9}c',
'es6'
);
equal(
jsesc('a\uD834\uDF06b\uD83D\uDCA9c', {
'es6': true,
'escapeEverything': true
}),
'\\x61\\u{1D306}\\x62\\u{1F4A9}\\x63',
'es6 + escapeEverything'
);
equal(
jsesc({}, {
'compact': true
}),
'{}',
'Stringifying an empty object with `compact: true`'
);
equal(
jsesc({}, {
'compact': false
}),
'{}',
'Stringifying an empty object with `compact: false`'
);
equal(
jsesc([], {
'compact': true
}),
'[]',
'Stringifying an empty array with `compact: true`'
);
equal(
jsesc([], {
'compact': false
}),
'[]',
'Stringifying an empty array with `compact: false`'
);
// Stringifying flat objects containing only string values
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }),
'{\'foo\\0bar\\uFFFDbaz\':\'foo\\0bar\\uFFFDbaz\'}',
'Stringifying a flat object with default settings`'
);
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
'quotes': 'double'
}),
'{"foo\\0bar\\uFFFDbaz":"foo\\0bar\\uFFFDbaz"}',
'Stringifying a flat object with `quotes: \'double\'`'
);
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
'compact': false
}),
'{\n\t\'foo\\0bar\\uFFFDbaz\': \'foo\\0bar\\uFFFDbaz\'\n}',
'Stringifying a flat object with `compact: false`'
);
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
'compact': false,
'indent': ' '
}),
'{\n \'foo\\0bar\\uFFFDbaz\': \'foo\\0bar\\uFFFDbaz\'\n}',
'Stringifying a flat object with `compact: false, indent: \' \'`'
);
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
'escapeEverything': true
}),
'{\'\\x66\\x6F\\x6F\\0\\x62\\x61\\x72\\uFFFD\\x62\\x61\\x7A\':\'\\x66\\x6F\\x6F\\0\\x62\\x61\\x72\\uFFFD\\x62\\x61\\x7A\'}',
'Stringifying a flat object with `escapeEverything: true`'
);
// Stringifying flat arrays containing only string values
equal(
jsesc(['foo\x00bar\uFFFDbaz', '\xA9'], {
'escapeEverything': true
}),
'[\'\\x66\\x6F\\x6F\\0\\x62\\x61\\x72\\uFFFD\\x62\\x61\\x7A\',\'\\xA9\']',
'Stringifying a flat array with `escapeEverything: true`'
);
equal(
jsesc(['foo\x00bar\uFFFDbaz', '\xA9'], {
'compact': false
}),
'[\n\t\'foo\\0bar\\uFFFDbaz\',\n\t\'\\xA9\'\n]',
'Stringifying a flat array with `compact: false`'
);
// JSON
equal(
jsesc('foo\x00bar\xFF\uFFFDbaz', {
'json': true
}),
'"foo\\u0000bar\\u00FF\\uFFFDbaz"',
'JSON-stringifying a string'
);
equal(
jsesc('foo\x00bar\uFFFDbaz', {
'escapeEverything': true,
'json': true
}),
'"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"',
'JSON-stringifying a string with `escapeEverything: true`'
);
equal(
jsesc({ 'foo\x00bar\uFFFDbaz': 'foo\x00bar\uFFFDbaz' }, {
'escapeEverything': true,
'json': true
}),
'{"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A":"\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"}',
'JSON-stringifying a flat object with `escapeEverything: true`'
);
equal(
jsesc(['foo\x00bar\uFFFDbaz', 'foo\x00bar\uFFFDbaz'], {
'escapeEverything': true,
'json': true
}),
'["\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A","\\u0066\\u006F\\u006F\\u0000\\u0062\\u0061\\u0072\\uFFFD\\u0062\\u0061\\u007A"]',
'JSON-stringifying a flat array with `escapeEverything: true`'
);
equal(
jsesc('foo\x00bar', {
'json': true,
'wrap': false // override default `wrap: true` when `json` is enabled
}),
'foo\\u0000bar',
'Escaping as JSON with `wrap: false`'
);
equal(
jsesc('foo "\x00" bar', {
'json': true,
'wrap': false // override default `wrap: true` when `json` is enabled
}),
'foo \\"\\u0000\\" bar',
'Escaping as JSON with `wrap: false` escapes double quotes correctly'
);
equal(
jsesc('foo "\x00" bar \' qux', {
'json': true,
'quotes': 'single', // override default `quotes: 'double'` when `json` is enabled
'wrap': false // override default `wrap: true` when `json` is enabled
}),
'foo "\\u0000" bar \\\' qux',
'Escaping as JSON with `wrap: false, quotes: \'single\'`'
);
equal(
jsesc('foo\uD834\uDF06bar\xA9baz', {
'json': true,
'es6': true // override default `es6: false` when `json` is enabled
}),
'"foo\\u{1D306}bar\\u00A9baz"',
'Escaping as JSON with `es6: true`'
);
var tmp = {
'shouldn\u2019t be here': 10,
'toJSON': function() {
return {
'hello': 'world',
'\uD83D\uDCA9': 'foo',
'pile': '\uD83D\uDCA9'
};
}
};
equal(
jsesc(tmp, { 'json' : true }),
'{"hello":"world","\\uD83D\\uDCA9":"foo","pile":"\\uD83D\\uDCA9"}',
'`toJSON` methods are called when `json: true`'
);
notEqual(
jsesc(tmp),
'{"hello":"world","\\uD83D\\uDCA9":"foo","pile":"\\uD83D\\uDCA9"}',
'`toJSON` methods are not called when `json: false`'
);
});
if (runExtendedTests) {
test('advanced tests', function() {
var map = function(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
};
// taken from http://mths.be/punycode
var stringFromCharCode = String.fromCharCode;
var ucs2encode = function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
};
var allSymbols = '';
var codePoint;
var symbol = '';
// Generate strings based on code points. Trickier than it seems:
// http://mathiasbynens.be/notes/javascript-encoding
for (codePoint = 0x000000; codePoint <= 0x10FFFF; codePoint++) {
symbol = ucs2encode(codePoint);
// ok(
// eval('\'' + jsesc(symbol) + '\'') == symbol,
// 'U+' + codePoint.toString(16).toUpperCase()
// );
allSymbols += symbol + ' ';
}
ok(
eval('\'' + jsesc(allSymbols) + '\'') == allSymbols,
'All Unicode symbols, space-separated, default quote type (single quotes)'
);
ok(
eval('\'' + jsesc(allSymbols, {
'quotes': 'single'
}) + '\'') == allSymbols,
'All Unicode symbols, space-separated, single quotes'
);
ok(
eval(jsesc(allSymbols, {
'quotes': 'single',
'wrap': true
})) == allSymbols,
'All Unicode symbols, space-separated, single quotes, auto-wrap'
);
ok(
eval('"' + jsesc(allSymbols, {
'quotes': 'double'
}) + '"') == allSymbols,
'All Unicode symbols, space-separated, double quotes'
);
ok(
eval(jsesc(allSymbols, {
'quotes': 'double',
'wrap': true
})) == allSymbols,
'All Unicode symbols, space-separated, double quotes, auto-wrap'
);
// Some of these depend on `JSON.parse()`, so only test them in Node
if (isNode) {
var testArray = [
undefined, Infinity, new Number(Infinity), -Infinity,
new Number(-Infinity), 0, new Number(0), -0, new Number(-0), +0,
new Number(+0), new Function(), 'str',
function zomg() { return 'desu'; }, null, true, new Boolean(true),
false, new Boolean(false), {
"foo": 42, "hah": [ 1, 2, 3, { "foo" : 42 } ]
}
];
equal(
jsesc(testArray, {
'json': false
}),
'[undefined,Infinity,Infinity,-Infinity,-Infinity,0,0,0,0,0,0,function anonymous() {\n\n},\'str\',function zomg() { return \'desu\'; },null,true,true,false,false,{\'foo\':42,\'hah\':[1,2,3,{\'foo\':42}]}]',
'Escaping a non-flat array with all kinds of values'
);
equal(
jsesc(testArray, {
'json': true
}),
'[null,null,null,null,null,0,0,0,0,0,0,null,"str",null,null,true,true,false,false,{"foo":42,"hah":[1,2,3,{"foo":42}]}]',
'Escaping a non-flat array with all kinds of values, with `json: true`'
);
equal(
jsesc(testArray, {
'json': true,
'compact': false
}),
'[\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\tnull,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\tnull,\n\t"str",\n\tnull,\n\tnull,\n\ttrue,\n\ttrue,\n\tfalse,\n\tfalse,\n\t{\n\t\t"foo": 42,\n\t\t"hah": [\n\t\t\t1,\n\t\t\t2,\n\t\t\t3,\n\t\t\t{\n\t\t\t\t"foo": 42\n\t\t\t}\n\t\t]\n\t}\n]',
'Escaping a non-flat array with all kinds of values, with `json: true, compact: false`'
);
}
});
}
// Test binary
if (isNode) {
asyncTest('jsesc binary', function() {
var exec = require('child_process').exec;
var shellTest = function(command, callback) {
exec(command, function(error, stdout, stderr) {
callback({
'stdout': stdout,
'stderr': stderr,
'exitStatus': error ? error.code : 0
});
});
};
var tests = [
{
'description': 'No arguments',
'command': './bin/jsesc',
'expected': {
'exitStatus': 1
}
},
{
'description': '-h option',
'command': './bin/jsesc -h',
'expected': {
'exitStatus': 1
}
},
{
'description': '--help option',
'command': './bin/jsesc --help',
'expected': {
'exitStatus': 1
}
},
{
'description': '-v option',
'command': './bin/jsesc -v',
'expected': {
'exitStatus': 1
}
},
{
'description': '--version option',
'command': './bin/jsesc --version',
'expected': {
'exitStatus': 1
}
},
{
'description': 'No options',
'command': './bin/jsesc "f\xF6o \u2665 b\xE5r \uD834\uDF06 baz"',
'expected': {
'stdout': 'f\\xF6o \\u2665 b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': 'No options, piping content',
'command': 'echo "f\xF6o \u2665 b\xE5r \uD834\uDF06 baz" | ./bin/jsesc',
'expected': {
'stdout': 'f\\xF6o \\u2665 b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-s option',
'command': './bin/jsesc -s f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-s option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -s',
'expected': {
'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--single-quotes option',
'command': './bin/jsesc --single-quotes f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--single-quotes option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --single-quotes',
'expected': {
'stdout': 'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-d option',
'command': './bin/jsesc -d f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-d option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -d',
'expected': {
'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--double-quotes option',
'command': './bin/jsesc --double-quotes f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--double-quotes option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --double-quotes',
'expected': {
'stdout': 'f\\xF6o \\u2665 \'\\"\'\\" b\\xE5r \\uD834\\uDF06 baz\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-w option',
'command': './bin/jsesc -w f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-w option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -w',
'expected': {
'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--wrap option',
'command': './bin/jsesc --wrap f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--wrap option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --wrap',
'expected': {
'stdout': '\'f\\xF6o \\u2665 \\\'"\\\'" b\\xE5r \\uD834\\uDF06 baz\'\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-6 option',
'command': './bin/jsesc -6 a\uD834\uDF06b\uD83D\uDCA9c',
'expected': {
'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-6 option, piping content',
'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc -6',
'expected': {
'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--es6 option',
'command': './bin/jsesc --es6 a\uD834\uDF06b\uD83D\uDCA9c',
'expected': {
'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--es6 option, piping content',
'command': 'echo a\uD834\uDF06b\uD83D\uDCA9c | ./bin/jsesc --es6',
'expected': {
'stdout': 'a\\u{1D306}b\\u{1F4A9}c\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-e option',
'command': './bin/jsesc -e f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-e option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -e',
'expected': {
'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--escape-everything option',
'command': './bin/jsesc --escape-everything f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--escape-everything option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --escape-everything',
'expected': {
'stdout': '\\x66\\xF6\\x6F\\x20\\u2665\\x20\\\'\\"\\\'\\"\\x20\\x62\\xE5\\x72\\x20\\uD834\\uDF06\\x20\\x62\\x61\\x7A\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-j option',
'command': './bin/jsesc -j f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-j option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc -j',
'expected': {
'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--json option',
'command': './bin/jsesc --json f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz',
'expected': {
'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--json option, piping content',
'command': 'echo f\xF6o\\ \u2665\\ \\\'\\"\\\'\\"\\ b\xE5r\\ \uD834\uDF06\\ baz | ./bin/jsesc --json',
'expected': {
'stdout': '"f\\u00F6o \\u2665 \'\\"\'\\" b\\u00E5r \\uD834\\uDF06 baz"\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-o option',
'command': './bin/jsesc -o \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
'expected': {
'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-o option, piping content',
'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc -o',
'expected': {
'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--object option',
'command': './bin/jsesc --object \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
'expected': {
'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--object option, piping content',
'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --object',
'expected': {
'stdout': '{\'f\\xF6o\':\'b\\xE5r \\uD834\\uDF06 baz\'}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-p option',
'command': './bin/jsesc --json -p \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
'expected': {
'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '-p option, piping content',
'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --json -p',
'expected': {
'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--pretty option',
'command': './bin/jsesc --json --pretty \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\}',
'expected': {
'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
'stderr': '',
'exitStatus': 0
}
},
{
'description': '--pretty option, piping content',
'command': 'echo \\{\\"f\xF6o\\":\\"b\xE5r\\ \uD834\uDF06\\ baz\\"\\} | ./bin/jsesc --json --pretty',
'expected': {
'stdout': '{\n\t"f\\u00F6o": "b\\u00E5r \\uD834\\uDF06 baz"\n}\n',
'stderr': '',
'exitStatus': 0
}
}
];
var counter = tests.length;
function done() {
--counter || QUnit.start();
}
tests.forEach(function(object) {
shellTest(object.command, function(data) {
// We can’t use `deepEqual` since sometimes not all expected values are provided
Object.keys(object.expected).forEach(function(key) {
equal(object.expected[key], data[key], object.description);
});
done();
});
});
});
}
/*--------------------------------------------------------------------------*/
// configure QUnit and call `QUnit.start()` for
// Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
if (!root.document || root.phantom) {
QUnit.config.noglobals = true;
QUnit.start();
}
}(typeof global == 'object' && global || this));