Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: eslint/json
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 77bd94574f2134a13d355ff7447f6c3987264148
Choose a base ref
...
head repository: eslint/json
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: d613ddec3c7fd608ad6f258d455c6e692f5c9bbf
Choose a head ref
  • 15 commits
  • 21 files changed
  • 6 contributors

Commits on Jan 24, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Jan 24, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    nicolo-ribaudo Nicolò Ribaudo
    Copy the full SHA
    c1049f1 View commit details

Commits on Feb 6, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 6, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    nicolo-ribaudo Nicolò Ribaudo
    Copy the full SHA
    2faf9d3 View commit details
  2. fix: Use updated types from @eslint/core (#66)

    * chore: Update types based on @eslint/core
    
    * feat: Update to new types
    
    * fix: Update types from @eslint/core
    
    * Update types
    
    * Add types.ts to JSR definition
    
    * Clean up no-unsafe-values.js
    
    * Fix tests
    
    * Update tools/dedupe-types.js
    
    Co-authored-by: Francesco Trotta <github@fasttime.org>
    
    * Update src/rules/no-duplicate-keys.js
    
    Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
    
    * clean up
    
    * Fix CJS type definitions
    
    * Fix build step
    
    ---------
    
    Co-authored-by: Francesco Trotta <github@fasttime.org>
    Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
    3 people authored Feb 6, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    nicolo-ribaudo Nicolò Ribaudo
    Copy the full SHA
    460e7c7 View commit details

Commits on Feb 8, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 8, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    nicolo-ribaudo Nicolò Ribaudo
    Copy the full SHA
    96c9b53 View commit details

Commits on Feb 12, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 12, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    26e41da View commit details

Commits on Feb 14, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 14, 2025
    Copy the full SHA
    396e15b View commit details

Commits on Feb 17, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 17, 2025
    Copy the full SHA
    9f39cd9 View commit details

Commits on Feb 21, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Feb 21, 2025
    Copy the full SHA
    6e76cff View commit details

Commits on Feb 22, 2025

  1. chore: Update dependencies (#81)

    nzakas authored Feb 22, 2025
    Copy the full SHA
    e16bf4a View commit details

Commits on Mar 1, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Mar 1, 2025
    Copy the full SHA
    e250cc7 View commit details

Commits on Mar 3, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Mar 3, 2025
    Copy the full SHA
    96e912f View commit details

Commits on Mar 7, 2025

  1. docs: Update README sponsors

    GitHub Actions Bot committed Mar 7, 2025
    Copy the full SHA
    c4f4abb View commit details

Commits on Mar 10, 2025

  1. feat: Add types to exports (#84)

    * Add `types` to exports
    
    * Make requested changes
    mrmckeb authored Mar 10, 2025
    Copy the full SHA
    d9eab9e View commit details

Commits on Mar 14, 2025

  1. fix: Update types and apply to all rules (#86)

    * fix: Update types and apply to all rules
    
    * Remove momoa
    
    * Fix rule types
    nzakas authored Mar 14, 2025
    Copy the full SHA
    10882ff View commit details
  2. chore: release 0.11.0 🚀 (#80)

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    github-actions[bot] authored Mar 14, 2025
    Copy the full SHA
    d613dde View commit details
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.10.0"
".": "0.11.0"
}
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [0.11.0](https://github.com/eslint/json/compare/json-v0.10.0...json-v0.11.0) (2025-03-14)


### Features

* Add `types` to exports ([#84](https://github.com/eslint/json/issues/84)) ([d9eab9e](https://github.com/eslint/json/commit/d9eab9ec3a733b561f55235eb71a611c7d84ebbb))


### Bug Fixes

* Update types and apply to all rules ([#86](https://github.com/eslint/json/issues/86)) ([10882ff](https://github.com/eslint/json/commit/10882ffe9c39cdd866be51801f9950f4a010cd87))
* Use updated types from @eslint/core ([#66](https://github.com/eslint/json/issues/66)) ([460e7c7](https://github.com/eslint/json/commit/460e7c707ed30fc41df280e40f300bafd5a3cae2))

## [0.10.0](https://github.com/eslint/json/compare/json-v0.9.1...json-v0.10.0) (2025-01-19)


6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -256,9 +256,9 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

<h3>Platinum Sponsors</h3>
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
<p><a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.serptriumph.com/"><img src="https://images.opencollective.com/serp-triumph5/fea3074/logo.png" alt="SERP Triumph" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nolebase.ayaka.io"><img src="https://avatars.githubusercontent.com/u/11081491" alt="Neko" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a></p>
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a> <a href="https://shopify.engineering/"><img src="https://avatars.githubusercontent.com/u/8085" alt="Shopify" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nolebase.ayaka.io"><img src="https://avatars.githubusercontent.com/u/11081491" alt="Neko" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
<h3>Technology Sponsors</h3>
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
3 changes: 2 additions & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "@eslint/json",
"version": "0.10.0",
"version": "0.11.0",
"exports": "./dist/esm/index.js",
"publish": {
"include": [
"dist/esm/index.js",
"dist/esm/index.d.ts",
"dist/esm/types.ts",
"README.md",
"jsr.json",
"LICENSE"
31 changes: 20 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
{
"name": "@eslint/json",
"version": "0.10.0",
"version": "0.11.0",
"description": "JSON linting plugin for ESLint",
"author": "Nicholas C. Zakas",
"type": "module",
"main": "dist/esm/index.js",
"types": "dist/esm/index.d.ts",
"exports": {
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
".": {
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
},
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
}
},
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
"./types": {
"require": {
"types": "./dist/cjs/types.cts"
},
"import": {
"types": "./dist/esm/types.d.ts"
}
}
},
"files": [
@@ -42,7 +52,7 @@
"homepage": "https://github.com/eslint/json#readme",
"scripts": {
"build:dedupe-types": "node tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js",
"build:cts": "node -e \"fs.copyFileSync('dist/esm/index.d.ts', 'dist/cjs/index.d.cts')\"",
"build:cts": "node tools/build-cts.js",
"build": "rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts",
"build:readme": "node tools/update-readme.js",
"test:jsr": "npx jsr@latest publish --dry-run",
@@ -63,13 +73,12 @@
],
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.10.0",
"@eslint/plugin-kit": "^0.2.5",
"@eslint/core": "^0.12.0",
"@eslint/plugin-kit": "^0.2.7",
"@humanwhocodes/momoa": "^3.3.4",
"natural-compare": "^1.4.0"
},
"devDependencies": {
"@types/eslint": "^8.56.10",
"c8": "^9.1.0",
"dedent": "^1.5.3",
"eslint": "^9.11.1",
10 changes: 10 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import copy from "rollup-plugin-copy";

export default {
input: "src/index.js",
output: [
@@ -11,4 +13,12 @@ export default {
banner: '// @ts-self-types="./index.d.ts"',
},
],
plugins: [
copy({
targets: [
{ src: "src/types.ts", dest: "dist/cjs", rename: "types.cts" },
{ src: "src/types.ts", dest: "dist/esm" },
],
}),
],
};
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ import topLevelInterop from "./rules/top-level-interop.js";
const plugin = {
meta: {
name: "@eslint/json",
version: "0.10.0", // x-release-please-version
version: "0.11.0", // x-release-please-version
},
languages: {
json: new JSONLanguage({ mode: "json" }),
8 changes: 3 additions & 5 deletions src/languages/json-language.js
Original file line number Diff line number Diff line change
@@ -21,18 +21,16 @@ import { visitorKeys } from "@humanwhocodes/momoa";
/** @typedef {import("@eslint/core").OkParseResult<DocumentNode>} OkParseResult */
/** @typedef {import("@eslint/core").ParseResult<DocumentNode>} ParseResult */
/** @typedef {import("@eslint/core").File} File */
/**
* @typedef {Object} JSONLanguageOptions
* @property {boolean} [allowTrailingCommas] Whether to allow trailing commas.
*/
/** @typedef {import("../types.ts").IJSONLanguage} IJSONLanguage */
/** @typedef {import("../types.ts").JSONLanguageOptions} JSONLanguageOptions */

//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------

/**
* JSON Language Object
* @implements {Language}
* @implements {IJSONLanguage}
*/
export class JSONLanguage {
/**
6 changes: 4 additions & 2 deletions src/languages/json-source-code.js
Original file line number Diff line number Diff line change
@@ -26,11 +26,12 @@ import {
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
/** @typedef {import("@eslint/core").File} File */
/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
/** @typedef {import("@eslint/core").TextSourceCode} TextSourceCode */
/** @typedef {import("@eslint/core").VisitTraversalStep} VisitTraversalStep */
/** @typedef {import("@eslint/core").FileProblem} FileProblem */
/** @typedef {import("@eslint/core").DirectiveType} DirectiveType */
/** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
/** @typedef {import("../types.ts").IJSONSourceCode} IJSONSourceCode */
/** @typedef {import("../types.ts").JSONSyntaxElement} JSONSyntaxElement */

//-----------------------------------------------------------------------------
// Helpers
@@ -71,6 +72,7 @@ class JSONTraversalStep extends VisitNodeStep {

/**
* JSON Source Code Object
* @implements {IJSONSourceCode}
*/
export class JSONSourceCode extends TextSourceCodeBase {
/**
@@ -147,7 +149,7 @@ export class JSONSourceCode extends TextSourceCodeBase {
);
}

return this.#inlineConfigComments;
return this.#inlineConfigComments ?? [];
}

/**
18 changes: 16 additions & 2 deletions src/rules/no-duplicate-keys.js
Original file line number Diff line number Diff line change
@@ -3,13 +3,22 @@
* @author Nicholas C. Zakas
*/

//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {"duplicateKey"} NoDuplicateKeysMessageIds */
/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoDuplicateKeysMessageIds>} NoDuplicateKeysRuleDefinition */
/** @typedef {import("@humanwhocodes/momoa").MemberNode} MemberNode */

//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------

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

docs: {
description: "Disallow duplicate keys in JSON objects",
@@ -21,7 +30,10 @@ export default {
},

create(context) {
/** @type {Array<Map<string, MemberNode>|undefined>} */
const objectKeys = [];

/** @type {Map<string, MemberNode>|undefined} */
let keys;

return {
@@ -54,3 +66,5 @@ export default {
};
},
};

export default rule;
18 changes: 16 additions & 2 deletions src/rules/no-empty-keys.js
Original file line number Diff line number Diff line change
@@ -3,9 +3,21 @@
* @author Nicholas C. Zakas
*/

export default {
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {"emptyKey"} NoEmptyKeysMessageIds */
/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoEmptyKeysMessageIds>} NoEmptyKeysRuleDefinition */

//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------

/** @type {NoEmptyKeysRuleDefinition} */
const rule = {
meta: {
type: /** @type {const} */ ("problem"),
type: "problem",

docs: {
description: "Disallow empty keys in JSON objects",
@@ -34,3 +46,5 @@ export default {
};
},
};

export default rule;
27 changes: 21 additions & 6 deletions src/rules/no-unnormalized-keys.js
Original file line number Diff line number Diff line change
@@ -3,9 +3,21 @@
* @author Bradley Meck Farias
*/

export default {
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds */
/** @typedef {import("../types.ts").JSONRuleDefinition<[{form:string}], NoUnnormalizedKeysMessageIds>} NoUnnormalizedKeysRuleDefinition */

//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------

/** @type {NoUnnormalizedKeysRuleDefinition} */
const rule = {
meta: {
type: /** @type {const} */ ("problem"),
type: "problem",

docs: {
description: "Disallow JSON keys that are not normalized",
@@ -29,17 +41,18 @@ export default {
},

create(context) {
const normalization = context.options.length
? text => text.normalize(context.options[0].form)
: text => text.normalize();
const form = context.options.length
? context.options[0].form
: undefined;

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

if (normalization(key) !== key) {
if (key.normalize(form) !== key) {
context.report({
loc: node.name.loc,
messageId: "unnormalizedKey",
@@ -52,3 +65,5 @@ export default {
};
},
};

export default rule;
35 changes: 30 additions & 5 deletions src/rules/no-unsafe-values.js
Original file line number Diff line number Diff line change
@@ -3,15 +3,36 @@
* @author Bradley Meck Farias
*/

// RFC 8259's `number` production, as a regex. Capture the integer part
// and the fractional part.
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds */
/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoUnsafeValuesMessageIds>} NoUnsafeValuesRuleDefinition */

//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------

/*
* This rule is based on the JSON grammar from RFC 8259, section 6.
* https://tools.ietf.org/html/rfc8259#section-6
*
* We separately capture the integer and fractional parts of a number, so that
* we can check for unsafe numbers that will evaluate to Infinity.
*/
const NUMBER =
/^-?(?<int>0|([1-9][0-9]*))(?:\.(?<frac>[0-9]+))?(?:[eE][+-]?[0-9]+)?$/u;
const NON_ZERO = /[1-9]/u;

export default {
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------

/** @type {NoUnsafeValuesRuleDefinition} */
const rule = {
meta: {
type: /** @type {const} */ ("problem"),
type: "problem",

docs: {
description: "Disallow JSON values that are unsafe for interchange",
@@ -85,7 +106,9 @@ export default {
loc: node.loc,
messageId: "subnormal",
// Value included so that it's seen in scientific notation
data: node,
data: {
value,
},
});
}
}
@@ -122,3 +145,5 @@ export default {
};
},
};

export default rule;
Loading