diff --git a/.automation/test/jsonc/README.md b/.automation/test/jsonc/README.md new file mode 100644 index 00000000..27069412 --- /dev/null +++ b/.automation/test/jsonc/README.md @@ -0,0 +1,19 @@ +# Json Test Cases + +This folder holds the test cases for **Json**. + +## Additional Docs + +No Additional information is needed for this test case. + +## Good Test Cases + +The test cases denoted: `LANGUAGE_good_FILE.EXTENSION` are all valid, and should pass successfully when linted. + +- **Note:** They are linted utilizing the default linter rules. + +## Bad Test Cases + +The test cases denoted: `LANGUAGE_bad_FILE.EXTENSION` are **NOT** valid, and should trigger errors when linted. + +- **Note:** They are linted utilizing the default linter rules. diff --git a/.automation/test/jsonc/json_bad_1.jsonc b/.automation/test/jsonc/json_bad_1.jsonc new file mode 100644 index 00000000..f90d345e --- /dev/null +++ b/.automation/test/jsonc/json_bad_1.jsonc @@ -0,0 +1,11 @@ +{ + "arrow_spacing": { + "level": ["ignore"] + }, + // more test + "braces_spacing": { + "level": 'ignore', + "spaces": 0 + "empty_object_spaces": 0 + } +} diff --git a/.automation/test/jsonc/json_good_1.json5 b/.automation/test/jsonc/json_good_1.json5 new file mode 100644 index 00000000..b72f80bd --- /dev/null +++ b/.automation/test/jsonc/json_good_1.json5 @@ -0,0 +1,11 @@ +{ + "arrow_spacing": { + "level": "ignore" + }, + // tests... + "braces_spacing": { + "level": "ignore", + "spaces": 0, + "empty_object_spaces": 0 + } +} diff --git a/.github/linters/.eslintrc.yml b/.github/linters/.eslintrc.yml index d8d60ec1..2025cb8e 100644 --- a/.github/linters/.eslintrc.yml +++ b/.github/linters/.eslintrc.yml @@ -39,3 +39,35 @@ plugins: # Rules # ######### rules: {} + +############################## +# Overrides for JSON parsing # +############################## +overrides: + +# JSON files +- files: + - "*.json" + extends: + - plugin:jsonc/recommended-with-json + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSON + +# JSONC files +- files: + - "*.jsonc" + extends: + - plugin:jsonc/recommended-with-jsonc + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSONC + +# JSON5 files +- files: + - "*.json5" + extends: + - plugin:jsonc/recommended-with-json5 + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSON5 diff --git a/README.md b/README.md index 3bcaf047..df12aaf7 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | **Java** | [checkstyle](https://checkstyle.org) | | **JavaScript** | [eslint](https://eslint.org/) / [standard js](https://standardjs.com/) | | **JSON** | [jsonlint](https://github.com/zaach/jsonlint) | +| **JSONC** | [eslint-plugin-jsonc](https://www.npmjs.com/package/eslint-plugin-jsonc) | | **Kubeval** | [kubeval](https://github.com/instrumenta/kubeval) | | **Kotlin** | [ktlint](https://github.com/pinterest/ktlint) | | **LaTeX** | [ChkTex](https://www.nongnu.org/chktex/) | diff --git a/TEMPLATES/.eslintrc.yml b/TEMPLATES/.eslintrc.yml index d8d60ec1..2025cb8e 100644 --- a/TEMPLATES/.eslintrc.yml +++ b/TEMPLATES/.eslintrc.yml @@ -39,3 +39,35 @@ plugins: # Rules # ######### rules: {} + +############################## +# Overrides for JSON parsing # +############################## +overrides: + +# JSON files +- files: + - "*.json" + extends: + - plugin:jsonc/recommended-with-json + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSON + +# JSONC files +- files: + - "*.jsonc" + extends: + - plugin:jsonc/recommended-with-jsonc + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSONC + +# JSON5 files +- files: + - "*.json5" + extends: + - plugin:jsonc/recommended-with-json5 + parser: jsonc-eslint-parser + parserOptions: + jsonSyntax: JSON5 diff --git a/dependencies/package-lock.json b/dependencies/package-lock.json index 9ddcc8a8..698175cc 100644 --- a/dependencies/package-lock.json +++ b/dependencies/package-lock.json @@ -18,6 +18,7 @@ "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-jest": "^24.3.6", + "eslint-plugin-jsonc": "^1.2.1", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.4.0", "gherkin-lint": "^4.2.1", @@ -859,6 +860,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { + "graceful-fs": "^4.1.6", "universalify": "^2.0.0" }, "optionalDependencies": { @@ -2189,6 +2191,7 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", + "fsevents": "~2.1.2", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -2224,6 +2227,7 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz", "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", "dependencies": { + "colors": "^1.1.2", "object-assign": "^4.1.0", "string-width": "^4.2.0" }, @@ -3435,6 +3439,19 @@ } } }, + "node_modules/eslint-plugin-jsonc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-1.2.1.tgz", + "integrity": "sha512-m7o4gaNKojSwRJDNP0/7HK1vGfGgynX6DeTHTXhYGxWn2DB8E2RU5jeK95CYw1/mwej4ku2Xd9Tevn6WOlI6Dg==", + "dependencies": { + "eslint-utils": "^2.1.0", + "jsonc-eslint-parser": "^1.0.0", + "natural-compare": "^1.4.0" + }, + "peerDependencies": { + "eslint": "^5.0.0 || >=6.0.0" + } + }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", @@ -4849,9 +4866,9 @@ } }, "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", + "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", "dependencies": { "has": "^1.0.3" }, @@ -5064,6 +5081,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { + "graceful-fs": "^4.1.6", "universalify": "^2.0.0" }, "optionalDependencies": { @@ -5217,6 +5235,24 @@ "node": ">=6" } }, + "node_modules/jsonc-eslint-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-1.0.1.tgz", + "integrity": "sha512-mh5LY5byThmc692EqJS3Ss9sViNoNeCLNG5VQUgJLoAFFM3FzdIetd99qEiiQ+NXBVAIUgX5sWeK9leniS8RbQ==", + "dependencies": { + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^6.0.0 || ^7.2.0" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, "node_modules/jsonc-parser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", @@ -6054,6 +6090,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.", "dependencies": { "chalk": "~0.4.0", "underscore": "~1.6.0" @@ -9138,10 +9175,7 @@ "node_modules/xregexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "engines": { - "node": "*" - } + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" }, "node_modules/xtend": { "version": "4.0.2", @@ -10529,6 +10563,7 @@ } } }, + "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -12264,6 +12299,16 @@ "@typescript-eslint/experimental-utils": "^4.0.1" } }, + "eslint-plugin-jsonc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-1.2.1.tgz", + "integrity": "sha512-m7o4gaNKojSwRJDNP0/7HK1vGfGgynX6DeTHTXhYGxWn2DB8E2RU5jeK95CYw1/mwej4ku2Xd9Tevn6WOlI6Dg==", + "requires": { + "eslint-utils": "^2.1.0", + "jsonc-eslint-parser": "^1.0.0", + "natural-compare": "^1.4.0" + } + }, "eslint-plugin-jsx-a11y": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", @@ -13172,9 +13217,9 @@ "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", + "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", "requires": { "has": "^1.0.3" } @@ -13458,6 +13503,23 @@ "minimist": "^1.2.5" } }, + "jsonc-eslint-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-1.0.1.tgz", + "integrity": "sha512-mh5LY5byThmc692EqJS3Ss9sViNoNeCLNG5VQUgJLoAFFM3FzdIetd99qEiiQ+NXBVAIUgX5sWeK9leniS8RbQ==", + "requires": { + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^6.0.0 || ^7.2.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + } + } + }, "jsonc-parser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz", diff --git a/dependencies/package.json b/dependencies/package.json index a124405f..621526be 100644 --- a/dependencies/package.json +++ b/dependencies/package.json @@ -11,8 +11,9 @@ "dockerfilelint": "^1.8.0", "eslint": "^7.26.0", "eslint-config-airbnb": "^18.2.1", - "eslint-plugin-jest": "^24.3.6", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jest": "^24.3.6", + "eslint-plugin-jsonc": "^1.2.1", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.4.0", "gherkin-lint": "^4.2.1", diff --git a/lib/functions/buildFileList.sh b/lib/functions/buildFileList.sh index c3a65937..165cc263 100755 --- a/lib/functions/buildFileList.sh +++ b/lib/functions/buildFileList.sh @@ -416,6 +416,15 @@ function BuildFileList() { FILE_ARRAY_JAVASCRIPT_STANDARD+=("${FILE}") FILE_ARRAY_JAVASCRIPT_PRETTIER+=("${FILE}") + ####################### + # Get the JSONC files # + ####################### + elif [ "$FILE_TYPE" == "jsonc" ] || [ "$FILE_TYPE" == "json5" ]; then + ################################ + # Append the file to the array # + ################################ + FILE_ARRAY_JSONC+=("${FILE}") + ###################### # Get the JSON files # ###################### diff --git a/lib/linter.sh b/lib/linter.sh index 164934a7..6a0b0f14 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -186,7 +186,7 @@ fi ################## LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'BASH_EXEC' 'CLOUDFORMATION' 'CLOJURE' 'COFFEESCRIPT' 'CPP' 'CSHARP' 'CSS' 'DART' 'DOCKERFILE' 'DOCKERFILE_HADOLINT' 'EDITORCONFIG' 'ENV' 'GHERKIN' 'GO' 'GROOVY' 'HTML' - 'JAVA' 'JAVASCRIPT_ES' "${JAVASCRIPT_STYLE_NAME}" 'JSCPD' 'JSON' 'JSX' 'KUBERNETES_KUBEVAL' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' + 'JAVA' 'JAVASCRIPT_ES' "${JAVASCRIPT_STYLE_NAME}" 'JSCPD' 'JSON' 'JSONC' 'JSX' 'KUBERNETES_KUBEVAL' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' 'OPENAPI' 'PERL' 'PHP_BUILTIN' 'PHP_PHPCS' 'PHP_PHPSTAN' 'PHP_PSALM' 'POWERSHELL' 'PROTOBUF' 'PYTHON_BLACK' 'PYTHON_PYLINT' 'PYTHON_FLAKE8' 'PYTHON_ISORT' 'PYTHON_MYPY' 'R' 'RAKU' 'RUBY' 'RUST_2015' 'RUST_2018' 'RUST_CLIPPY' @@ -221,6 +221,7 @@ LINTER_NAMES_ARRAY['JAVASCRIPT_ES']="eslint" LINTER_NAMES_ARRAY["${JAVASCRIPT_STYLE_NAME}"]="${JAVASCRIPT_STYLE}" LINTER_NAMES_ARRAY['JSCPD']="jscpd" LINTER_NAMES_ARRAY['JSON']="jsonlint" +LINTER_NAMES_ARRAY['JSONC']="eslint" LINTER_NAMES_ARRAY['JSX']="eslint" LINTER_NAMES_ARRAY['KOTLIN']="ktlint" LINTER_NAMES_ARRAY['KUBERNETES_KUBEVAL']="kubeval" @@ -770,6 +771,7 @@ LINTER_COMMANDS_ARRAY['JAVASCRIPT_STANDARD']="standard ${JAVASCRIPT_STANDARD_LIN LINTER_COMMANDS_ARRAY['JAVASCRIPT_PRETTIER']="prettier --check" LINTER_COMMANDS_ARRAY['JSCPD']="jscpd --config ${JSCPD_LINTER_RULES}" LINTER_COMMANDS_ARRAY['JSON']="jsonlint" +LINTER_COMMANDS_ARRAY['JSONC']="eslint --no-eslintrc -c ${JAVASCRIPT_ES_LINTER_RULES} --ext .json5,.jsonc" LINTER_COMMANDS_ARRAY['JSX']="eslint --no-eslintrc -c ${JSX_LINTER_RULES}" LINTER_COMMANDS_ARRAY['KOTLIN']="ktlint" LINTER_COMMANDS_ARRAY['KUBERNETES_KUBEVAL']="kubeval --strict" diff --git a/test/inspec/super-linter/controls/super_linter.rb b/test/inspec/super-linter/controls/super_linter.rb index 127e13ba..dbd6dfab 100644 --- a/test/inspec/super-linter/controls/super_linter.rb +++ b/test/inspec/super-linter/controls/super_linter.rb @@ -276,6 +276,7 @@ control "super-linter-installed-npm-packages" do "eslint-config-airbnb", "eslint-config-prettier", "eslint-plugin-jest", + "eslint-plugin-jsonc", "eslint-plugin-jsx-a11y", "eslint-plugin-prettier", "gherkin-lint",