',
+ ],
+ license: 'MIT',
+ bugs: {
+ url: 'https://github.com/json5/json5/issues',
+ },
+ homepage: 'http://json5.org/',
+ devDependencies: {
+ 'core-js': '^2.6.5',
+ eslint: '^5.15.3',
+ 'eslint-config-standard': '^12.0.0',
+ 'eslint-plugin-import': '^2.16.0',
+ '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',
+ 'rollup-plugin-commonjs': '^9.2.1',
+ 'rollup-plugin-node-resolve': '^3.4.0',
+ 'rollup-plugin-terser': '^1.0.1',
+ sinon: '^6.3.5',
+ tap: '^12.6.0',
+ 'unicode-10.0.0': '^0.7.5',
+ },
+}
\ No newline at end of file
diff --git a/rollup.config.js b/rollup.config.js
index c94c43ec..871066d8 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,18 +1,13 @@
-import resolve from 'rollup-plugin-node-resolve'
-import commonjs from 'rollup-plugin-commonjs'
-import babel from 'rollup-plugin-babel'
-import babelrc from 'babelrc-rollup'
-import uglify from 'rollup-plugin-uglify'
-import pkg from './package.json'
+const resolve = require('rollup-plugin-node-resolve')
+const commonjs = require('rollup-plugin-commonjs')
+const buble = require('rollup-plugin-buble')
+const terser = require('rollup-plugin-terser').terser
+const pkg = require('./package.json')
-const babelConfig = babelrc()
-babelConfig.presets.find(p => p[0] === 'env')[1].modules = false
-babelConfig.plugins = babelConfig.plugins.filter(p => p !== 'add-module-exports')
-babelConfig.plugins.push('external-helpers')
-
-export default [
+module.exports = [
+ // ES5 Non-minified
{
- input: 'src/index.js',
+ input: 'build/es5.js',
output: {
file: pkg.browser,
format: 'umd',
@@ -21,8 +16,47 @@ export default [
plugins: [
resolve(),
commonjs(),
- babel(babelConfig),
- uglify(),
+ buble({transforms: {dangerousForOf: true}}),
+ ],
+ },
+ // ES5 Minified
+ {
+ input: 'build/es5.js',
+ output: {
+ file: pkg.browser.replace(/\.js$/, '.min.js'),
+ format: 'umd',
+ name: 'JSON5',
+ },
+ plugins: [
+ resolve(),
+ commonjs(),
+ buble({transforms: {dangerousForOf: true}}),
+ terser(),
+ ],
+ },
+ // ES6 Modules Non-minified
+ {
+ input: 'lib/index.js',
+ output: {
+ file: pkg.browser.replace(/\.js$/, '.mjs'),
+ format: 'esm',
+ },
+ plugins: [
+ resolve(),
+ commonjs(),
+ ],
+ },
+ // ES6 Modules Minified
+ {
+ input: 'lib/index.js',
+ output: {
+ file: pkg.browser.replace(/\.js$/, '.min.mjs'),
+ format: 'esm',
+ },
+ plugins: [
+ resolve(),
+ commonjs(),
+ terser(),
],
},
]
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index f0b82894..00000000
--- a/src/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import parse from './parse'
-import stringify from './stringify'
-
-export default {
- parse,
- stringify,
-}
diff --git a/src/util.js b/src/util.js
deleted file mode 100644
index dd2a8992..00000000
--- a/src/util.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import * as unicode from '../lib/unicode'
-
-export function isSpaceSeparator (c) {
- return unicode.Space_Separator.test(c)
-}
-
-export function isIdStartChar (c) {
- return (
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c === '$') || (c === '_') ||
- unicode.ID_Start.test(c)
- )
-}
-
-export function isIdContinueChar (c) {
- return (
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- (c === '$') || (c === '_') ||
- (c === '\u200C') || (c === '\u200D') ||
- unicode.ID_Continue.test(c)
- )
-}
-
-export function isDigit (c) {
- return /[0-9]/.test(c)
-}
-
-export function isHexDigit (c) {
- return /[0-9A-Fa-f]/.test(c)
-}
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 122925a8..3d1ca827 100644
--- a/test/cli.js
+++ b/test/cli.js
@@ -1,16 +1,15 @@
-import assert from 'assert'
-import child from 'child_process'
-import fs from 'fs'
-import path from 'path'
-
-import pkg from '../package.json'
+const assert = require('assert')
+const child = require('child_process')
+const fs = require('fs')
+const path = require('path')
+const pkg = require('../package.json')
const cliPath = path.resolve(__dirname, '../lib/cli.js')
-describe('CLI', function () {
- this.timeout(10000)
+const t = require('tap')
- it('converts JSON5 to JSON from stdin to stdout', done => {
+t.test('CLI', t => {
+ t.test('converts JSON5 to JSON from stdin to stdout', t => {
const proc = child.spawn(process.execPath, [cliPath])
let output = ''
proc.stdout.on('data', data => {
@@ -19,13 +18,13 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert.strictEqual(output, '{"a":1,"b":2}')
- done()
+ t.end()
})
fs.createReadStream(path.resolve(__dirname, 'test.json5')).pipe(proc.stdin)
})
- it('reads from the specified file', done => {
+ t.test('reads from the specified file', t => {
const proc = child.spawn(
process.execPath,
[
@@ -41,11 +40,11 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert.strictEqual(output, '{"a":1,"b":2}')
- done()
+ t.end()
})
})
- it('indents output with the number of spaces specified', done => {
+ t.test('indents output with the number of spaces specified with -s', t => {
const proc = child.spawn(
process.execPath,
[
@@ -63,11 +62,33 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert.strictEqual(output, '{\n "a": 1,\n "b": 2\n}')
- done()
+ t.end()
})
})
- it('indents output with tabs when specified', done => {
+ 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,
[
@@ -85,11 +106,11 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert.strictEqual(output, '{\n\t"a": 1,\n\t"b": 2\n}')
- done()
+ t.end()
})
})
- it('outputs to the specified file', done => {
+ t.test('outputs to the specified file with -o', t => {
const proc = child.spawn(
process.execPath,
[
@@ -108,17 +129,46 @@ describe('CLI', function () {
),
'{"a":1,"b":2}'
)
- done()
+ t.end()
})
- after(() => {
+ t.tearDown(() => {
try {
fs.unlinkSync(path.resolve(__dirname, 'output.json'))
} catch (err) {}
})
})
- it('validates valid JSON5 files', done => {
+ 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,
[
@@ -130,11 +180,27 @@ describe('CLI', function () {
proc.on('exit', code => {
assert.strictEqual(code, 0)
- done()
+ t.end()
})
})
- it('validates invalid JSON5 files', done => {
+ 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,
[
@@ -155,11 +221,11 @@ describe('CLI', function () {
proc.on('exit', code => {
assert.strictEqual(code, 1)
- done()
+ t.end()
})
})
- it('outputs the version number when specified', done => {
+ t.test('outputs the version number when specified with -V', t => {
const proc = child.spawn(process.execPath, [cliPath, '-V'])
let output = ''
@@ -169,11 +235,25 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert.strictEqual(output, pkg.version + '\n')
- done()
+ t.end()
+ })
+ })
+
+ 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()
})
})
- it('outputs usage information when specified', done => {
+ t.test('outputs usage information when specified with -h', t => {
const proc = child.spawn(process.execPath, [cliPath, '-h'])
let output = ''
@@ -183,11 +263,25 @@ describe('CLI', function () {
proc.stdout.on('end', () => {
assert(/Usage/.test(output))
- done()
+ t.end()
+ })
+ })
+
+ 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()
})
})
- it('is backward compatible with v0.5.1', done => {
+ t.test('is backward compatible with v0.5.1 with -c', t => {
const proc = child.spawn(
process.execPath,
[
@@ -205,13 +299,43 @@ describe('CLI', function () {
),
'{"a":1,"b":2}'
)
- done()
+ t.end()
+ })
+
+ t.tearDown(() => {
+ try {
+ fs.unlinkSync(path.resolve(__dirname, 'test.json'))
+ } catch (err) {}
+ })
+ })
+
+ 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()
})
- after(() => {
+ 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 0764779c..50f590cf 100644
--- a/test/errors.js
+++ b/test/errors.js
@@ -1,442 +1,377 @@
-import assert from 'assert'
-import JSON5 from '../lib'
-
-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 hexidecimal 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 JSON5 = require('../lib')
+
+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 9d4f4e02..e305767e 100644
--- a/test/parse.js
+++ b/test/parse.js
@@ -1,219 +1,343 @@
-import assert from 'assert'
-import sinon from 'sinon'
-import JSON5 from '../lib'
-
-describe('JSON5', () => {
- describe('#parse()', () => {
- describe('objects', () => {
- it('parses empty objects', () => {
- assert.deepStrictEqual(JSON5.parse('{}'), {})
- })
-
- it('parses double string property names', () => {
- assert.deepStrictEqual(JSON5.parse('{"a":1}'), {a: 1})
- })
-
- it('parses single string property names', () => {
- assert.deepStrictEqual(JSON5.parse("{'a':1}"), {a: 1})
- })
-
- it('parses unquoted property names', () => {
- assert.deepStrictEqual(JSON5.parse('{a:1}'), {a: 1})
- })
-
- it('parses special character property names', () => {
- assert.deepStrictEqual(JSON5.parse('{$_:1,_$:2,a\u200C:3}'), {$_: 1, _$: 2, 'a\u200C': 3})
- })
-
- it('parses unicode property names', () => {
- assert.deepStrictEqual(JSON5.parse('{ùńîċõďë:9}'), {'ùńîċõďë': 9})
- })
-
- it('parses escaped property names', () => {
- assert.deepStrictEqual(JSON5.parse('{\\u0061\\u0062:1,\\u0024\\u005F:2,\\u005F\\u0024:3}'), {ab: 1, $_: 2, _$: 3})
- })
-
- it('parses multiple properties', () => {
- assert.deepStrictEqual(JSON5.parse('{abc:1,def:2}'), {abc: 1, def: 2})
- })
-
- it('parses nested objects', () => {
- assert.deepStrictEqual(JSON5.parse('{a:{b:2}}'), {a: {b: 2}})
- })
- })
-
- describe('arrays', () => {
- it('parses empty arrays', () => {
- assert.deepStrictEqual(JSON5.parse('[]'), [])
- })
-
- it('parses array values', () => {
- assert.deepStrictEqual(JSON5.parse('[1]'), [1])
- })
-
- it('parses multiple array values', () => {
- assert.deepStrictEqual(JSON5.parse('[1,2]'), [1, 2])
- })
-
- it('parses nested arrays', () => {
- assert.deepStrictEqual(JSON5.parse('[1,[2,3]]'), [1, [2, 3]])
- })
- })
-
- it('parses nulls', () => {
- assert.strictEqual(JSON5.parse('null'), null)
- })
-
- it('parses true', () => {
- assert.strictEqual(JSON5.parse('true'), true)
- })
-
- it('parses false', () => {
- assert.strictEqual(JSON5.parse('false'), false)
- })
-
- describe('numbers', () => {
- it('parses leading zeroes', () => {
- assert.deepStrictEqual(JSON5.parse('[0,0.,0e0]'), [0, 0, 0])
- })
-
- it('parses integers', () => {
- assert.deepStrictEqual(JSON5.parse('[1,23,456,7890]'), [1, 23, 456, 7890])
- })
-
- it('parses signed numbers', () => {
- assert.deepStrictEqual(JSON5.parse('[-1,+2,-.1,-0]'), [-1, +2, -0.1, -0])
- })
-
- it('parses leading decimal points', () => {
- assert.deepStrictEqual(JSON5.parse('[.1,.23]'), [0.1, 0.23])
- })
-
- it('parses fractional numbers', () => {
- assert.deepStrictEqual(JSON5.parse('[1.0,1.23]'), [1, 1.23])
- })
-
- it('parses exponents', () => {
- assert.deepStrictEqual(JSON5.parse('[1e0,1e1,1e01,1.e0,1.1e0,1e-1,1e+1]'), [1, 10, 10, 1, 1.1, 0.1, 10])
- })
-
- it('parses hexadecimal numbers', () => {
- assert.deepStrictEqual(JSON5.parse('[0x1,0x10,0xff,0xFF]'), [1, 16, 255, 255])
- })
+const assert = require('assert')
+const sinon = require('sinon')
+const JSON5 = require('../lib')
+
+const t = require('tap')
+
+t.test('parse(text)', t => {
+ t.test('objects', t => {
+ t.strictSame(
+ JSON5.parse('{}'),
+ {},
+ 'parses empty objects'
+ )
+
+ t.strictSame(
+ JSON5.parse('{"a":1}'),
+ {a: 1},
+ 'parses double string property names'
+ )
+
+ t.strictSame(
+ JSON5.parse("{'a':1}"),
+ {a: 1},
+ 'parses single string property names'
+ )
+
+ t.strictSame(
+ JSON5.parse('{a:1}'),
+ {a: 1},
+ 'parses unquoted property names'
+ )
+
+ t.strictSame(
+ JSON5.parse('{$_:1,_$:2,a\u200C:3}'),
+ {$_: 1, _$: 2, 'a\u200C': 3},
+ 'parses special character property names'
+ )
+
+ t.strictSame(
+ JSON5.parse('{ùńîċõďë:9}'),
+ {'ùńîċõďë': 9},
+ 'parses unicode property names'
+ )
+
+ t.strictSame(
+ JSON5.parse('{\\u0061\\u0062:1,\\u0024\\u005F:2,\\u005F\\u0024:3}'),
+ {ab: 1, $_: 2, _$: 3},
+ '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},
+ 'parses multiple properties'
+ )
+
+ t.strictSame(
+ JSON5.parse('{a:{b:2}}'),
+ {a: {b: 2}},
+ 'parses nested objects'
+ )
+
+ t.end()
+ })
- it('parses signed and unsiged Infinity', () => {
- assert.deepStrictEqual(JSON5.parse('[Infinity,-Infinity]'), [Infinity, -Infinity])
- })
+ t.test('arrays', t => {
+ t.strictSame(
+ JSON5.parse('[]'),
+ [],
+ 'parses empty arrays'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1]'),
+ [1],
+ 'parses array values'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1,2]'),
+ [1, 2],
+ 'parses multiple array values'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1,[2,3]]'),
+ [1, [2, 3]],
+ 'parses nested arrays'
+ )
+
+ t.end()
+ })
- it('parses signed and unsigned NaN', () => {
- assert(isNaN(JSON5.parse('NaN')))
- assert(isNaN(JSON5.parse('-NaN')))
- })
- })
+ t.test('nulls', t => {
+ t.equal(
+ JSON5.parse('null'),
+ null,
+ 'parses nulls'
+ )
- describe('strings', () => {
- it('parses double quoted strings', () => {
- assert.strictEqual(JSON5.parse('"abc"'), 'abc')
- })
-
- it('parses single quoted strings', () => {
- assert.strictEqual(JSON5.parse("'abc'"), 'abc')
- })
-
- it('parses nested quotes strings', () => {
- assert.deepStrictEqual(JSON5.parse(`['"',"'"]`), ['"', "'"])
- })
-
- it('parses escaped characters', () => {
- // eslint-disable-next-line no-useless-escape
- assert.strictEqual(JSON5.parse(`'\\b\\f\\n\\r\\t\\v\\0\\x0f\\u01fF\\\n\\\r\n\\\r\\\u2028\\\u2029\\a\\'\\"'`), `\b\f\n\r\t\v\0\x0f\u01FF\a'"`)
- })
-
- it('parses line and paragraph separators with a warning', () => {
- const warn = sinon.stub(console, 'warn').callsFake(message => {
- assert(message.indexOf('not valid ECMAScript') >= 0)
- })
- assert.strictEqual(JSON5.parse("'\u2028\u2029'"), '\u2028\u2029')
- assert(warn.calledTwice)
- warn.restore()
- })
- })
+ t.end()
+ })
- describe('comments', () => {
- it('parses single-line comments', () => {
- assert.deepStrictEqual(JSON5.parse('{//comment\n}'), {})
- })
+ t.test('Booleans', t => {
+ t.equal(
+ JSON5.parse('true'),
+ true,
+ 'parses true'
+ )
- it('parses single-line comments at end of input', () => {
- assert.deepStrictEqual(JSON5.parse('{}//comment'), {})
- })
+ t.equal(
+ JSON5.parse('false'),
+ false,
+ 'parses false'
+ )
- it('parses multi-line comments', () => {
- assert.deepStrictEqual(JSON5.parse('{/*comment\n** */}'), {})
- })
- })
+ t.end()
+ })
- it('parses whitespace', () => {
- assert.deepStrictEqual(JSON5.parse('{\t\v\f \u00A0\uFEFF\n\r\u2028\u2029\u2003}'), {})
- })
+ t.test('numbers', t => {
+ t.strictSame(
+ JSON5.parse('[0,0.,0e0]'),
+ [0, 0, 0],
+ 'parses leading zeroes'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1,23,456,7890]'),
+ [1, 23, 456, 7890],
+ 'parses integers'
+ )
+
+ t.strictSame(
+ JSON5.parse('[-1,+2,-.1,-0]'),
+ [-1, +2, -0.1, -0],
+ 'parses signed numbers'
+ )
+
+ t.strictSame(
+ JSON5.parse('[.1,.23]'),
+ [0.1, 0.23],
+ 'parses leading decimal points'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1.0,1.23]'),
+ [1, 1.23],
+ 'parses fractional numbers'
+ )
+
+ t.strictSame(
+ JSON5.parse('[1e0,1e1,1e01,1.e0,1.1e0,1e-1,1e+1]'),
+ [1, 10, 10, 1, 1.1, 0.1, 10],
+ 'parses exponents'
+ )
+
+ t.strictSame(
+ JSON5.parse('[0x1,0x10,0xff,0xFF]'),
+ [1, 16, 255, 255],
+ 'parses hexadecimal numbers'
+ )
+
+ t.strictSame(
+ JSON5.parse('[Infinity,-Infinity]'),
+ [Infinity, -Infinity],
+ 'parses signed and unsigned Infinity'
+ )
+
+ t.ok(
+ isNaN(JSON5.parse('NaN')),
+ 'parses NaN'
+ )
+
+ t.ok(
+ isNaN(JSON5.parse('-NaN')),
+ 'parses signed NaN'
+ )
+
+ t.strictSame(
+ JSON5.parse('1'),
+ 1,
+ 'parses 1'
+ )
+
+ t.strictSame(
+ JSON5.parse('+1.23e100'),
+ 1.23e100,
+ 'parses +1.23e100'
+ )
+
+ t.strictSame(
+ JSON5.parse('0x1'),
+ 0x1,
+ 'parses bare hexadecimal number'
+ )
+
+ t.strictSame(
+ JSON5.parse('-0x0123456789abcdefABCDEF'),
+ -0x0123456789abcdefABCDEF,
+ 'parses bare long hexadecimal number'
+ )
+
+ t.end()
})
- describe('#parse(text, reviver)', () => {
- it('modifies property values', () => {
- assert.deepStrictEqual(
- JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? 'revived' : v),
- {a: 'revived', b: 2}
- )
- })
+ t.test('strings', t => {
+ t.equal(
+ JSON5.parse('"abc"'),
+ 'abc',
+ 'parses double quoted strings'
+ )
+
+ t.equal(
+ JSON5.parse("'abc'"),
+ 'abc',
+ 'parses single quoted strings'
+ )
+
+ t.strictSame(
+ JSON5.parse(`['"',"'"]`),
+ ['"', "'"],
+ 'parses quotes in strings')
+
+ t.equal(
+ JSON5.parse(`'\\b\\f\\n\\r\\t\\v\\0\\x0f\\u01fF\\\n\\\r\n\\\r\\\u2028\\\u2029\\a\\'\\"'`),
+ `\b\f\n\r\t\v\0\x0f\u01FF\a'"`, // eslint-disable-line no-useless-escape
+ 'parses escaped characters'
+ )
+
+ t.test('parses line and paragraph separators with a warning', t => {
+ const mock = sinon.mock(console)
+ mock
+ .expects('warn')
+ .twice()
+ .calledWithMatch('not valid ECMAScript')
- it('modifies nested object property values', () => {
assert.deepStrictEqual(
- JSON5.parse('{a:{b:2}}', (k, v) => (k === 'b') ? 'revived' : v),
- {a: {b: 'revived'}}
+ JSON5.parse("'\u2028\u2029'"),
+ '\u2028\u2029'
)
- })
- it('deletes property values', () => {
- assert.deepStrictEqual(
- JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? undefined : v),
- {b: 2}
- )
- })
+ mock.verify()
+ mock.restore()
- it('modifies array values', () => {
- assert.deepStrictEqual(
- JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? 'revived' : v),
- [0, 'revived', 2]
- )
+ t.end()
})
- it('modifies nested array values', () => {
- assert.deepStrictEqual(
- JSON5.parse('[0,[1,2,3]]', (k, v) => (k === '2') ? 'revived' : v),
- [0, [1, 2, 'revived']]
- )
- })
+ t.end()
+ })
- it('deletes array values', () => {
- assert.deepStrictEqual(
- JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? undefined : v),
- // eslint-disable-next-line no-sparse-arrays
- [0, , 2]
- )
- })
+ t.test('comments', t => {
+ t.strictSame(
+ JSON5.parse('{//comment\n}'),
+ {},
+ 'parses single-line comments'
+ )
+
+ t.strictSame(
+ JSON5.parse('{}//comment'),
+ {},
+ 'parses single-line comments at end of input'
+ )
+
+ t.strictSame(
+ JSON5.parse('{/*comment\n** */}'),
+ {},
+ 'parses multi-line comments'
+ )
+
+ t.end()
+ })
- it('modifies the root value', () => {
- assert.strictEqual(
- JSON5.parse('1', (k, v) => (k === '') ? 'revived' : v),
- 'revived'
- )
- })
+ t.test('whitespace', t => {
+ t.strictSame(
+ JSON5.parse('{\t\v\f \u00A0\uFEFF\n\r\u2028\u2029\u2003}'),
+ {},
+ 'parses whitespace'
+ )
- it('sets `this` to the parent value', () => {
- assert.deepStrictEqual(
- JSON5.parse('{a:{b:2}}', function (k, v) { return (k === 'b' && this.b) ? 'revived' : v }),
- {a: {b: 'revived'}}
- )
- })
+ t.end()
})
+
+ t.end()
+})
+
+t.test('parse(text, reviver)', t => {
+ t.strictSame(
+ JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? 'revived' : v),
+ {a: 'revived', b: 2},
+ 'modifies property values'
+ )
+
+ t.strictSame(
+ JSON5.parse('{a:{b:2}}', (k, v) => (k === 'b') ? 'revived' : v),
+ {a: {b: 'revived'}},
+ 'modifies nested object property values'
+ )
+
+ t.strictSame(
+ JSON5.parse('{a:1,b:2}', (k, v) => (k === 'a') ? undefined : v),
+ {b: 2},
+ 'deletes property values'
+ )
+
+ t.strictSame(
+ JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? 'revived' : v),
+ [0, 'revived', 2],
+ 'modifies array values'
+ )
+
+ t.strictSame(
+ JSON5.parse('[0,[1,2,3]]', (k, v) => (k === '2') ? 'revived' : v),
+ [0, [1, 2, 'revived']],
+ 'modifies nested array values'
+ )
+
+ t.strictSame(
+ JSON5.parse('[0,1,2]', (k, v) => (k === '1') ? undefined : v),
+ [0, , 2], // eslint-disable-line no-sparse-arrays
+ 'deletes array values'
+ )
+
+ t.equal(
+ JSON5.parse('1', (k, v) => (k === '') ? 'revived' : v),
+ 'revived',
+ 'modifies the root value'
+ )
+
+ t.strictSame(
+ JSON5.parse('{a:{b:2}}', function (k, v) { return (k === 'b' && this.b) ? 'revived' : v }),
+ {a: {b: 'revived'}},
+ 'sets `this` to the parent value'
+ )
+
+ t.end()
})
diff --git a/test/require.js b/test/require.js
index 4fd22c62..86b9b470 100644
--- a/test/require.js
+++ b/test/require.js
@@ -1,22 +1,29 @@
-import assert from 'assert'
-import sinon from 'sinon'
+const assert = require('assert')
+const sinon = require('sinon')
-describe('require(*.json5)', () => {
- it('parses a JSON5 document', () => {
+const t = require('tap')
+
+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 21363332..e256a314 100644
--- a/test/stringify.js
+++ b/test/stringify.js
@@ -1,330 +1,482 @@
-import assert from 'assert'
-import JSON5 from '../lib'
-
-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}")
- })
+const assert = require('assert')
+const JSON5 = require('../lib')
+
+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 double quoted string property names', () => {
- assert.strictEqual(JSON5.stringify({"a'": 1}), `{"a'":1}`)
- })
+ t.strictSame(
+ JSON5.stringify({a: 1}),
+ '{a:1}',
+ 'stringifies unquoted property names'
+ )
- it('stringifies empty string property names', () => {
- assert.strictEqual(JSON5.stringify({'': 1}), "{'':1}")
- })
+ t.strictSame(
+ JSON5.stringify({'a-b': 1}),
+ "{'a-b':1}",
+ 'stringifies single quoted string 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'": 1}),
+ `{"a'":1}`,
+ 'stringifies double quoted string property names'
+ )
- it('stringifies unicode property names', () => {
- assert.strictEqual(JSON5.stringify({'ùńîċõďë': 9}), '{ùńîċõďë:9}')
- })
+ t.strictSame(
+ JSON5.stringify({'': 1}),
+ "{'':1}",
+ 'stringifies empty 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, _$: 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 single quotes', () => {
- assert.strictEqual(JSON5.stringify(`'"`), `'\\'"'`)
- })
+ t.strictSame(
+ JSON5.stringify('\0\x001'),
+ "'\\0\\x001'",
+ 'stringifies escaped null characters'
+ )
- it('stringifies escaped double quotes', () => {
- assert.strictEqual(JSON5.stringify(`''"`), `"''\\""`)
- })
+ t.strictSame(
+ JSON5.stringify(`'"`),
+ `'\\'"'`,
+ 'stringifies escaped single quotes'
+ )
- it('stringifies escaped line and paragraph separators', () => {
- assert.strictEqual(JSON5.stringify('\u2028\u2029'), "'\\u2028\\u2029'")
- })
+ t.strictSame(
+ JSON5.stringify(`''"`),
+ `"''\\""`,
+ 'stringifies escaped double quotes'
+ )
- it('stringifies String objects', () => {
+ t.strictSame(
+ JSON5.stringify('\u2028\u2029'),
+ "'\\u2028\\u2029'",
+ 'stringifies escaped line and paragraph separators'
+ )
+
+ 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]')
+ t.end()
})
- 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]')
- })
-
- 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()
})
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy