Skip to content

Commit

Permalink
Add top-level-interop rule.
Browse files Browse the repository at this point in the history
Partial fix for eslint#68.
  • Loading branch information
hildjj committed Dec 3, 2024
1 parent a0374aa commit f6345c8
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export default [
- `no-empty-keys` - warns when there is a key in an object that is an empty string or contains only whitespace (note: `package-lock.json` uses empty keys intentionally)
- `no-unsafe-values` - warns on values that are unsafe for interchange, such as numbers outside safe range or lone surrogates.
- `no-unnormalized-keys` - warns on keys containing [unnormalized characters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize#description). You can optionally specify the normalization form via `{ form: "form_name" }`, where `form_name` can be any of `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`.
- `top-level-interop` - warns when the top-level item in the document is neither an array nor an object. This can be enabled to ensure maximal interoperability with the oldest JSON parsers.

## Configuration Comments

Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import noDuplicateKeys from "./rules/no-duplicate-keys.js";
import noEmptyKeys from "./rules/no-empty-keys.js";
import noUnsafeValues from "./rules/no-unsafe-values.js";
import noUnnormalizedKeys from "./rules/no-unnormalized-keys.js";
import topLevelinterop from "./rules/top-level-interop.js";

//-----------------------------------------------------------------------------
// Plugin
Expand All @@ -33,6 +34,7 @@ const plugin = {
"no-empty-keys": noEmptyKeys,
"no-unsafe-values": noUnsafeValues,
"no-unnormalized-keys": noUnnormalizedKeys,
"top-level-interop": topLevelinterop,
},
configs: {
recommended: {
Expand All @@ -42,6 +44,7 @@ const plugin = {
"json/no-empty-keys": "error",
"json/no-unsafe-values": "error",
"json/no-unnormalized-keys": "error",
"json/top-level-interop": "off",
}),
},
},
Expand Down
35 changes: 35 additions & 0 deletions src/rules/top-level-interop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @fileoverview Rule to ensure top-level items are either an array or ojbect.
* @author Joe Hildebrand
*/

export default {
meta: {
type: /** @type {const} */ ("problem"),

docs: {
description:
"Disallow JSON top-level items are not an array or object",
},

messages: {
topLevel:
'Top level item should be array or object, got "{{type}}".',
},
},

create(context) {
return {
Document(node) {
const { type } = node.body;
if (type !== "Object" && type !== "Array") {
context.report({
loc: node.loc,
messageId: "topLevel",
data: { type },
});
}
},
};
},
};
108 changes: 108 additions & 0 deletions tests/rules/top-level-interop.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @fileoverview Tests for top-level-interop rule.
* @author Joe Hildebrand
*/

//------------------------------------------------------------------------------
// Imports
//------------------------------------------------------------------------------

import rule from "../../src/rules/top-level-interop.js";
import json from "../../src/index.js";
import { RuleTester } from "eslint";

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester({
plugins: {
json,
},
language: "json/json",
});

ruleTester.run("top-level-interop", rule, {
valid: [
"[]",
{
code: "[1]",
language: "json/json5",
},
{
code: "[1, 2]",
language: "json/json5",
},
"{}",
{
code: '{"foo": 1}',
language: "json/json5",
},
{
code: '{"foo": 1, "foo": 2}',
language: "json/json5",
},
],
invalid: [
{
code: "1",
errors: [
{
messageId: "topLevel",
data: {
type: "Number",
},
line: 1,
column: 1,
endLine: 1,
endColumn: 2,
},
],
},
{
code: "true",
errors: [
{
messageId: "topLevel",
data: {
type: "Boolean",
},
line: 1,
column: 1,
endLine: 1,
endColumn: 5,
},
],
},
{
code: "null",
errors: [
{
messageId: "topLevel",
data: {
type: "Null",
},
line: 1,
column: 1,
endLine: 1,
endColumn: 5,
},
],
},
{
code: '"foo"',
errors: [
{
messageId: "topLevel",
data: {
type: "String",
},
line: 1,
column: 1,
endLine: 1,
endColumn: 6,
},
],
},
],
});

0 comments on commit f6345c8

Please sign in to comment.