diff --git a/.gitignore b/.gitignore index 3c3629e..e9a53a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +test/fixture/actual-json/temp_json_file.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index e46b8ff..a20bcaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,4 +11,4 @@ before_script: script: - npm test - - ./node_modules/.bin/eslint ./lib + - npm run lint diff --git a/README.md b/README.md index 9a7e7b8..313c32a 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Verify if the code style is fine: ./node_modules/.bin/jsoncs my/file.json -Fix the code style of a file: +Fix the code style of a file or multiple files: - ./node_modules/.bin/jsoncs --fix my/file.json + ./node_modules/.bin/jsoncs --fix my/directory/ ### Options @@ -25,6 +25,7 @@ Fix the code style of a file: Options: -f, --fix Fix the file + -q, --quiet Run in quiet mode -v, --version print version and exit ### Example @@ -36,5 +37,4 @@ Fix the code style of a file: ## TO-DO -* Make it accept multiple files * Leave the code style to the user in a config file diff --git a/lib/cli.js b/lib/cli.js index 4f9648a..822ae87 100755 --- a/lib/cli.js +++ b/lib/cli.js @@ -5,12 +5,13 @@ const path = require("path"); const formatter = require("./formatter.js").formatter; const commander = require("commander"); const packageVersion = require("../package").version; -const jsdiff = require("diff"); +const { getFiles, fixJsonFile, showDiff } = require("./modules.js"); const program = new commander.Command(); let jsonFile = ""; -let hasErrors = false; +let errors = []; +let fixedFiles = []; program. version(packageVersion, @@ -18,6 +19,8 @@ program. "json code style version") .option("-f, --fix", "fix json file") + .option("-q, --quiet", + "quiet mode") .arguments("[json]") .action(function (json) { jsonFile = json; @@ -25,40 +28,29 @@ program. program.parse(process.argv); -function parse(filePath) { - let source = fs.readFileSync(filePath, "utf8"); - - let formatted = formatter.formatJson(source); - let diff = jsdiff.diffJson(source, formatted); +function parse(path) { + getFiles(path).map(processFile); - showDiff(diff); - fixJson(filePath, formatted); - - if (hasErrors) { + if (errors.includes(true)) { process.exit(1); } - + + !program.fix || console.log(fixedFiles); process.exit(0); } -function fixJson(filePath, formatted) { - if (!program.fix) { - return; - } +function processFile(filePath) { + let source = fs.readFileSync(filePath, "utf8"); + let formatted = formatter.formatJson(source); + let fileWithErrors = showDiff(program.quiet, source, formatted, filePath); - fs.writeFileSync(filePath, formatted); - console.log(filePath + " - has been fixed"); - hasErrors = false; -} + errors.push(fileWithErrors); -function showDiff(diff) { - diff.forEach((part) => { - let color = part.added ? "\x1b[34m" : part.removed ? "\x1b[31m" : "\x1b[37m"; - if (part.added || part.removed) { - console.log(color, part.value); - hasErrors = true; - } - }); + if (program.fix) { + let fixedFile = fixJsonFile(filePath, formatted); + fixedFiles.push(fixedFile); + errors = []; + } } function main(jsonFilePath) { diff --git a/lib/modules.js b/lib/modules.js new file mode 100644 index 0000000..0a29228 --- /dev/null +++ b/lib/modules.js @@ -0,0 +1,50 @@ +const fs = require("fs"); +const jsdiff = require("diff"); + +const blue = "\x1b[34m"; +const red = "\x1b[31m"; +const withe = "\x1b[37m"; + +module.exports = { + getFiles: (path) => { + if (fs.lstatSync(path).isDirectory()) { + return readDirectory(path); + } + + return [path]; + }, + fixJsonFile: (filePath, formatted) => { + fs.writeFileSync(filePath, formatted); + + return filePath + " - has been fixed"; + }, + showDiff: (quiet, source, formatted, filePath) => { + let fileWithErrors = false; + let diff = jsdiff.diffJson(source, formatted); + + diff.forEach((part) => { + let color = part.added ? blue : part.removed ? red : withe; + + if (part.added || part.removed) { + quiet || console.log(color, part.value); + fileWithErrors = true; + } + }); + + !fileWithErrors || console.log(withe, " ============== "); + !fileWithErrors || console.log(withe, filePath, "\n"); + + return fileWithErrors; + } +}; + +function readDirectory(directoryPath) { + let files = fs.readdirSync(directoryPath); + let filesPath = []; + + files.forEach((file) => { + filesPath.push(directoryPath + file); + }); + + return filesPath; +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 54e4c4f..766ca4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,12 +54,6 @@ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, - "ansi-font": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ansi-font/-/ansi-font-0.0.2.tgz", - "integrity": "sha1-iQMBvVhBRi/TnAt3Ca/R9SUUMzE=", - "dev": true - }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -200,12 +194,33 @@ "ms": "^2.1.1" } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, "diff": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", @@ -226,6 +241,31 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "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", @@ -413,12 +453,27 @@ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "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", @@ -454,12 +509,27 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "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-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -528,6 +598,18 @@ "through": "^2.3.6" } }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -555,6 +637,24 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -659,6 +759,18 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "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 + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -718,6 +830,12 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -742,6 +860,15 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -758,6 +885,15 @@ "signal-exit": "^3.0.2" } }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -856,6 +992,17 @@ } } }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -913,13 +1060,33 @@ } } }, - "test": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/test/-/test-0.6.0.tgz", - "integrity": "sha1-WYasRF7Bd1QyJRLRBLoyyKY+k44=", + "tape": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", + "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", "dev": true, "requires": { - "ansi-font": "0.0.2" + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.4", + "has": "~1.0.3", + "inherits": "~2.0.4", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.11.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } } }, "text-table": { diff --git a/package.json b/package.json index ab07287..ef4a722 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,11 @@ }, "devDependencies": { "eslint": "^6.2.1", - "test": "*" + "tape": "^4.11.0" }, "scripts": { - "test": "node test/all-tests.js" + "test": "./node_modules/.bin/tape test/*.js", + "lint": "./node_modules/.bin/eslint ./test ./lib" }, "homepage": "https://github.com/codelicia/jsoncs#readme", "directories": { diff --git a/test/all-tests.js b/test/all-tests.js deleted file mode 100644 index 4da3d98..0000000 --- a/test/all-tests.js +++ /dev/null @@ -1,19 +0,0 @@ -const fs = require("fs"); -const assert = require("assert"); -const formatter = require("../lib/formatter.js").formatter; - -exports["test pass-1"] = function () { - let actualJson = fs.readFileSync(__dirname + "/actual-json/1.json").toString(); - let expectedJson = fs.readFileSync(__dirname + "/expected-json/1.json").toString(); - assert.equal(formatter.formatJson(actualJson), expectedJson); -} - -exports["test pass-2"] = function () { - let actualJson = fs.readFileSync(__dirname + "/actual-json/2.json").toString(); - let expectedJson = fs.readFileSync(__dirname + "/expected-json/2.json").toString(); - assert.equal(formatter.formatJson(actualJson), expectedJson); -} - -if (require.main === module) { - require("test").run(exports); -} diff --git a/test/actual-json/1.json b/test/fixture/actual-json/1.json similarity index 100% rename from test/actual-json/1.json rename to test/fixture/actual-json/1.json diff --git a/test/actual-json/2.json b/test/fixture/actual-json/2.json similarity index 100% rename from test/actual-json/2.json rename to test/fixture/actual-json/2.json diff --git a/test/expected-json/1.json b/test/fixture/expected-json/1.json similarity index 100% rename from test/expected-json/1.json rename to test/fixture/expected-json/1.json diff --git a/test/expected-json/2.json b/test/fixture/expected-json/2.json similarity index 100% rename from test/expected-json/2.json rename to test/fixture/expected-json/2.json diff --git a/test/formatterTest.js b/test/formatterTest.js new file mode 100644 index 0000000..74831ac --- /dev/null +++ b/test/formatterTest.js @@ -0,0 +1,17 @@ +const test = require("tape"); +const fs = require("fs"); +const formatter = require("../lib/formatter.js").formatter; + +test("format a simple json file", (assert) => { + let actualJson = fs.readFileSync(__dirname + "/fixture/actual-json/1.json").toString(); + let expectedJson = fs.readFileSync(__dirname + "/fixture/expected-json/1.json").toString(); + assert.equal(formatter.formatJson(actualJson), expectedJson); + assert.end(); +}); + +test("format a complex json file", (assert) => { + let actualJson = fs.readFileSync(__dirname + "/fixture/actual-json/2.json").toString(); + let expectedJson = fs.readFileSync(__dirname + "/fixture/expected-json/2.json").toString(); + assert.equal(formatter.formatJson(actualJson), expectedJson); + assert.end(); +}); diff --git a/test/modulesTest.js b/test/modulesTest.js new file mode 100644 index 0000000..0d1fe6b --- /dev/null +++ b/test/modulesTest.js @@ -0,0 +1,55 @@ +const test = require("tape"); +const fs = require("fs"); +const { fixJsonFile, getFiles, showDiff } = require("../lib/modules.js"); + +test("test write formatted json on the file", (assert) => { + let path = __dirname + "/fixture/actual-json/temp_json_file.json"; + let result = fixJsonFile(path, "{a}"); + let file = fs.readFileSync(path).toString(); + + assert.equal(path + " - has been fixed", result); + assert.equal("{a}", file); + assert.end(); +}); + +test("test get file path", (assert) => { + let path = __dirname + "/fixture/actual-json/temp_json_file.json"; + fs.writeFileSync(path, ""); + let result = getFiles(path); + + assert.equal(result.length, 1); + assert.equal(result[0], path); + assert.end(); +}); + +test("test get directory path", (assert) => { + let path = __dirname + "/fixture/expected-json/"; + let result = getFiles(path); + + assert.equal(result.length, 2); + assert.end(); +}); + +test("test show diff between two different json objects", (assert) => { + let json1 = {foo:"bar"}; + let json2 = {ble:"bar"}; + let path = __dirname + "/fixture/expected-json/any.json"; + let quiet = false; + + let result = showDiff(quiet, json1, json2, path); + + assert.true(result); + assert.end(); +}); + +test("test show diff between two equal json objects", (assert) => { + let json1 = {foo:"bar"}; + let json2 = {foo:"bar"}; + let path = __dirname + "/fixture/expected-json/any.json"; + let quiet = false; + + let result = showDiff(quiet, json1, json2, path); + + assert.false(result); + assert.end(); +});