diff --git a/.github/issue_template.md b/.github/issue_template.md
index 3fd3598c..de5b728a 100644
--- a/.github/issue_template.md
+++ b/.github/issue_template.md
@@ -1,6 +1,10 @@
-If you are submitting a bug because you are receiving an error or because this
-project is incompatible with the [official JSON5
-specification][spec], please continue.
+If you are reporting a security vulnerability, please do not submit an issue.
+Instead, follow the guidelines described in our
+[security policy](../blob/main/SECURITY.md).
+
+If you are submitting a bug report because you are receiving an error or because
+this project is incompatible with the [official JSON5 specification][spec],
+please continue.
If you are submitting a feature request or code improvement that is compatible
with the [official JSON5 specification][spec], please continue.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 647597ea..29da2850 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,3 +1,7 @@
+If you are patching a security vulnerability, please do not submit a pull
+request. Instead, follow the guidelines described in our
+[security policy](../blob/main/SECURITY.md).
+
If you are submitting a bug fix for an an error or fixing an incompatibility
with the [official JSON5 specification][spec], please continue.
diff --git a/.travis.yml b/.travis.yml
index 7716b7b5..931847ea 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,4 +3,3 @@ node_js:
- "11"
- "10"
- "8"
- - "6"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b9aa0d2..5d04cf06 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,31 @@
### Unreleased [[code][c-unreleased], [diff][d-unreleased]]
-[c-unreleased]: https://github.com/json5/json5/tree/master
-[d-unreleased]: https://github.com/json5/json5/compare/v2.2.0...HEAD
+[c-unreleased]: https://github.com/json5/json5/tree/main
+[d-unreleased]: https://github.com/json5/json5/compare/v2.2.3...HEAD
+
+### v2.2.3 [[code][c2.2.3], [diff][d2.2.3]]
+
+[c2.2.3]: https://github.com/json5/json5/tree/v2.2.3
+[d2.2.3]: https://github.com/json5/json5/compare/v2.2.2...v2.2.3
+
+- Fix: json5@2.2.3 is now the 'latest' release according to npm instead of
+ v1.0.2. ([#299])
+
+### v2.2.2 [[code][c2.2.2], [diff][d2.2.2]]
+
+[c2.2.2]: https://github.com/json5/json5/tree/v2.2.2
+[d2.2.2]: https://github.com/json5/json5/compare/v2.2.1...v2.2.2
+
+- Fix: Properties with the name `__proto__` are added to objects and arrays.
+ ([#199]) This also fixes a prototype pollution vulnerability reported by
+ Jonathan Gregson! ([#295]).
+
+### v2.2.1 [[code][c2.2.1], [diff][d2.2.1]]
+
+[c2.2.1]: https://github.com/json5/json5/tree/v2.2.1
+[d2.2.1]: https://github.com/json5/json5/compare/v2.2.0...v2.2.1
+
+- Fix: Removed dependence on minimist to patch CVE-2021-44906. ([#266])
### v2.2.0 [[code][c2.2.0], [diff][d2.2.0]]
@@ -353,6 +377,7 @@ parser for the regular JSON format.
[#182]: https://github.com/json5/json5/issues/182
[#187]: https://github.com/json5/json5/issues/187
[#196]: https://github.com/json5/json5/issues/196
+[#199]: https://github.com/json5/json5/issues/199
[#208]: https://github.com/json5/json5/issues/208
[#210]: https://github.com/json5/json5/issues/210
[#222]: https://github.com/json5/json5/issues/222
@@ -360,3 +385,6 @@ parser for the regular JSON format.
[#229]: https://github.com/json5/json5/issues/229
[#236]: https://github.com/json5/json5/issues/236
[#244]: https://github.com/json5/json5/issues/244
+[#266]: https://github.com/json5/json5/issues/266
+[#295]: https://github.com/json5/json5/issues/295
+[#299]: https://github.com/json5/json5/issues/299
diff --git a/README.md b/README.md
index 6049d02c..00ee7939 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,39 @@
# JSON5 – JSON for Humans
-[![Build Status](https://travis-ci.com/json5/json5.svg)][Build Status]
-[![Coverage
+[![Build Status](https://app.travis-ci.com/json5/json5.svg?branch=main)][Build
+Status] [![Coverage
Status](https://coveralls.io/repos/github/json5/json5/badge.svg)][Coverage
Status]
-The JSON5 Data Interchange Format (JSON5) is a superset of [JSON] that aims to
-alleviate some of the limitations of JSON by expanding its syntax to include
-some productions from [ECMAScript 5.1].
-
-This JavaScript library is the official reference implementation for JSON5
-parsing and serialization libraries.
-
-[Build Status]: https://travis-ci.com/json5/json5
+JSON5 is an extension to the popular [JSON] file format that aims to be
+easier to **write and maintain _by hand_ (e.g. for config files)**.
+It is _not intended_ to be used for machine-to-machine communication.
+(Keep using JSON or other file formats for that. 🙂)
+
+JSON5 was started in 2012, and as of 2022, now gets **[>65M downloads/week](https://www.npmjs.com/package/json5)**,
+ranks in the **[top 0.1%](https://gist.github.com/anvaka/8e8fa57c7ee1350e3491)** of the most depended-upon packages on npm,
+and has been adopted by major projects like
+**[Chromium](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5;drc=5de823b36e68fd99009a29281b17bc3a1d6b329c),
+[Next.js](https://github.com/vercel/next.js/blob/b88f20c90bf4659b8ad5cb2a27956005eac2c7e8/packages/next/lib/find-config.ts#L43-L46),
+[Babel](https://babeljs.io/docs/en/config-files#supported-file-extensions),
+[Retool](https://community.retool.com/t/i-am-attempting-to-append-several-text-fields-to-a-google-sheet-but-receiving-a-json5-invalid-character-error/7626),
+[WebStorm](https://www.jetbrains.com/help/webstorm/json.html),
+and [more](https://github.com/json5/json5/wiki/In-the-Wild)**.
+It's also natively supported on **[Apple platforms](https://developer.apple.com/documentation/foundation/jsondecoder/3766916-allowsjson5)**
+like **MacOS** and **iOS**.
+
+Formally, the **[JSON5 Data Interchange Format](https://spec.json5.org/)** is a superset of JSON
+(so valid JSON files will always be valid JSON5 files)
+that expands its syntax to include some productions from [ECMAScript 5.1] (ES5).
+It's also a strict _subset_ of ES5, so valid JSON5 files will always be valid ES5.
+
+This JavaScript library is a reference implementation for JSON5 parsing and serialization,
+and is directly used in many of the popular projects mentioned above
+(where e.g. extreme performance isn't necessary),
+but others have created [many other libraries](https://github.com/json5/json5/wiki/In-the-Wild)
+across many other platforms.
+
+[Build Status]: https://app.travis-ci.com/json5/json5
[Coverage Status]: https://coveralls.io/github/json5/json5
@@ -52,7 +73,9 @@ been extended to JSON5.
[IEEE 754]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
-## Short Example
+## Example
+Kitchen-sink example:
+
```js
{
// comments
@@ -68,26 +91,42 @@ No \\n's!",
}
```
+A more real-world example is [this config file](https://github.com/chromium/chromium/blob/feb3c9f670515edf9a88f185301cbd7794ee3e52/third_party/blink/renderer/platform/runtime_enabled_features.json5)
+from the Chromium/Blink project.
+
## Specification
For a detailed explanation of the JSON5 format, please read the [official
specification](https://json5.github.io/json5-spec/).
-## Installation
+## Installation and Usage
### Node.js
```sh
npm install json5
```
+#### CommonJS
```js
const JSON5 = require('json5')
```
+#### Modules
+```js
+import JSON5 from 'json5'
+```
+
### Browsers
+#### UMD
```html
-
+
+
```
-This will create a global `JSON5` variable.
+#### Modules
+```html
+
+```
## API
The JSON5 API is compatible with the [JSON API].
@@ -195,18 +234,27 @@ run lint` before submitting pull requests. Please use an editor that supports
[EditorConfig](http://editorconfig.org/).
### Issues
-To report bugs or request features regarding the JSON5 data format, please
-submit an issue to the [official specification
-repository](https://github.com/json5/json5-spec).
+To report bugs or request features regarding the JSON5 **data format**,
+please submit an issue to the official
+**[_specification_ repository](https://github.com/json5/json5-spec)**.
+
+Note that we will never add any features that make JSON5 incompatible with ES5;
+that compatibility is a fundamental premise of JSON5.
+
+To report bugs or request features regarding this **JavaScript implementation**
+of JSON5, please submit an issue to **_this_ repository**.
-To report bugs or request features regarding the JavaScript implementation of
-JSON5, please submit an issue to this repository.
+### Security Vulnerabilities and Disclosures
+To report a security vulnerability, please follow the follow the guidelines
+described in our [security policy](./SECURITY.md).
## License
MIT. See [LICENSE.md](./LICENSE.md) for details.
## Credits
-[Assem Kishore](https://github.com/aseemk) founded this project.
+[Aseem Kishore](https://github.com/aseemk) founded this project.
+He wrote a [blog post](https://aseemk.substack.com/p/ignore-the-f-ing-haters-json5)
+about the journey and lessons learned 10 years in.
[Michael Bolin](http://bolinfest.com/) independently arrived at and published
some of these same ideas with awesome explanations and detail. Recommended
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..2eaadb65
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,45 @@
+# JSON5 Security Policy
+
+We take security seriously. Responsible reporting and disclosure of security
+vulnerabilities is important for the protection and privacy of our users. If you
+discover any security vulnerabilities, please follow these guidelines.
+
+Published security advisories are available on our [GitHub Security Advisories]
+page.
+
+To report a vulnerability, please draft a [new security advisory on GitHub]. Any
+fields that you are unsure of or don't understand can be left at their default
+values. The important part is that the vulnerability is reported. Once the
+security advisory draft has been created, we will validate the vulnerability and
+coordinate with you to fix it, release a patch, and responsibly disclose the
+vulnerability to the public. Read GitHub's documentation on [privately reporting
+a security vulnerability] for details.
+
+If you are unable to draft a security advisory, or if you need help or have
+security related questions, please send an email to [security@json5.org].
+
+Please do not report undisclosed vulnerabilities on public sites or forums,
+including GitHub issues and pull requests. Reporting vulnerabilities to the
+public could allow attackers to exploit vulnerable applications before we have
+been able to release a patch and before applications have had time to install
+the patch. Once we have released a patch and sufficient time has passed for
+applications to install the patch, we will disclose the vulnerability to the
+public, at which time you will be free to publish details of the vulnerability
+on public sites and forums.
+
+If you have a fix for a security vulnerability, please do not submit a GitHub
+pull request. Instead, report the vulnerability as described in this policy.
+Once we have verified the vulnerability, we can create a [temporary private
+fork] to collaborate on a patch.
+
+We appreciate your cooperation in helping keep our users safe by following this
+policy.
+
+[github security advisories]: https://github.com/json5/json5/security/advisories
+[new security advisory on github]:
+ https://github.com/json5/json5/security/advisories/new
+[privately reporting a security vulnerability]:
+ https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability
+[security@json5.org]: mailto:security@json5.org
+[temporary private fork]:
+ https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-repository-security-vulnerability
diff --git a/lib/cli.js b/lib/cli.js
index de852f15..93cb8092 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -2,37 +2,17 @@
const fs = require('fs')
const path = require('path')
-const minimist = require('minimist')
const pkg = require('../package.json')
const JSON5 = require('./')
-const argv = minimist(process.argv.slice(2), {
- alias: {
- 'convert': 'c',
- 'space': 's',
- 'validate': 'v',
- 'out-file': 'o',
- 'version': 'V',
- 'help': 'h',
- },
- boolean: [
- 'convert',
- 'validate',
- 'version',
- 'help',
- ],
- string: [
- 'space',
- 'out-file',
- ],
-})
+const argv = parseArgs()
if (argv.version) {
version()
} else if (argv.help) {
usage()
} else {
- const inFilename = argv._[0]
+ const inFilename = argv.defaults[0]
let readStream
if (inFilename) {
@@ -65,7 +45,7 @@ if (argv.version) {
// --convert is for backward compatibility with v0.5.1. If
// specified with and not --out-file, then a file with
// the same name but with a .json extension will be written.
- if (argv.convert && inFilename && !argv.o) {
+ if (argv.convert && inFilename && !argv.outFile) {
const parsedFilename = path.parse(inFilename)
const outFilename = path.format(
Object.assign(
@@ -75,8 +55,8 @@ if (argv.version) {
)
writeStream = fs.createWriteStream(outFilename)
- } else if (argv.o) {
- writeStream = fs.createWriteStream(argv.o)
+ } else if (argv.outFile) {
+ writeStream = fs.createWriteStream(argv.outFile)
} else {
writeStream = process.stdout
}
@@ -90,6 +70,66 @@ if (argv.version) {
})
}
+function parseArgs () {
+ let convert
+ let space
+ let validate
+ let outFile
+ let version
+ let help
+ const defaults = []
+
+ const args = process.argv.slice(2)
+ for (let i = 0; i < args.length; i++) {
+ const arg = args[i]
+ switch (arg) {
+ case '--convert':
+ case '-c':
+ convert = true
+ break
+
+ case '--space':
+ case '-s':
+ space = args[++i]
+ break
+
+ case '--validate':
+ case '-v':
+ validate = true
+ break
+
+ case '--out-file':
+ case '-o':
+ outFile = args[++i]
+ break
+
+ case '--version':
+ case '-V':
+ version = true
+ break
+
+ case '--help':
+ case '-h':
+ help = true
+ break
+
+ default:
+ defaults.push(arg)
+ break
+ }
+ }
+
+ return {
+ convert,
+ space,
+ validate,
+ outFile,
+ version,
+ help,
+ defaults,
+ }
+}
+
function version () {
console.log(pkg.version)
}
diff --git a/lib/parse.js b/lib/parse.js
index c01646fc..da2078a6 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -42,12 +42,34 @@ module.exports = function parse (text, reviver) {
function internalize (holder, name, reviver) {
const value = holder[name]
if (value != null && typeof value === 'object') {
- for (const key in value) {
- const replacement = internalize(value, key, reviver)
- if (replacement === undefined) {
- delete value[key]
- } else {
- value[key] = replacement
+ if (Array.isArray(value)) {
+ for (let i = 0; i < value.length; i++) {
+ const key = String(i)
+ const replacement = internalize(value, key, reviver)
+ if (replacement === undefined) {
+ delete value[key]
+ } else {
+ Object.defineProperty(value, key, {
+ value: replacement,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ })
+ }
+ }
+ } else {
+ for (const key in value) {
+ const replacement = internalize(value, key, reviver)
+ if (replacement === undefined) {
+ delete value[key]
+ } else {
+ Object.defineProperty(value, key, {
+ value: replacement,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ })
+ }
}
}
}
@@ -973,7 +995,12 @@ function push () {
if (Array.isArray(parent)) {
parent.push(value)
} else {
- parent[key] = value
+ Object.defineProperty(parent, key, {
+ value,
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ })
}
}
diff --git a/package-lock.json b/package-lock.json
index 56c0f4de..ac2e4549 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "json5",
- "version": "2.2.0",
+ "version": "2.2.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -563,6 +563,16 @@
"unset-value": "^1.0.0"
}
},
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
"callsites": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz",
@@ -801,6 +811,16 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
+ "define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "requires": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
"define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
@@ -894,6 +914,48 @@
"is-arrayish": "^0.2.1"
}
},
+ "es-abstract": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.1",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.4",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -1542,12 +1604,51 @@
"integrity": "sha1-gHa7MF6OajzO7ikgdl8zDRkPNAw=",
"dev": true
},
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
+ "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
"get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
@@ -1620,12 +1721,42 @@
"function-bind": "^1.1.1"
}
},
+ "has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true
+ },
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
"has-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -1771,6 +1902,17 @@
}
}
},
+ "internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
"is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
@@ -1797,12 +1939,37 @@
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
},
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
+ "is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true
+ },
"is-data-descriptor": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
@@ -1823,6 +1990,15 @@
}
}
},
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
"is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
@@ -1860,6 +2036,12 @@
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
+ "is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true
+ },
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -1880,6 +2062,15 @@
}
}
},
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -1895,12 +2086,58 @@
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -1980,6 +2217,12 @@
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
"dev": true
},
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@@ -2130,6 +2373,12 @@
"object-visit": "^1.0.0"
}
},
+ "memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true
+ },
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -2184,7 +2433,8 @@
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+ "dev": true
},
"minipass": {
"version": "2.3.5",
@@ -2310,6 +2560,73 @@
"validate-npm-package-license": "^3.0.1"
}
},
+ "npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "dependencies": {
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ }
+ }
+ },
"nyc": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz",
@@ -3381,6 +3698,18 @@
}
}
},
+ "object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
"object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -3390,6 +3719,18 @@
"isobject": "^3.0.0"
}
},
+ "object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ }
+ },
"object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@@ -3568,6 +3909,12 @@
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
"dev": true
},
+ "pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true
+ },
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -3694,6 +4041,17 @@
"safe-regex": "^1.1.0"
}
},
+ "regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ }
+ },
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
@@ -3977,6 +4335,23 @@
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
+ "shell-quote": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
+ "dev": true
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@@ -4281,6 +4656,39 @@
"strip-ansi": "^4.0.0"
}
},
+ "string.prototype.padend": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz",
+ "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.1"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -4654,6 +5062,18 @@
"integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==",
"dev": true
},
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
"unicode-10.0.0": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/unicode-10.0.0/-/unicode-10.0.0-0.7.5.tgz",
@@ -4860,6 +5280,19 @@
"isexe": "^2.0.0"
}
},
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
diff --git a/package.json b/package.json
index 31c43e5f..60c51d93 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "json5",
- "version": "2.2.0",
- "description": "JSON for humans.",
+ "version": "2.2.3",
+ "description": "JSON for Humans",
"main": "lib/index.js",
"module": "dist/index.mjs",
"bin": "lib/cli.js",
@@ -20,10 +20,12 @@
"build-unicode": "node build/unicode.js",
"coverage": "tap --coverage-report html test",
"lint": "eslint --fix .",
+ "lint-report": "eslint .",
"prepublishOnly": "npm run production",
"preversion": "npm run production",
- "production": "npm run lint && npm test && npm run build",
- "test": "tap -Rspec --100 test",
+ "production": "run-s test build",
+ "tap": "tap -Rspec --100 test",
+ "test": "run-s lint-report tap",
"version": "npm run build-package && git add package.json5"
},
"repository": {
@@ -48,9 +50,6 @@
"url": "https://github.com/json5/json5/issues"
},
"homepage": "http://json5.org/",
- "dependencies": {
- "minimist": "^1.2.5"
- },
"devDependencies": {
"core-js": "^2.6.5",
"eslint": "^5.15.3",
@@ -59,6 +58,7 @@
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
+ "npm-run-all": "^4.1.5",
"regenerate": "^1.4.0",
"rollup": "^0.64.1",
"rollup-plugin-buble": "^0.19.6",
diff --git a/package.json5 b/package.json5
index afcfbe26..322bed55 100644
--- a/package.json5
+++ b/package.json5
@@ -1,8 +1,8 @@
// This is a generated file. Do not edit.
{
name: 'json5',
- version: '2.2.0',
- description: 'JSON for humans.',
+ version: '2.2.3',
+ description: 'JSON for Humans',
main: 'lib/index.js',
module: 'dist/index.mjs',
bin: 'lib/cli.js',
@@ -21,10 +21,12 @@
'build-unicode': 'node build/unicode.js',
coverage: 'tap --coverage-report html test',
lint: 'eslint --fix .',
+ 'lint-report': 'eslint .',
prepublishOnly: 'npm run production',
preversion: 'npm run production',
- production: 'npm run lint && npm test && npm run build',
- test: 'tap -Rspec --100 test',
+ production: 'run-s test build',
+ tap: 'tap -Rspec --100 test',
+ test: 'run-s lint-report tap',
version: 'npm run build-package && git add package.json5',
},
repository: {
@@ -49,9 +51,6 @@
url: 'https://github.com/json5/json5/issues',
},
homepage: 'http://json5.org/',
- dependencies: {
- minimist: '^1.2.5',
- },
devDependencies: {
'core-js': '^2.6.5',
eslint: '^5.15.3',
@@ -60,6 +59,7 @@
'eslint-plugin-node': '^8.0.1',
'eslint-plugin-promise': '^4.0.1',
'eslint-plugin-standard': '^4.0.0',
+ 'npm-run-all': '^4.1.5',
regenerate: '^1.4.0',
rollup: '^0.64.1',
'rollup-plugin-buble': '^0.19.6',
diff --git a/test/.eslintrc.json b/test/.eslintrc.json
deleted file mode 100644
index 4668ae79..00000000
--- a/test/.eslintrc.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "env": {
- "mocha": true
- }
-}
diff --git a/test/cli.js b/test/cli.js
index 8ddef73a..3d1ca827 100644
--- a/test/cli.js
+++ b/test/cli.js
@@ -2,12 +2,13 @@ const assert = require('assert')
const child = require('child_process')
const fs = require('fs')
const path = require('path')
-const tap = require('tap')
const pkg = require('../package.json')
const cliPath = path.resolve(__dirname, '../lib/cli.js')
-tap.test('CLI', t => {
+const t = require('tap')
+
+t.test('CLI', t => {
t.test('converts JSON5 to JSON from stdin to stdout', t => {
const proc = child.spawn(process.execPath, [cliPath])
let output = ''
@@ -43,7 +44,7 @@ tap.test('CLI', t => {
})
})
- t.test('indents output with the number of spaces specified', t => {
+ t.test('indents output with the number of spaces specified with -s', t => {
const proc = child.spawn(
process.execPath,
[
@@ -65,7 +66,29 @@ tap.test('CLI', t => {
})
})
- t.test('indents output with tabs when specified', t => {
+ t.test('indents output with the number of spaces specified with --space', t => {
+ const proc = child.spawn(
+ process.execPath,
+ [
+ cliPath,
+ path.resolve(__dirname, 'test.json5'),
+ '--space',
+ '4',
+ ]
+ )
+
+ let output = ''
+ proc.stdout.on('data', data => {
+ output += data
+ })
+
+ proc.stdout.on('end', () => {
+ assert.strictEqual(output, '{\n "a": 1,\n "b": 2\n}')
+ t.end()
+ })
+ })
+
+ t.test('indents output with tabs when specified with -s', t => {
const proc = child.spawn(
process.execPath,
[
@@ -87,7 +110,7 @@ tap.test('CLI', t => {
})
})
- t.test('outputs to the specified file', t => {
+ t.test('outputs to the specified file with -o', t => {
const proc = child.spawn(
process.execPath,
[
@@ -116,7 +139,36 @@ tap.test('CLI', t => {
})
})
- t.test('validates valid JSON5 files', t => {
+ t.test('outputs to the specified file with --out-file', t => {
+ const proc = child.spawn(
+ process.execPath,
+ [
+ cliPath,
+ path.resolve(__dirname, 'test.json5'),
+ '--out-file',
+ path.resolve(__dirname, 'output.json'),
+ ]
+ )
+
+ proc.on('exit', () => {
+ assert.strictEqual(
+ fs.readFileSync(
+ path.resolve(__dirname, 'output.json'),
+ 'utf8'
+ ),
+ '{"a":1,"b":2}'
+ )
+ t.end()
+ })
+
+ t.tearDown(() => {
+ try {
+ fs.unlinkSync(path.resolve(__dirname, 'output.json'))
+ } catch (err) {}
+ })
+ })
+
+ t.test('validates valid JSON5 files with -v', t => {
const proc = child.spawn(
process.execPath,
[
@@ -132,7 +184,23 @@ tap.test('CLI', t => {
})
})
- t.test('validates invalid JSON5 files', t => {
+ t.test('validates valid JSON5 files with --validate', t => {
+ const proc = child.spawn(
+ process.execPath,
+ [
+ cliPath,
+ path.resolve(__dirname, 'test.json5'),
+ '--validate',
+ ]
+ )
+
+ proc.on('exit', code => {
+ assert.strictEqual(code, 0)
+ t.end()
+ })
+ })
+
+ t.test('validates invalid JSON5 files with -v', t => {
const proc = child.spawn(
process.execPath,
[
@@ -157,7 +225,7 @@ tap.test('CLI', t => {
})
})
- t.test('outputs the version number when specified', t => {
+ t.test('outputs the version number when specified with -V', t => {
const proc = child.spawn(process.execPath, [cliPath, '-V'])
let output = ''
@@ -171,7 +239,21 @@ tap.test('CLI', t => {
})
})
- t.test('outputs usage information when specified', t => {
+ t.test('outputs the version number when specified with --version', t => {
+ const proc = child.spawn(process.execPath, [cliPath, '--version'])
+
+ let output = ''
+ proc.stdout.on('data', data => {
+ output += data
+ })
+
+ proc.stdout.on('end', () => {
+ assert.strictEqual(output, pkg.version + '\n')
+ t.end()
+ })
+ })
+
+ t.test('outputs usage information when specified with -h', t => {
const proc = child.spawn(process.execPath, [cliPath, '-h'])
let output = ''
@@ -185,7 +267,21 @@ tap.test('CLI', t => {
})
})
- t.test('is backward compatible with v0.5.1', t => {
+ t.test('outputs usage information when specified with --help', t => {
+ const proc = child.spawn(process.execPath, [cliPath, '--help'])
+
+ let output = ''
+ proc.stdout.on('data', data => {
+ output += data
+ })
+
+ proc.stdout.on('end', () => {
+ assert(/Usage/.test(output))
+ t.end()
+ })
+ })
+
+ t.test('is backward compatible with v0.5.1 with -c', t => {
const proc = child.spawn(
process.execPath,
[
@@ -213,5 +309,33 @@ tap.test('CLI', t => {
})
})
+ t.test('is backward compatible with v0.5.1 with --convert', t => {
+ const proc = child.spawn(
+ process.execPath,
+ [
+ cliPath,
+ '--convert',
+ path.resolve(__dirname, 'test.json5'),
+ ]
+ )
+
+ proc.on('exit', () => {
+ assert.strictEqual(
+ fs.readFileSync(
+ path.resolve(__dirname, 'test.json'),
+ 'utf8'
+ ),
+ '{"a":1,"b":2}'
+ )
+ t.end()
+ })
+
+ t.tearDown(() => {
+ try {
+ fs.unlinkSync(path.resolve(__dirname, 'test.json'))
+ } catch (err) {}
+ })
+ })
+
t.end()
})
diff --git a/test/errors.js b/test/errors.js
index 1d1657c6..50f590cf 100644
--- a/test/errors.js
+++ b/test/errors.js
@@ -1,444 +1,377 @@
-const assert = require('assert')
const JSON5 = require('../lib')
-require('tap').mochaGlobals()
-
-describe('JSON5', () => {
- describe('#parse()', () => {
- describe('errors', () => {
- it('throws on empty documents', () => {
- assert.throws(() => {
- JSON5.parse('')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 1
- ))
- })
-
- it('throws on documents with only comments', () => {
- assert.throws(() => {
- JSON5.parse('//a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on incomplete single line comments', () => {
- assert.throws(() => {
- JSON5.parse('/a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on unterminated multiline comments', () => {
- assert.throws(() => {
- JSON5.parse('/*')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on unterminated multiline comment closings', () => {
- assert.throws(() => {
- JSON5.parse('/**')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on invalid characters in values', () => {
- assert.throws(() => {
- JSON5.parse('a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 1
- ))
- })
-
- it('throws on invalid characters in identifier start escapes', () => {
- assert.throws(() => {
- JSON5.parse('{\\a:1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid identifier start characters', () => {
- assert.throws(() => {
- JSON5.parse('{\\u0021:1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid identifier character/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on invalid characters in identifier continue escapes', () => {
- assert.throws(() => {
- JSON5.parse('{a\\a:1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on invalid identifier continue characters', () => {
- assert.throws(() => {
- JSON5.parse('{a\\u0021:1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid identifier character/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid characters following a sign', () => {
- assert.throws(() => {
- JSON5.parse('-a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on invalid characters following a leading decimal point', () => {
- assert.throws(() => {
- JSON5.parse('.a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on invalid characters following an exponent indicator', () => {
- assert.throws(() => {
- JSON5.parse('1ea')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid characters following an exponent sign', () => {
- assert.throws(() => {
- JSON5.parse('1e-a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'a'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on invalid characters following a hexadecimal indicator', () => {
- assert.throws(() => {
- JSON5.parse('0xg')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'g'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid new lines in strings', () => {
- assert.throws(() => {
- JSON5.parse('"\n"')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '\\n'/.test(err.message) &&
- err.lineNumber === 2 &&
- err.columnNumber === 0
- ))
- })
-
- it('throws on unterminated strings', () => {
- assert.throws(() => {
- JSON5.parse('"')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on invalid identifier start characters in property names', () => {
- assert.throws(() => {
- JSON5.parse('{!:1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '!'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on invalid characters following a property name', () => {
- assert.throws(() => {
- JSON5.parse('{a!1}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '!'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid characters following a property value', () => {
- assert.throws(() => {
- JSON5.parse('{a:1!}')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '!'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 5
- ))
- })
-
- it('throws on invalid characters following an array value', () => {
- assert.throws(() => {
- JSON5.parse('[1!]')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '!'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid characters in literals', () => {
- assert.throws(() => {
- JSON5.parse('tru!')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '!'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on unterminated escapes', () => {
- assert.throws(() => {
- JSON5.parse('"\\')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on invalid first digits in hexadecimal escapes', () => {
- assert.throws(() => {
- JSON5.parse('"\\xg"')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'g'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on invalid second digits in hexadecimal escapes', () => {
- assert.throws(() => {
- JSON5.parse('"\\x0g"')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'g'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 5
- ))
- })
-
- it('throws on invalid unicode escapes', () => {
- assert.throws(() => {
- JSON5.parse('"\\u000g"')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character 'g'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 7
- ))
- })
-
- it('throws on escaped digits other than 0', () => {
- for (let i = 1; i <= 9; i++) {
- assert.throws(() => {
- JSON5.parse(`'\\${i}'`)
+const t = require('tap')
+
+t.test('JSON5', t => {
+ t.test('#parse()', t => {
+ t.test('errors', t => {
+ t.throws(
+ () => { JSON5.parse('') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 1,
+ },
+ 'throws on empty documents'
+ )
+
+ t.throws(
+ () => { JSON5.parse('//a') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on documents with only comments'
+ )
+
+ t.throws(
+ () => { JSON5.parse('/a') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on incomplete single line comments'
+ )
+
+ t.throws(
+ () => { JSON5.parse('/*') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on unterminated multiline comments'
+ )
+
+ t.throws(
+ () => { JSON5.parse('/**') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on unterminated multiline comment closings'
+ )
+
+ t.throws(
+ () => { JSON5.parse('a') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 1,
+ },
+ 'throws on invalid characters in values'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{\\a:1}') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid characters in identifier start escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{\\u0021:1}') },
+ {
+ message: /^JSON5: invalid identifier character/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on invalid identifier start characters'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a\\a:1}') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on invalid characters in identifier continue escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a\\u0021:1}') },
+ {
+ message: /^JSON5: invalid identifier character/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid identifier continue characters'
+ )
+
+ t.throws(
+ () => { JSON5.parse('-a') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on invalid characters following a sign'
+ )
+
+ t.throws(
+ () => { JSON5.parse('.a') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on invalid characters following a leading decimal point'
+ )
+
+ t.throws(
+ () => { JSON5.parse('1ea') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid characters following an exponent indicator'
+ )
+
+ t.throws(
+ () => { JSON5.parse('1e-a') },
+ {
+ message: /^JSON5: invalid character 'a'/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on invalid characters following an exponent sign'
+ )
+
+ t.throws(
+ () => { JSON5.parse('0xg') },
+ {
+ message: /^JSON5: invalid character 'g'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid characters following a hexadecimal indicator'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"\n"') },
+ {
+ message: /^JSON5: invalid character '\\n'/,
+ lineNumber: 2,
+ columnNumber: 0,
+ },
+ 'throws on invalid new lines in strings'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on unterminated strings'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{!:1}') },
+ {
+ message: /^JSON5: invalid character '!'/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on invalid identifier start characters in property names'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a!1}') },
+ {
+ message: /^JSON5: invalid character '!'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid characters following a property name'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a:1!}') },
+ {
+ message: /^JSON5: invalid character '!'/,
+ lineNumber: 1,
+ columnNumber: 5,
+ },
+ 'throws on invalid characters following a property value'
+ )
+
+ t.throws(
+ () => { JSON5.parse('[1!]') },
+ {
+ message: /^JSON5: invalid character '!'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on invalid characters following an array value'
+ )
+
+ t.throws(
+ () => { JSON5.parse('tru!') },
+ {
+ message: /^JSON5: invalid character '!'/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on invalid characters in literals'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"\\') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on unterminated escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"\\xg"') },
+ {
+ message: /^JSON5: invalid character 'g'/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on invalid first digits in hexadecimal escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"\\x0g"') },
+ {
+ message: /^JSON5: invalid character 'g'/,
+ lineNumber: 1,
+ columnNumber: 5,
+ },
+ 'throws on invalid second digits in hexadecimal escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('"\\u000g"') },
+ {
+ message: /^JSON5: invalid character 'g'/,
+ lineNumber: 1,
+ columnNumber: 7,
+ },
+ 'throws on invalid unicode escapes'
+ )
+
+ for (let i = 1; i <= 9; i++) {
+ t.throws(
+ () => { JSON5.parse(`'\\${i}'`) },
+ {
+ message: /^JSON5: invalid character '\d'/,
+ lineNumber: 1,
+ columnNumber: 3,
},
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '\d'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- }
- })
-
- it('throws on octal escapes', () => {
- assert.throws(() => {
- JSON5.parse("'\\01'")
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '1'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on multiple values', () => {
- assert.throws(() => {
- JSON5.parse('1 2')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '2'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws with control characters escaped in the message', () => {
- assert.throws(() => {
- JSON5.parse('\x01')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid character '\\x01'/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 1
- ))
- })
-
- it('throws on unclosed objects before property names', () => {
- assert.throws(() => {
- JSON5.parse('{')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on unclosed objects after property names', () => {
- assert.throws(() => {
- JSON5.parse('{a')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
-
- it('throws on unclosed objects before property values', () => {
- assert.throws(() => {
- JSON5.parse('{a:')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 4
- ))
- })
-
- it('throws on unclosed objects after property values', () => {
- assert.throws(() => {
- JSON5.parse('{a:1')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 5
- ))
- })
-
- it('throws on unclosed arrays before values', () => {
- assert.throws(() => {
- JSON5.parse('[')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 2
- ))
- })
-
- it('throws on unclosed arrays after values', () => {
- assert.throws(() => {
- JSON5.parse('[1')
- },
- err => (
- err instanceof SyntaxError &&
- /^JSON5: invalid end of input/.test(err.message) &&
- err.lineNumber === 1 &&
- err.columnNumber === 3
- ))
- })
+ `throws on escaped digit ${i}`
+ )
+ }
+
+ t.throws(
+ () => { JSON5.parse("'\\01'") },
+ {
+ message: /^JSON5: invalid character '1'/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on octal escapes'
+ )
+
+ t.throws(
+ () => { JSON5.parse('1 2') },
+ {
+ message: /^JSON5: invalid character '2'/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on multiple values'
+ )
+
+ t.throws(
+ () => { JSON5.parse('\x01') },
+ {
+ message: /^JSON5: invalid character '\\x01'/,
+ lineNumber: 1,
+ columnNumber: 1,
+ },
+ 'throws with control characters escaped in the message'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on unclosed objects before property names'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on unclosed objects after property names'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a:') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 4,
+ },
+ 'throws on unclosed objects before property values'
+ )
+
+ t.throws(
+ () => { JSON5.parse('{a:1') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 5,
+ },
+ 'throws on unclosed objects after property values'
+ )
+
+ t.throws(
+ () => { JSON5.parse('[') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 2,
+ },
+ 'throws on unclosed arrays before values'
+ )
+
+ t.throws(
+ () => { JSON5.parse('[1') },
+ {
+ message: /^JSON5: invalid end of input/,
+ lineNumber: 1,
+ columnNumber: 3,
+ },
+ 'throws on unclosed arrays after values'
+ )
+
+ t.end()
})
+
+ t.end()
})
+
+ t.end()
})
diff --git a/test/parse.js b/test/parse.js
index 59fbdd15..e305767e 100644
--- a/test/parse.js
+++ b/test/parse.js
@@ -2,8 +2,6 @@ const assert = require('assert')
const sinon = require('sinon')
const JSON5 = require('../lib')
-require('tap').mochaGlobals()
-
const t = require('tap')
t.test('parse(text)', t => {
@@ -50,6 +48,13 @@ t.test('parse(text)', t => {
'parses escaped property names'
)
+ t.strictSame(
+ // eslint-disable-next-line no-proto
+ JSON5.parse('{"__proto__":1}').__proto__,
+ 1,
+ 'preserves __proto__ property names'
+ )
+
t.strictSame(
JSON5.parse('{abc:1,def:2}'),
{abc: 1, def: 2},
diff --git a/test/require.js b/test/require.js
index b30f74c7..86b9b470 100644
--- a/test/require.js
+++ b/test/require.js
@@ -1,24 +1,29 @@
const assert = require('assert')
const sinon = require('sinon')
-require('tap').mochaGlobals()
+const t = require('tap')
-describe('require(*.json5)', () => {
- it('parses a JSON5 document', () => {
+t.test('require(*.json5)', t => {
+ t.test('parses a JSON5 document', t => {
require('../lib/register')
assert.deepStrictEqual({a: 1, b: 2}, require('./test.json5'))
+ t.end()
})
- it('is backward compatible with v0.5.1, but gives a deprecation warning', () => {
+ t.test('is backward compatible with v0.5.1, but gives a deprecation warning', t => {
const mock = sinon.mock(console)
mock.expects('warn').once().withExactArgs("'json5/require' is deprecated. Please use 'json5/register' instead.")
require('../lib/require')
assert.deepStrictEqual({a: 1, b: 2}, require('./test.json5'))
mock.verify()
+ t.end()
})
- it('throws on invalid JSON5', () => {
+ t.test('throws on invalid JSON5', t => {
require('../lib/register')
assert.throws(() => { require('./invalid.json5') }, SyntaxError)
+ t.end()
})
+
+ t.end()
})
diff --git a/test/stringify.js b/test/stringify.js
index a0c494f0..e256a314 100644
--- a/test/stringify.js
+++ b/test/stringify.js
@@ -1,340 +1,482 @@
const assert = require('assert')
const JSON5 = require('../lib')
-require('tap').mochaGlobals()
-
-describe('JSON5', () => {
- describe('#stringify', () => {
- describe('objects', () => {
- it('stringifies empty objects', () => {
- assert.strictEqual(JSON5.stringify({}), '{}')
- })
-
- it('stringifies unquoted property names', () => {
- assert.strictEqual(JSON5.stringify({a: 1}), '{a:1}')
- })
-
- it('stringifies single quoted string property names', () => {
- assert.strictEqual(JSON5.stringify({'a-b': 1}), "{'a-b':1}")
- })
-
- it('stringifies double quoted string property names', () => {
- assert.strictEqual(JSON5.stringify({"a'": 1}), `{"a'":1}`)
- })
+const t = require('tap')
+
+t.test('JSON5', t => {
+ t.test('#stringify', t => {
+ t.test('objects', t => {
+ t.strictSame(
+ JSON5.stringify({}),
+ '{}',
+ 'stringifies empty objects'
+ )
- it('stringifies empty string property names', () => {
- assert.strictEqual(JSON5.stringify({'': 1}), "{'':1}")
- })
+ t.strictSame(
+ JSON5.stringify({a: 1}),
+ '{a:1}',
+ 'stringifies unquoted property names'
+ )
- it('stringifies special character property names', () => {
- assert.strictEqual(JSON5.stringify({$_: 1, _$: 2, 'a\u200C': 3}), '{$_:1,_$:2,a\u200C:3}')
- })
+ t.strictSame(
+ JSON5.stringify({'a-b': 1}),
+ "{'a-b':1}",
+ 'stringifies single quoted string property names'
+ )
- it('stringifies unicode property names', () => {
- assert.strictEqual(JSON5.stringify({'ùńîċõďë': 9}), '{ùńîċõďë:9}')
- })
+ t.strictSame(
+ JSON5.stringify({"a'": 1}),
+ `{"a'":1}`,
+ 'stringifies double quoted string property names'
+ )
- it('stringifies escaped property names', () => {
- assert.strictEqual(JSON5.stringify({'\\\b\f\n\r\t\v\0\x01': 1}), "{'\\\\\\b\\f\\n\\r\\t\\v\\0\\x01':1}")
- })
+ t.strictSame(
+ JSON5.stringify({'': 1}),
+ "{'':1}",
+ 'stringifies empty string property names'
+ )
- it('stringifies escaped null character property names', () => {
- assert.strictEqual(JSON5.stringify({'\0\x001': 1}), "{'\\0\\x001':1}")
- })
+ t.strictSame(
+ JSON5.stringify({$_: 1, _$: 2, 'a\u200C': 3}),
+ '{$_:1,_$:2,a\u200C:3}',
+ 'stringifies special character property names'
+ )
- it('stringifies multiple properties', () => {
- assert.strictEqual(JSON5.stringify({abc: 1, def: 2}), '{abc:1,def:2}')
- })
+ t.strictSame(
+ JSON5.stringify({'ùńîċõďë': 9}),
+ '{ùńîċõďë:9}',
+ 'stringifies unicode property names'
+ )
- it('stringifies nested objects', () => {
- assert.strictEqual(JSON5.stringify({a: {b: 2}}), '{a:{b:2}}')
- })
- })
+ t.strictSame(
+ JSON5.stringify({'\\\b\f\n\r\t\v\0\x01': 1}),
+ "{'\\\\\\b\\f\\n\\r\\t\\v\\0\\x01':1}",
+ 'stringifies escaped property names'
+ )
- describe('arrays', () => {
- it('stringifies empty arrays', () => {
- assert.strictEqual(JSON5.stringify([]), '[]')
- })
+ t.strictSame(
+ JSON5.stringify({'\0\x001': 1}),
+ "{'\\0\\x001':1}",
+ 'stringifies escaped null character property names'
+ )
- it('stringifies array values', () => {
- assert.strictEqual(JSON5.stringify([1]), '[1]')
- })
+ t.strictSame(
+ JSON5.stringify({abc: 1, def: 2}),
+ '{abc:1,def:2}',
+ 'stringifies multiple properties'
+ )
- it('stringifies multiple array values', () => {
- assert.strictEqual(JSON5.stringify([1, 2]), '[1,2]')
- })
+ t.strictSame(
+ JSON5.stringify({a: {b: 2}}),
+ '{a:{b:2}}',
+ 'stringifies nested objects'
+ )
- it('stringifies nested arrays', () => {
- assert.strictEqual(JSON5.stringify([1, [2, 3]]), '[1,[2,3]]')
- })
+ t.end()
})
- it('stringifies nulls', () => {
- assert.strictEqual(JSON5.stringify(null), 'null')
- })
+ t.test('arrays', t => {
+ t.strictSame(
+ JSON5.stringify([]),
+ '[]',
+ 'stringifies empty arrays'
+ )
- it('returns undefined for functions', () => {
- assert.strictEqual(JSON5.stringify(() => {}), undefined)
- })
+ t.strictSame(
+ JSON5.stringify([1]),
+ '[1]',
+ 'stringifies array values'
+ )
- it('ignores function properties', () => {
- assert.strictEqual(JSON5.stringify({a () {}}), '{}')
- })
+ t.strictSame(
+ JSON5.stringify([1, 2]),
+ '[1,2]',
+ 'stringifies multiple array values'
+ )
- it('returns null for functions in arrays', () => {
- assert.strictEqual(JSON5.stringify([() => {}]), '[null]')
- })
+ t.strictSame(
+ JSON5.stringify([1, [2, 3]]),
+ '[1,[2,3]]',
+ 'stringifies nested arrays'
+ )
- describe('Booleans', () => {
- it('stringifies true', () => {
- assert.strictEqual(JSON5.stringify(true), 'true')
- })
+ t.end()
+ })
+
+ t.strictSame(
+ JSON5.stringify(null),
+ 'null',
+ 'stringifies nulls'
+ )
+
+ t.strictSame(
+ JSON5.stringify(() => {}),
+ undefined,
+ 'returns undefined for functions'
+ )
+
+ t.strictSame(
+ JSON5.stringify({a () {}}),
+ '{}',
+ 'ignores function properties'
+ )
+
+ t.strictSame(
+ JSON5.stringify([() => {}]),
+ '[null]',
+ 'returns null for functions in arrays'
+ )
+
+ t.test('Booleans', t => {
+ t.strictSame(
+ JSON5.stringify(true),
+ 'true',
+ 'stringifies true'
+ )
- it('stringifies false', () => {
- assert.strictEqual(JSON5.stringify(false), 'false')
- })
+ t.strictSame(
+ JSON5.stringify(false),
+ 'false',
+ 'stringifies false'
+ )
- it('stringifies true Boolean objects', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify(new Boolean(true)), 'true')
- })
+ JSON5.stringify(new Boolean(true)),
+ 'true',
+ 'stringifies true Boolean objects'
+ )
- it('stringifies false Boolean objects', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify(new Boolean(false)), 'false')
- })
+ JSON5.stringify(new Boolean(false)),
+ 'false',
+ 'stringifies false Boolean objects'
+ )
+
+ t.end()
})
- describe('numbers', () => {
- it('stringifies numbers', () => {
- assert.strictEqual(JSON5.stringify(-1.2), '-1.2')
- })
+ t.test('numbers', t => {
+ t.strictSame(
+ JSON5.stringify(-1.2),
+ '-1.2',
+ 'stringifies numbers'
+ )
- it('stringifies non-finite numbers', () => {
- assert.strictEqual(JSON5.stringify([Infinity, -Infinity, NaN]), '[Infinity,-Infinity,NaN]')
- })
+ t.strictSame(
+ JSON5.stringify([Infinity, -Infinity, NaN]),
+ '[Infinity,-Infinity,NaN]',
+ 'stringifies non-finite numbers'
+ )
- it('stringifies Number objects', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify(new Number(-1.2)), '-1.2')
- })
+ JSON5.stringify(new Number(-1.2)),
+ '-1.2',
+ 'stringifies Number objects'
+ )
+
+ t.end()
})
- describe('strings', () => {
- it('stringifies single quoted strings', () => {
- assert.strictEqual(JSON5.stringify('abc'), "'abc'")
- })
+ t.test('strings', t => {
+ t.strictSame(
+ JSON5.stringify('abc'),
+ "'abc'",
+ 'stringifies single quoted strings'
+ )
- it('stringifies double quoted strings', () => {
- assert.strictEqual(JSON5.stringify("abc'"), `"abc'"`)
- })
+ t.strictSame(
+ JSON5.stringify("abc'"),
+ `"abc'"`,
+ 'stringifies double quoted strings'
+ )
- it('stringifies escaped characters', () => {
- assert.strictEqual(JSON5.stringify('\\\b\f\n\r\t\v\0\x0f'), "'\\\\\\b\\f\\n\\r\\t\\v\\0\\x0f'")
- })
+ t.strictSame(
+ JSON5.stringify('\\\b\f\n\r\t\v\0\x0f'),
+ "'\\\\\\b\\f\\n\\r\\t\\v\\0\\x0f'",
+ 'stringifies escaped characters'
+ )
- it('stringifies escaped null characters', () => {
- assert.strictEqual(JSON5.stringify('\0\x001'), "'\\0\\x001'")
- })
+ t.strictSame(
+ JSON5.stringify('\0\x001'),
+ "'\\0\\x001'",
+ 'stringifies escaped null characters'
+ )
- it('stringifies escaped single quotes', () => {
- assert.strictEqual(JSON5.stringify(`'"`), `'\\'"'`)
- })
+ t.strictSame(
+ JSON5.stringify(`'"`),
+ `'\\'"'`,
+ 'stringifies escaped single quotes'
+ )
- it('stringifies escaped double quotes', () => {
- assert.strictEqual(JSON5.stringify(`''"`), `"''\\""`)
- })
+ t.strictSame(
+ JSON5.stringify(`''"`),
+ `"''\\""`,
+ 'stringifies escaped double quotes'
+ )
- it('stringifies escaped line and paragraph separators', () => {
- assert.strictEqual(JSON5.stringify('\u2028\u2029'), "'\\u2028\\u2029'")
- })
+ t.strictSame(
+ JSON5.stringify('\u2028\u2029'),
+ "'\\u2028\\u2029'",
+ 'stringifies escaped line and paragraph separators'
+ )
- it('stringifies String objects', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify(new String('abc')), "'abc'")
- })
- })
+ JSON5.stringify(new String('abc')),
+ "'abc'",
+ 'stringifies String objects'
+ )
- it('stringifies using built-in toJSON methods', () => {
- assert.strictEqual(JSON5.stringify(new Date('2016-01-01T00:00:00.000Z')), "'2016-01-01T00:00:00.000Z'")
+ t.end()
})
- it('stringifies using user defined toJSON methods', () => {
+ t.strictSame(
+ JSON5.stringify(new Date('2016-01-01T00:00:00.000Z')),
+ "'2016-01-01T00:00:00.000Z'",
+ 'stringifies using built-in toJSON methods'
+ )
+
+ t.test('stringifies using user defined toJSON methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON () { return {a: 1, b: 2} }})
assert.strictEqual(JSON5.stringify(new C()), '{a:1,b:2}')
+ t.end()
})
- it('stringifies using user defined toJSON(key) methods', () => {
+ t.test('stringifies using user defined toJSON(key) methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON (key) { return (key === 'a') ? 1 : 2 }})
assert.strictEqual(JSON5.stringify({a: new C(), b: new C()}), '{a:1,b:2}')
+ t.end()
})
- it('stringifies using toJSON5 methods', () => {
+ t.test('stringifies using toJSON5 methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 () { return {a: 1, b: 2} }})
assert.strictEqual(JSON5.stringify(new C()), '{a:1,b:2}')
+ t.end()
})
- it('stringifies using toJSON5(key) methods', () => {
+ t.test('stringifies using toJSON5(key) methods', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 (key) { return (key === 'a') ? 1 : 2 }})
assert.strictEqual(JSON5.stringify({a: new C(), b: new C()}), '{a:1,b:2}')
+ t.end()
})
- it('calls toJSON5 instead of toJSON if both are defined', () => {
+ t.test('calls toJSON5 instead of toJSON if both are defined', t => {
function C () {}
Object.assign(C.prototype, {
toJSON () { return {a: 1, b: 2} },
toJSON5 () { return {a: 2, b: 2} },
})
assert.strictEqual(JSON5.stringify(new C()), '{a:2,b:2}')
+ t.end()
})
- it('throws on circular objects', () => {
+ t.test('throws on circular objects', t => {
let a = {}
a.a = a
assert.throws(() => { JSON5.stringify(a) }, TypeError, 'Converting circular structure to JSON5')
+ t.end()
})
- it('throws on circular arrays', () => {
+ t.test('throws on circular arrays', t => {
let a = []
a[0] = a
assert.throws(() => { JSON5.stringify(a) }, TypeError, 'Converting circular structure to JSON5')
- })
- })
-
- describe('#stringify(value, null, space)', () => {
- it('does not indent when no value is provided', () => {
- assert.strictEqual(JSON5.stringify([1]), '[1]')
- })
-
- it('does not indent when 0 is provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, 0), '[1]')
- })
-
- it('does not indent when an empty string is provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, ''), '[1]')
- })
-
- it('indents n spaces when a number is provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, 2), '[\n 1,\n]')
- })
-
- it('does not indent more than 10 spaces when a number is provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, 11), '[\n 1,\n]')
- })
-
- it('indents with the string provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, '\t'), '[\n\t1,\n]')
- })
-
- it('does not indent more than 10 characters of the string provided', () => {
- assert.strictEqual(JSON5.stringify([1], null, ' '), '[\n 1,\n]')
- })
-
- it('indents in arrays', () => {
- assert.strictEqual(JSON5.stringify([1], null, 2), '[\n 1,\n]')
- })
-
- it('indents in nested arrays', () => {
- assert.strictEqual(JSON5.stringify([1, [2], 3], null, 2), '[\n 1,\n [\n 2,\n ],\n 3,\n]')
+ t.end()
})
- it('indents in objects', () => {
- assert.strictEqual(JSON5.stringify({a: 1}, null, 2), '{\n a: 1,\n}')
- })
-
- it('indents in nested objects', () => {
- assert.strictEqual(JSON5.stringify({a: {b: 2}}, null, 2), '{\n a: {\n b: 2,\n },\n}')
- })
+ t.end()
+ })
- it('accepts Number objects', () => {
+ t.test('#stringify(value, null, space)', t => {
+ t.strictSame(
+ JSON5.stringify([1]),
+ '[1]',
+ 'does not indent when no value is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, 0),
+ '[1]',
+ 'does not indent when 0 is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, ''),
+ '[1]',
+ 'does not indent when an empty string is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, 2),
+ '[\n 1,\n]',
+ 'indents n spaces when a number is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, 11),
+ '[\n 1,\n]',
+ 'does not indent more than 10 spaces when a number is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, '\t'),
+ '[\n\t1,\n]',
+ 'indents with the string provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, ' '),
+ '[\n 1,\n]',
+ 'does not indent more than 10 characters of the string provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1], null, 2),
+ '[\n 1,\n]',
+ 'indents in arrays'
+ )
+
+ t.strictSame(
+ JSON5.stringify([1, [2], 3], null, 2),
+ '[\n 1,\n [\n 2,\n ],\n 3,\n]',
+ 'indents in nested arrays'
+ )
+
+ t.strictSame(
+ JSON5.stringify({a: 1}, null, 2),
+ '{\n a: 1,\n}',
+ 'indents in objects'
+ )
+
+ t.strictSame(
+ JSON5.stringify({a: {b: 2}}, null, 2),
+ '{\n a: {\n b: 2,\n },\n}',
+ 'indents in nested objects'
+ )
+
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify([1], null, new Number(2)), '[\n 1,\n]')
- })
+ JSON5.stringify([1], null, new Number(2)),
+ '[\n 1,\n]',
+ 'accepts Number objects'
+ )
- it('accepts String objects', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify([1], null, new String('\t')), '[\n\t1,\n]')
- })
+ JSON5.stringify([1], null, new String('\t')),
+ '[\n\t1,\n]',
+ 'accepts String objects'
+ )
+
+ t.end()
})
- describe('#stringify(value, replacer)', () => {
- it('filters keys when an array is provided', () => {
- assert.strictEqual(JSON5.stringify({a: 1, b: 2, 3: 3}, ['a', 3]), "{a:1,'3':3}")
- })
+ t.test('#stringify(value, replacer)', t => {
+ t.strictSame(
+ JSON5.stringify({a: 1, b: 2, 3: 3}, ['a', 3]),
+ "{a:1,'3':3}",
+ 'filters keys when an array is provided'
+ )
- it('only filters string and number keys when an array is provided', () => {
- assert.strictEqual(JSON5.stringify({a: 1, b: 2, 3: 3, false: 4}, ['a', 3, false]), "{a:1,'3':3}")
- })
+ t.strictSame(
+ JSON5.stringify({a: 1, b: 2, 3: 3, false: 4}, ['a', 3, false]),
+ "{a:1,'3':3}",
+ 'only filters string and number keys when an array is provided'
+ )
- it('accepts String and Number objects when an array is provided', () => {
+ t.strictSame(
// eslint-disable-next-line no-new-wrappers
- assert.strictEqual(JSON5.stringify({a: 1, b: 2, 3: 3}, [new String('a'), new Number(3)]), "{a:1,'3':3}")
- })
-
- it('replaces values when a function is provided', () => {
- assert.strictEqual(
- JSON5.stringify({a: 1, b: 2}, (key, value) => (key === 'a') ? 2 : value),
- '{a:2,b:2}'
- )
- })
-
- it('sets `this` to the parent value', () => {
- assert.strictEqual(
- JSON5.stringify({a: {b: 1}}, function (k, v) { return (k === 'b' && this.b) ? 2 : v }),
- '{a:{b:2}}'
- )
- })
-
- it('is called after toJSON', () => {
+ JSON5.stringify({a: 1, b: 2, 3: 3}, [new String('a'), new Number(3)]),
+ "{a:1,'3':3}",
+ 'accepts String and Number objects when an array is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify({a: 1, b: 2}, (key, value) => (key === 'a') ? 2 : value),
+ '{a:2,b:2}',
+ 'replaces values when a function is provided'
+ )
+
+ t.strictSame(
+ JSON5.stringify({a: {b: 1}}, function (k, v) { return (k === 'b' && this.b) ? 2 : v }),
+ '{a:{b:2}}',
+ 'sets `this` to the parent value'
+ )
+
+ t.test('is called after toJSON', t => {
function C () {}
Object.assign(C.prototype, {toJSON () { return {a: 1, b: 2} }})
assert.strictEqual(
JSON5.stringify(new C(), (key, value) => (key === 'a') ? 2 : value),
'{a:2,b:2}'
)
+ t.end()
})
- it('is called after toJSON5', () => {
+ t.test('is called after toJSON5', t => {
function C () {}
Object.assign(C.prototype, {toJSON5 () { return {a: 1, b: 2} }})
assert.strictEqual(
JSON5.stringify(new C(), (key, value) => (key === 'a') ? 2 : value),
'{a:2,b:2}'
)
+ t.end()
})
- it('does not affect space when calls are nested', () => {
- assert.strictEqual(
- JSON5.stringify({a: 1}, (key, value) => {
+ t.strictSame(
+ JSON5.stringify(
+ {a: 1},
+ (key, value) => {
JSON5.stringify({}, null, 4)
return value
- }, 2),
- '{\n a: 1,\n}'
- )
- })
+ },
+ 2
+ ),
+ '{\n a: 1,\n}',
+ 'does not affect space when calls are nested'
+ )
+
+ t.end()
})
- describe('#stringify(value, options)', () => {
- it('accepts replacer as an option', () => {
- assert.strictEqual(JSON5.stringify({a: 1, b: 2, 3: 3}, {replacer: ['a', 3]}), "{a:1,'3':3}")
- })
+ t.test('#stringify(value, options)', t => {
+ t.strictSame(
+ JSON5.stringify({a: 1, b: 2, 3: 3}, {replacer: ['a', 3]}),
+ "{a:1,'3':3}",
+ 'accepts replacer as an option'
+ )
- it('accepts space as an option', () => {
- assert.strictEqual(JSON5.stringify([1], {space: 2}), '[\n 1,\n]')
- })
+ t.strictSame(
+ JSON5.stringify([1], {space: 2}),
+ '[\n 1,\n]',
+ 'accepts space as an option'
+ )
+
+ t.end()
})
- describe('#stringify(value, {quote})', () => {
- it('uses double quotes if provided', () => {
- assert.strictEqual(JSON5.stringify({'a"': '1"'}, {quote: '"'}), '{"a\\"":"1\\""}')
- })
+ t.test('#stringify(value, {quote})', t => {
+ t.strictSame(
+ JSON5.stringify({'a"': '1"'}, {quote: '"'}),
+ '{"a\\"":"1\\""}',
+ 'uses double quotes if provided'
+ )
- it('uses single quotes if provided', () => {
- assert.strictEqual(JSON5.stringify({"a'": "1'"}, {quote: "'"}), "{'a\\'':'1\\''}")
- })
+ t.strictSame(
+ JSON5.stringify({"a'": "1'"}, {quote: "'"}),
+ "{'a\\'':'1\\''}",
+ 'uses single quotes if provided'
+ )
+
+ t.end()
})
+
+ t.end()
})