Skip to content

Commit

Permalink
feat: Add JSON5 support (#15)
Browse files Browse the repository at this point in the history
* feat: Add JSON5 support

* Fix no-empty-keys for JSON5
  • Loading branch information
nzakas committed Jul 25, 2024
1 parent bc43984 commit ea8dbb5
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 12 deletions.
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ deno add @eslint/json

## Usage

This package exports two different languages:
This package exports these languages:

- `"json/json"` is for regular JSON files
- `"json/jsonc"` is for JSON files that support comments (JSON-C) such as those used for Visual Studio Code configuration files
- `"json/jsonc"` is for JSON files that support comments ([JSONC](https://github.com/microsoft/node-jsonc-parser)) such as those used for Visual Studio Code configuration files
- `"json/json5"` is for [JSON5](https://json5.org) files

Depending on which types of JSON files you'd like to lint, you can set up your `eslint.config.js` file to include just the files you'd like. Here's an example that lints both JSON and JSON-C files:
Depending on which types of JSON files you'd like to lint, you can set up your `eslint.config.js` file to include just the files you'd like. Here's an example that lints JSON, JSONC, and JSON5 files:

```js
import json from "@eslint/json";
Expand All @@ -54,14 +55,23 @@ export default [
},
},

// lint JSON-C files
// lint JSONC files
{
files: ["**/*.jsonc", ".vscode/*.json"],
language: "json/jsonc",
rules: {
"json/no-duplicate-keys": "error",
},
},

// lint JSON5 files
{
files: ["**/*.json5"],
language: "json/json5",
rules: {
"json/no-duplicate-keys": "error",
},
},
];
```

Expand All @@ -81,12 +91,19 @@ export default [
...json.configs.recommended,
},

// lint JSON-C files
// lint JSONC files
{
files: ["**/*.jsonc"],
language: "json/jsonc",
...json.configs.recommended,
},

// lint JSON5 files
{
files: ["**/*.json5"],
language: "json/json5",
...json.configs.recommended,
},
];
```

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
],
"license": "Apache-2.0",
"dependencies": {
"@humanwhocodes/momoa": "^3.1.1"
"@humanwhocodes/momoa": "^3.2.0"
},
"devDependencies": {
"@eslint/core": "^0.3.0",
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const plugin = {
languages: {
json: new JSONLanguage({ mode: "json" }),
jsonc: new JSONLanguage({ mode: "jsonc" }),
json5: new JSONLanguage({ mode: "json5" }),
},
rules: {
"no-duplicate-keys": noDuplicateKeys,
Expand Down
4 changes: 2 additions & 2 deletions src/languages/json-language.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class JSONLanguage {

/**
* The parser mode.
* @type {"json"|"jsonc"}
* @type {"json"|"jsonc"|"json5"}
*/
#mode = "json";

Expand All @@ -70,7 +70,7 @@ export class JSONLanguage {
/**
* Creates a new instance.
* @param {Object} options The options to use for this instance.
* @param {"json"|"jsonc"} options.mode The parser mode to use.
* @param {"json"|"jsonc"|"json5"} options.mode The parser mode to use.
*/
constructor({ mode }) {
this.#mode = mode;
Expand Down
7 changes: 5 additions & 2 deletions src/rules/no-duplicate-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

//-----------------------------------------------------------------------------
// Type Definitions
// Rule Definition
//-----------------------------------------------------------------------------

export default {
Expand All @@ -31,7 +31,10 @@ export default {
},

Member(node) {
const key = node.name.value;
const key =
node.name.type === "String"
? node.name.value
: node.name.name;

if (keys.has(key)) {
context.report({
Expand Down
5 changes: 4 additions & 1 deletion src/rules/no-empty-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ export default {
create(context) {
return {
Member(node) {
const key = node.name.value;
const key =
node.name.type === "String"
? node.name.value
: node.name.name;

if (key.trim() === "") {
context.report({
Expand Down
66 changes: 66 additions & 0 deletions tests/rules/no-duplicate-keys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ ruleTester.run("no-duplicate-keys", rule, {
"{}",
'{"foo": 1, "bar": {"bar": 2}}',
'{"foo": { "bar": 5 }, "bar": 6 }',
{
code: "{foo: 1, bar: {bar: 2}}",
language: "json/json5",
},
],
invalid: [
{
Expand Down Expand Up @@ -61,5 +65,67 @@ ruleTester.run("no-duplicate-keys", rule, {
},
],
},
{
code: "{foo: 1, foo: 2}",
language: "json/json5",
errors: [
{
messageId: "duplicateKey",
line: 1,
column: 10,
endLine: 1,
endColumn: 13,
},
],
},
{
code: `{
foo: {
"bar": 5
},
foo: 6
}`,
language: "json/json5",
errors: [
{
messageId: "duplicateKey",
line: 5,
column: 5,
endLine: 5,
endColumn: 8,
},
],
},
{
code: '{"foo": 1, foo: 2}',
language: "json/json5",
errors: [
{
messageId: "duplicateKey",
line: 1,
column: 12,
endLine: 1,
endColumn: 15,
},
],
},
{
code: `{
foo: {
"bar": 5
},
"foo": 6
}`,
language: "json/json5",
errors: [
{
messageId: "duplicateKey",
line: 5,
column: 5,
endLine: 5,
endColumn: 10,
},
],
},
],
});
38 changes: 37 additions & 1 deletion tests/rules/no-empty-keys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ const ruleTester = new RuleTester({
});

ruleTester.run("no-empty-keys", rule, {
valid: ['{"foo": 1, "bar": 2}'],
valid: [
'{"foo": 1, "bar": 2}',
{
code: '{"foo": 1, "bar": 2, "baz": 3}',
language: "json/json5",
},
{
code: '{foo: 1, bar: 2, "baz": 3}',
language: "json/json5",
},
],
invalid: [
{
code: '{"": 1}',
Expand All @@ -49,5 +59,31 @@ ruleTester.run("no-empty-keys", rule, {
},
],
},
{
code: "{'': 1}",
language: "json/json5",
errors: [
{
messageId: "emptyKey",
line: 1,
column: 2,
endLine: 1,
endColumn: 4,
},
],
},
{
code: "{' ': 1}",
language: "json/json5",
errors: [
{
messageId: "emptyKey",
line: 1,
column: 2,
endLine: 1,
endColumn: 6,
},
],
},
],
});

0 comments on commit ea8dbb5

Please sign in to comment.