liquid-json
Advanced tools
Comparing version 0.3.1 to 1.0.0-beta.1
@@ -18,2 +18,3 @@ var bomb = { | ||
* Checks whether string has BOM | ||
* | ||
* @param {String} str An input string that is tested for the presence of BOM | ||
@@ -20,0 +21,0 @@ * |
182
lib/index.js
@@ -9,2 +9,5 @@ /**! | ||
ERROR_NAME = 'JSONError', | ||
BOOLEAN = 'boolean', | ||
FUNCTION = 'function', | ||
NUM_ZERO = 0, | ||
@@ -15,14 +18,17 @@ parse; // fn | ||
* Accept a string as JSON and return an object. | ||
* | ||
* @private | ||
* | ||
* @param {String} str The input stringified JSON object to be parsed. | ||
* @param {String} text The input stringified JSON object to be parsed. | ||
* @param {Function=} [reviver] A customizer function to be used within the fallback (BOM friendly) JSON parser. | ||
* @param {Boolean=} [strict] Set to true to treat the occurrence of BOM as a fatal error. | ||
* | ||
* @returns {Object} The parsed JSON object constructed from str | ||
* @throws {SyntaxError} If `str` is not a valid JSON | ||
* @throws {SyntaxError} In `strict` mode if `str` contains BOM | ||
* @returns {Object} The parsed JSON object constructed from text | ||
* @throws {SyntaxError} If `text` is not a valid JSON | ||
* @throws {SyntaxError} In `strict` mode if `text` contains BOM | ||
* | ||
* @returns {Object} - Returns JS Object derived after parsing `text` parameter | ||
*/ | ||
parse = function (str, reviver, strict) { | ||
var bomMarkerIndex = bomb.indexOfBOM(str); | ||
parse = function (text, reviver, strict) { | ||
var bomMarkerIndex = bomb.indexOfBOM(text); | ||
@@ -34,10 +40,10 @@ if (bomMarkerIndex) { | ||
// clean up BOM if not strict | ||
str = str.slice(bomMarkerIndex); | ||
text = text.slice(bomMarkerIndex); | ||
} | ||
try { // first try and use normal JSON.parse as this is faster | ||
return JSON.parse(str, reviver); | ||
return JSON.parse(text, reviver); | ||
} | ||
catch (err) { // if JSON.parse fails, we try using a more verbose parser | ||
fallback.parse(str, { | ||
fallback.parse(text, { | ||
mode: FALLBACK_MODE, | ||
@@ -54,4 +60,24 @@ reviver: reviver | ||
module.exports = { | ||
parse: function (str, reviver, relaxed) { | ||
if ((typeof reviver === 'boolean') && (relaxed === null)) { | ||
/** | ||
* Converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is | ||
* specified, or optionally including only the specified properties if a replacer array is specified. | ||
* | ||
* @param {Object|Array} text - The value to convert to a JSON string | ||
* @param {Function=} reviver - A function that alters the behavior of the stringification process, | ||
* or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of | ||
* the value object to be included in the JSON string. If this value is null or not provided, all properties of | ||
* the object are included in the resulting JSON string. | ||
* @param {Number|String=} relaxed A String or Number object that's used to insert white space into the output | ||
* JSON string for readability purposes. If this is a Number, it indicates the number of space characters to use | ||
* as white space; this number is capped at 10 if it's larger than that. Values less than 1 indicate that | ||
* no space should be used. If this is a String, the string (or the first 10 characters of the string, if it's | ||
* longer than that) is used as white space. If this parameter is not provided (or is null), no white space is | ||
* used. | ||
* | ||
* @returns {Object} | ||
* | ||
* @throws {JSONError} If the `text` parameter contains invalid JSON syntax | ||
*/ | ||
parse: function (text, reviver, relaxed) { | ||
if ((typeof reviver === BOOLEAN) && (relaxed === null)) { | ||
relaxed = reviver; | ||
@@ -62,3 +88,3 @@ reviver = null; | ||
try { | ||
return parse(str, reviver, relaxed); | ||
return parse(text, reviver, relaxed); | ||
} | ||
@@ -72,6 +98,26 @@ // we do this simply to set the error name and as such making it more identifiable | ||
stringify: function () { | ||
/** | ||
* Converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is | ||
* specified, or optionally including only the specified properties if a replacer array is specified. | ||
* | ||
* @param {Object|Array} value - The value to convert to a JSON string | ||
* @param {Function=} replacer - A function that alters the behavior of the stringification process, | ||
* or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of | ||
* the value object to be included in the JSON string. If this value is null or not provided, all properties of | ||
* the object are included in the resulting JSON string. | ||
* @param {Number|String=} indent A String or Number object that's used to insert white space into the output | ||
* JSON string for readability purposes. If this is a Number, it indicates the number of space characters to use | ||
* as white space; this number is capped at 10 if it's larger than that. Values less than 1 indicate that | ||
* no space should be used. If this is a String, the string (or the first 10 characters of the string, if it's | ||
* longer than that) is used as white space. If this parameter is not provided (or is null), no white space is | ||
* used. | ||
* | ||
* @returns {String} | ||
* | ||
* @throws {JSONError} If the value cannot be converted to JSON | ||
*/ | ||
stringify: function (value, replacer, indent) { | ||
try { | ||
// eslint-disable-next-line prefer-spread | ||
return JSON.stringify.apply(JSON, arguments); | ||
return JSON.stringify(value, replacer, indent); | ||
} | ||
@@ -83,3 +129,111 @@ // we do this simply to set the error name and as such making it more identifiable | ||
} | ||
}, | ||
async: { | ||
/** | ||
* Parses a JSON string, constructing the JavaScript value or object described by the string. An optional | ||
* reviver function can be provided to perform a transformation on the resulting object before it is returned. | ||
* | ||
* This is an asynchronous variant of JSON.parse() and accepts a callback where it returns the result as | ||
* well as the error (if any.) It does not throw anything that one would otherwise need to trap within a | ||
* try-catch block. | ||
* | ||
* @param {String} text - The string to parse as JSON | ||
* @param {Object=} options - Provide parsing options | ||
* @param {Function=} options.reviver - If a function, prescribes how the value originally produced by parsing | ||
* is transformed, before being returned. | ||
* @param {Boolean=true} options.relaxed - When set to `false`, this causes the presence of `BOM` mark in `text` | ||
* parameter as a fatal error. Otherwise, the BOM is stripped out before parsing. | ||
* @param {Function} callback - receives parameters `err:Error, json:Object` | ||
*/ | ||
parse: function (text, options, callback) { | ||
// normalise polymorphic function to make `options` optional | ||
if (typeof options === FUNCTION && !callback) { | ||
callback = options; | ||
options = null; | ||
} | ||
// check whether callback is a function and otherwise unset to avoid erroneous calls | ||
(typeof callback !== FUNCTION) && (callback = null); | ||
// move up the event loop to make this asynchronous | ||
setTimeout(function () { | ||
var reviver, | ||
relaxed, | ||
json; | ||
// get options, if provided by user | ||
if (options) { | ||
reviver = options.reviver; | ||
relaxed = options.relaxed; | ||
} | ||
try { | ||
json = parse(text, reviver, relaxed); | ||
} | ||
catch (err) { | ||
err.name = ERROR_NAME; | ||
return callback && callback(err); | ||
} | ||
callback && callback(null, json); | ||
}, NUM_ZERO); | ||
}, | ||
/** | ||
* Converts a JavaScript value to a JSON string, optionally replacing values if a replacer function is | ||
* specified, or optionally including only the specified properties if a replacer array is specified. | ||
* | ||
* This is an asynchronous variant of JSON.stringify() and accepts a callback where it returns the result as | ||
* well as the error (if any.) It does not throw anything that one would otherwise need to trap within a | ||
* try-catch block. | ||
* | ||
* @param {Object|Array} value - The value to convert to a JSON string | ||
* @param {Object=} options - Provide stringification options | ||
* @param {Function=} options.replacer - A function that alters the behavior of the stringification process, | ||
* or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of | ||
* the value object to be included in the JSON string. If this value is null or not provided, all properties of | ||
* the object are included in the resulting JSON string. | ||
* @param {Number|String=} options.indent A String or Number object that's used to insert white space into the | ||
* output JSON string for readability purposes. If this is a Number, it indicates the number of space characters | ||
* to use as white space; this number is capped at 10 if it's larger than that. Values less than 1 indicate that | ||
* no space should be used. If this is a String, the string (or the first 10 characters of the string, if it's | ||
* longer than that) is used as white space. If this parameter is not provided (or is null), no white space is | ||
* used. | ||
* @param {Function} callback - receives parameters `err:Error, str:String` | ||
*/ | ||
stringify: function (value, options, callback) { | ||
// normalise polymorphic function to make `options` optional | ||
if (typeof options === FUNCTION && !callback) { | ||
callback = options; | ||
options = null; | ||
} | ||
// check whether callback is a function and otherwise unset to avoid erroneous calls | ||
(typeof callback !== FUNCTION) && (callback = null); | ||
// move up the event loop to make this asynchronous | ||
setTimeout(function () { | ||
var replacer, | ||
indent, | ||
str; | ||
// get options, if provided by user | ||
if (options) { | ||
replacer = options.replacer; | ||
indent = options.indent; | ||
} | ||
try { | ||
str = JSON.stringify(value, replacer, indent); | ||
} | ||
catch (err) { | ||
err.name = ERROR_NAME; | ||
return callback && callback(err); | ||
} | ||
callback && callback(null, str); | ||
}, NUM_ZERO); | ||
} | ||
} | ||
}; |
#!/usr/bin/env node | ||
require('shelljs/global'); | ||
require('colors'); | ||
var async = require('async'), | ||
var chalk = require('chalk'), | ||
async = require('async'), | ||
ESLintCLIEngine = require('eslint').CLIEngine, | ||
@@ -10,6 +10,4 @@ | ||
'./lib', | ||
'./bin', | ||
'./test', | ||
'./examples/*.js', | ||
'./npm/*.js', | ||
'./npm', | ||
'./index.js' | ||
@@ -20,3 +18,3 @@ ]; | ||
// banner line | ||
console.info('\nLinting files using eslint...'.yellow.bold); | ||
console.info(chalk.yellow.bold('\nLinting files using eslint...')); | ||
@@ -35,3 +33,3 @@ async.waterfall([ | ||
// log the success of the parser if it has no errors | ||
(errorReport && !errorReport.length) && console.info('eslint ok!'.green); | ||
(errorReport && !errorReport.length) && console.info(chalk.green('eslint ok!')); | ||
// ensure that the exit code is non zero in case there was an error | ||
@@ -38,0 +36,0 @@ next(Number(errorReport && errorReport.length) || 0); |
#!/usr/bin/env node | ||
require('shelljs/global'); | ||
require('colors'); | ||
var fs = require('fs'), | ||
path = require('path'), | ||
var NYC = require('nyc'), | ||
chalk = require('chalk'), | ||
Mocha = require('mocha'), | ||
recursive = require('recursive-readdir'), | ||
COV_REPORT_PATH = '.coverage', | ||
SPEC_SOURCE_DIR = './test/unit'; | ||
@@ -13,16 +14,32 @@ | ||
// banner line | ||
console.info('Running unit tests using mocha...'.yellow.bold); | ||
console.info(chalk.yellow.bold('Running unit tests using mocha...')); | ||
var mocha = new Mocha(); | ||
test('-d', COV_REPORT_PATH) && rm('-rf', COV_REPORT_PATH); | ||
mkdir('-p', COV_REPORT_PATH); | ||
fs.readdir(SPEC_SOURCE_DIR, function (err, files) { | ||
files.filter(function (file) { | ||
var nyc = new NYC({ | ||
reporter: ['text', 'lcov'], | ||
reportDir: COV_REPORT_PATH, | ||
tempDirectory: COV_REPORT_PATH | ||
}); | ||
nyc.wrap(); | ||
// add all spec files to mocha | ||
recursive(SPEC_SOURCE_DIR, function (err, files) { | ||
if (err) { console.error(err); return exit(1); } | ||
var mocha = new Mocha({ timeout: 1000 * 60 }); | ||
files.filter(function (file) { // extract all test files | ||
return (file.substr(-8) === '.test.js'); | ||
}).forEach(function (file) { | ||
mocha.addFile(path.join(SPEC_SOURCE_DIR, file)); | ||
}).forEach(mocha.addFile.bind(mocha)); | ||
mocha.run(function (runError) { | ||
runError && console.error(runError.stack || runError); | ||
nyc.reset(); | ||
nyc.writeCoverageFile(); | ||
nyc.report(); | ||
exit(runError ? 1 : 0); | ||
}); | ||
// start the mocha run | ||
mocha.run(exit); | ||
mocha = null; // cleanup | ||
}); | ||
@@ -29,0 +46,0 @@ }; |
#!/usr/bin/env node | ||
require('shelljs/global'); | ||
require('colors'); | ||
var prettyms = require('pretty-ms'), | ||
var chalk = require('chalk'), | ||
prettyms = require('pretty-ms'), | ||
startedAt = Date.now(); | ||
@@ -10,8 +10,10 @@ | ||
require('./test-lint'), | ||
require('./test-unit') | ||
require('./test-system'), | ||
require('./test-unit'), | ||
require('./test-browser') | ||
], function (code) { | ||
// eslint-disable-next-line max-len | ||
console.info(`\nliquid-json: duration ${prettyms(Date.now() - startedAt)}\nliquid-json: ${code ? 'not ok' : 'ok'}!`[code ? | ||
'red' : 'green']); | ||
console.info(chalk[code ? | ||
// eslint-disable-next-line max-len | ||
'red' : 'green'](`\nliquid-json: duration ${prettyms(Date.now() - startedAt)}\nliquid-json: ${code ? 'not ok' : 'ok'}!`)); | ||
exit(code && (typeof code === 'number' ? code : 1) || 0); | ||
}); |
{ | ||
"name": "liquid-json", | ||
"version": "0.3.1", | ||
"version": "1.0.0-beta.1", | ||
"description": "Implementation of JSON that ignores BOM and thows friendly error", | ||
@@ -8,4 +8,6 @@ "main": "index.js", | ||
"test": "node npm/test.js", | ||
"test-lint": "node npm/test-lint.js", | ||
"test-system": "node npm/test-system.js", | ||
"test-unit": "node npm/test-unit.js", | ||
"test-lint": "node npm/test-lint.js" | ||
"test-browser": "node npm/test-browser.js" | ||
}, | ||
@@ -31,12 +33,27 @@ "author": "Postman Labs <help@getpostman.com> (=)", | ||
"devDependencies": { | ||
"async": "2.0.1", | ||
"colors": "1.1.2", | ||
"eslint": "3.4.0", | ||
"eslint-plugin-jsdoc": "2.3.1", | ||
"eslint-plugin-mocha": "4.5.1", | ||
"eslint-plugin-security": "1.2.0", | ||
"expect.js": "0.3.1", | ||
"mocha": "3.0.2", | ||
"pretty-ms": "2.1.0", | ||
"shelljs": "0.7.4" | ||
"async": "2.6.1", | ||
"browserify": "16.2.2", | ||
"chai": "4.1.2", | ||
"chalk": "2.4.1", | ||
"editorconfig": "0.15.0", | ||
"eslint": "5.4.0", | ||
"eslint-plugin-jsdoc": "3.7.1", | ||
"eslint-plugin-lodash": "2.7.0", | ||
"eslint-plugin-mocha": "5.2.0", | ||
"eslint-plugin-security": "1.4.0", | ||
"js-yaml": "3.12.0", | ||
"karma": "3.0.0", | ||
"karma-browserify": "5.3.0", | ||
"karma-chrome-launcher": "2.2.0", | ||
"karma-mocha": "1.3.0", | ||
"karma-mocha-reporter": "2.2.5", | ||
"lodash": "4.17.10", | ||
"mocha": "5.2.0", | ||
"nyc": "12.0.2", | ||
"parse-gitignore": "1.0.1", | ||
"pretty-ms": "3.2.0", | ||
"recursive-readdir": "2.2.2", | ||
"shelljs": "0.8.2", | ||
"strip-json-comments": "2.0.1", | ||
"watchify": "3.11.0" | ||
}, | ||
@@ -43,0 +60,0 @@ "engines": { |
@@ -20,2 +20,16 @@ # liquid-json | ||
### asynchronous flavour | ||
```javascript | ||
var LJSON = require('liquid-json').async; | ||
LJSON.parse('{ "hello": "world" }', function (err, obj) { | ||
console.log(obj); // logs the object | ||
}); | ||
LJSON.stringify({ hello: 'world' }, function (err, text) { | ||
console.log(text); // logs '{"hello":"world"}' | ||
}); | ||
``` | ||
## attributions | ||
@@ -22,0 +36,0 @@ |
@@ -1,6 +0,4 @@ | ||
var path = require('path'), | ||
var expect = require('chai').expect, | ||
bomb = require('../../lib/bomb'), | ||
expect = require('expect.js'), | ||
bomb = require(path.join(__dirname, '..', '..', 'lib', 'bomb')), | ||
TEST_STRING = 'string', | ||
@@ -22,7 +20,7 @@ | ||
it('returns an unchanged value for undefined / no input', function () { | ||
expect(bomb.trim()).to.be(undefined); | ||
expect(bomb.trim()).to.equal(undefined); | ||
}); | ||
it('returns and unchanged value for non string input', function () { | ||
expect(bomb.trim(testInput.number)).to.be(testInput.number); | ||
expect(bomb.trim(testInput.number)).to.equal(testInput.number); | ||
}); | ||
@@ -33,3 +31,3 @@ }); | ||
it('returns an unchanged value for regular string input', function () { | ||
expect(bomb.trim(TEST_STRING)).to.be(TEST_STRING); | ||
expect(bomb.trim(TEST_STRING)).to.equal(TEST_STRING); | ||
}); | ||
@@ -40,19 +38,19 @@ | ||
it.skip('correctly removes UTF-16 BOM', function () { // @todo: unskip after a utf16 BOM has been found | ||
expect(bomb.trim(testInput.utf16)).to.be(TEST_STRING); | ||
expect(bomb.trim(testInput.utf16)).to.equal(TEST_STRING); | ||
}); | ||
it('correctly removes UTF-32 BOM', function () { | ||
expect(bomb.trim(testInput.utf32)).to.be(TEST_STRING); | ||
expect(bomb.trim(testInput.utf32)).to.equal(TEST_STRING); | ||
}); | ||
it('correctly removes big endian UTF-16 BOM', function () { | ||
expect(bomb.trim(testInput.utf16BigEndian)).to.be(TEST_STRING); | ||
expect(bomb.trim(testInput.utf16BigEndian)).to.equal(TEST_STRING); | ||
}); | ||
it('correctly removes little endian UTF-16 BOM', function () { | ||
expect(bomb.trim(testInput.utf16LittleEndian)).to.be(TEST_STRING); | ||
expect(bomb.trim(testInput.utf16LittleEndian)).to.equal(TEST_STRING); | ||
}); | ||
it('correctly removes UTF-8 BOM', function () { | ||
expect(bomb.trim(testInput.utf8)).to.be(TEST_STRING); | ||
expect(bomb.trim(testInput.utf8)).to.equal(TEST_STRING); | ||
}); | ||
@@ -59,0 +57,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
99293
27
1559
38
25
4