diff --git a/src/index.js b/src/index.js index a1a1b7b..1051754 100644 --- a/src/index.js +++ b/src/index.js @@ -2,9 +2,6 @@ MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ - -import util from 'util'; - import JSON5 from 'json5'; import { getOptions } from 'loader-utils'; @@ -25,5 +22,11 @@ export default function loader(source) { this.emitError(error); } - return `module.exports = ${util.inspect(value, { depth: null })}`; + value = value + ? JSON5.stringify(value, null) + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029') + : source; + + return `module.exports = ${value}`; } diff --git a/test/__snapshots__/loader.test.js.snap b/test/__snapshots__/loader.test.js.snap new file mode 100644 index 0000000..1954a93 --- /dev/null +++ b/test/__snapshots__/loader.test.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`loader should handle valid JSON5 1`] = `"module.exports = {unquoted:'and you can quote me on that',singleQuotes:'I can use \\"double quotes\\" here',lineBreaks:\\"Look, Mom! No \\\\\\\\n's!\\",hexadecimal:912559,leadingDecimalPoint:0.8675309,andTrailing:8675309,positiveSign:1,trailingComma:'in objects',andIn:['arrays'],backwardsCompatible:'with JSON'}"`; + +exports[`loader should invalid characters 1`] = `"module.exports = {foo:'\\\\u2028\\\\u2029'}"`; + +exports[`loader should preserve -Infinity 1`] = `"module.exports = {to:-Infinity}"`; + +exports[`loader should preserve Infinity 1`] = `"module.exports = {to:Infinity}"`; + +exports[`loader should preserve NaN 1`] = `"module.exports = {nan:NaN}"`; + +exports[`loader should preserve null 1`] = `"module.exports = {null:null}"`; diff --git a/test/loader.test.js b/test/loader.test.js index dd6efcf..195f018 100644 --- a/test/loader.test.js +++ b/test/loader.test.js @@ -1,42 +1,134 @@ -import loader from '../src'; +import JSON5 from 'json5'; -const staticJson5 = "{name: 'test'}"; +import loader from '../src'; describe('loader', () => { - test('should export the loader', (done) => { + it('should export the loader', (done) => { expect(loader).toBeInstanceOf(Function); + done(); }); - test('should convert to requires', (done) => { - const content = loader.call({}, staticJson5); - expect(content).toBe("module.exports = { name: 'test' }"); + it('should handle valid JSON5', (done) => { + const json5 = `{ + // comments + unquoted: 'and you can quote me on that', + singleQuotes: 'I can use "double quotes" here', + lineBreaks: "Look, Mom! \\ +No \\\\n's!", + hexadecimal: 0xdecaf, + leadingDecimalPoint: .8675309, andTrailing: 8675309., + positiveSign: +1, + trailingComma: 'in objects', andIn: ['arrays',], + "backwardsCompatible": "with JSON", +}`; + const emitError = jest.fn(); + const content = loader.call( + { + emitError, + }, + json5 + ); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + done(); }); - test('should handle invalid JSON5', (done) => { - const brokenJson5 = '{broken: json5}'; + it('should invalid characters', (done) => { + const json5 = `{foo: '\u2028\u2029'}`; const emitError = jest.fn(); - - loader.call( + const content = loader.call( { emitError, }, - brokenJson5 + json5 ); - expect(emitError).toHaveBeenCalledWith(expect.any(SyntaxError)); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + + done(); + }); + + it('should preserve Infinity', (done) => { + const json5 = '{to : Infinity}'; + const content = loader.call({}, json5); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + + done(); + }); + + it('should preserve -Infinity', (done) => { + const json5 = '{to : -Infinity}'; + const content = loader.call({}, json5); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + done(); }); - test('should preserve Infinity', (done) => { - const content = loader.call({}, '{to : Infinity}'); - expect(content).toBe('module.exports = { to: Infinity }'); + it('should preserve null', (done) => { + const json5 = '{null : null}'; + const content = loader.call({}, json5); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + done(); }); - test('should preserve NaN', (done) => { + it('should preserve NaN', (done) => { + const json5 = '{nan : NaN}'; const content = loader.call({}, '{nan : NaN}'); - expect(content).toBe('module.exports = { nan: NaN }'); + + expect(content).toMatchSnapshot(); + + // eslint-disable-next-line no-eval + const js = eval(content); + + expect(JSON5.stringify(js)).toEqual(JSON5.stringify(JSON5.parse(json5))); + + done(); + }); + + it('should handle invalid JSON5', (done) => { + const brokenJson5 = '{broken: json5}'; + const emitError = jest.fn(); + + loader.call( + { + emitError, + }, + brokenJson5 + ); + + expect(emitError).toHaveBeenCalledWith(expect.any(SyntaxError)); + done(); }); });