From cb3675db0aa778caf2d47254b9f5219080241d7d Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 22 Aug 2024 11:44:28 -0400 Subject: [PATCH 01/12] chore: Update types based on @eslint/core --- rollup.config.js | 7 ++++ src/rules/no-duplicate-keys.js | 8 +++++ src/rules/no-empty-keys.js | 12 +++++++ src/types.ts | 61 ++++++++++++++++++++++++++++++++++ tools/dedupe-types.js | 7 +++- tsconfig.json | 3 +- 6 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/types.ts diff --git a/rollup.config.js b/rollup.config.js index 0ec27fb..11c7417 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,3 +1,5 @@ +import copy from "rollup-plugin-copy"; + export default { input: "src/index.js", output: [ @@ -11,4 +13,9 @@ export default { banner: '// @ts-self-types="./index.d.ts"', }, ], + plugins: [ + copy({ + targets: [{ src: "src/types.ts", dest: "dist/esm" }], + }), + ], }; diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index 3499526..e511448 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -3,10 +3,18 @@ * @author Nicholas C. Zakas */ +//----------------------------------------------------------------------------- +// Type Definitions +//----------------------------------------------------------------------------- + +/** @typedef {import("../types.ts").JSONRuleVisitor} JSONRuleVisitor */ +/** @typedef {import("../../../rewrite/packages/core/src/types.ts").RuleDefinition} RuleDefinition */ + //----------------------------------------------------------------------------- // Rule Definition //----------------------------------------------------------------------------- +/** @type {RuleDefinition} */ export default { meta: { type: /** @type {const} */ ("problem"), diff --git a/src/rules/no-empty-keys.js b/src/rules/no-empty-keys.js index 3fedc4f..93e8a2d 100644 --- a/src/rules/no-empty-keys.js +++ b/src/rules/no-empty-keys.js @@ -3,6 +3,18 @@ * @author Nicholas C. Zakas */ +//----------------------------------------------------------------------------- +// Type Definitions +//----------------------------------------------------------------------------- + +/** @typedef {import("../types.ts").JSONRuleVisitor} JSONRuleVisitor */ +/** @typedef {import("../../../rewrite/packages/core/src/types.ts").RuleDefinition} RuleDefinition */ + +//----------------------------------------------------------------------------- +// Rule Definition +//----------------------------------------------------------------------------- + +/** @type {RuleDefinition} */ export default { meta: { type: /** @type {const} */ ("problem"), diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..b98ad1b --- /dev/null +++ b/src/types.ts @@ -0,0 +1,61 @@ +/** + * @fileoverview Additional types for this package. + * @author Nicholas C. Zakas + */ + +//------------------------------------------------------------------------------ +// Imports +//------------------------------------------------------------------------------ + +import { RuleVisitor } from "../../rewrite/packages/core/src/types.ts"; +import { + DocumentNode, + MemberNode, + ElementNode, + ObjectNode, + ArrayNode, + StringNode, + NullNode, + NumberNode, + BooleanNode, + NaNNode, + InfinityNode, + IdentifierNode, +} from "@humanwhocodes/momoa"; + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +type ValueNodeParent = DocumentNode | MemberNode | ElementNode; + +/** + * The visitor format returned from rules in this package. + */ +export interface JSONRuleVisitor extends RuleVisitor { + Document?(node: DocumentNode): void; + Member?(node: MemberNode, parent?: ObjectNode): void; + Element?(node: ElementNode, parent?: ArrayNode): void; + Object?(node: ObjectNode, parent?: ValueNodeParent): void; + Array?(node: ArrayNode, parent?: ValueNodeParent): void; + String?(node: StringNode, parent?: ValueNodeParent): void; + Null?(node: NullNode, parent?: ValueNodeParent): void; + Number?(node: NumberNode, parent?: ValueNodeParent): void; + Boolean?(node: BooleanNode, parent?: ValueNodeParent): void; + NaN?(node: NaNNode, parent?: ValueNodeParent): void; + Infinity?(node: InfinityNode, parent?: ValueNodeParent): void; + Identifier?(node: IdentifierNode, parent?: ValueNodeParent): void; + + "Document:exit"?(node: DocumentNode): void; + "Member:exit"?(node: MemberNode, parent?: ObjectNode): void; + "Element:exit"?(node: ElementNode, parent?: ArrayNode): void; + "Object:exit"?(node: ObjectNode, parent?: ValueNodeParent): void; + "Array:exit"?(node: ArrayNode, parent?: ValueNodeParent): void; + "String:exit"?(node: StringNode, parent?: ValueNodeParent): void; + "Null:exit"?(node: NullNode, parent?: ValueNodeParent): void; + "Number:exit"?(node: NumberNode, parent?: ValueNodeParent): void; + "Boolean:exit"?(node: BooleanNode, parent?: ValueNodeParent): void; + "NaN:exit"?(node: NaNNode, parent?: ValueNodeParent): void; + "Infinity:exit"?(node: InfinityNode, parent?: ValueNodeParent): void; + "Identifier:exit"?(node: IdentifierNode, parent?: ValueNodeParent): void; +} diff --git a/tools/dedupe-types.js b/tools/dedupe-types.js index ce8b16d..0378001 100644 --- a/tools/dedupe-types.js +++ b/tools/dedupe-types.js @@ -39,5 +39,10 @@ files.forEach(filePath => { return true; }); - fs.writeFileSync(filePath, remainingLines.join("\n"), "utf8"); + // replace references to ../types.ts with types.ts + const text = remainingLines + .join("\n") + .replace(/\.\.\/types\.ts/gu, "types.ts"); + + fs.writeFileSync(filePath, text, "utf8"); }); diff --git a/tsconfig.json b/tsconfig.json index 3fa504c..0a3d0a1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "outDir": "dist/esm", "target": "ES2022", "moduleResolution": "NodeNext", - "module": "NodeNext" + "module": "NodeNext", + "allowImportingTsExtensions": true } } From 2e03f9a2b490b422346f7cbaca90bce2b182989b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 4 Oct 2024 10:55:02 -0400 Subject: [PATCH 02/12] feat: Update to new types --- rollup.config.js | 5 ++++- src/languages/json-language.js | 3 ++- src/languages/json-source-code.js | 24 ++++++++++++++++++++- src/types.ts | 36 ++++++++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 11c7417..03a11e1 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -15,7 +15,10 @@ export default { ], plugins: [ copy({ - targets: [{ src: "src/types.ts", dest: "dist/esm" }], + targets: [ + { src: "src/types.ts", dest: "dist/cjs" }, + { src: "src/types.ts", dest: "dist/esm" }, + ], }), ], }; diff --git a/src/languages/json-language.js b/src/languages/json-language.js index 9948aac..c5e54f0 100644 --- a/src/languages/json-language.js +++ b/src/languages/json-language.js @@ -25,6 +25,7 @@ import { visitorKeys } from "@humanwhocodes/momoa"; * @typedef {Object} JSONLanguageOptions * @property {boolean} [allowTrailingCommas] Whether to allow trailing commas. */ +/** @typedef {import("../types.ts").IJSONLanguage} IJSONLanguage */ //----------------------------------------------------------------------------- // Exports @@ -32,7 +33,7 @@ import { visitorKeys } from "@humanwhocodes/momoa"; /** * JSON Language Object - * @implements {Language} + * @implements {IJSONLanguage} */ export class JSONLanguage { /** diff --git a/src/languages/json-source-code.js b/src/languages/json-source-code.js index acec0ec..039fff1 100644 --- a/src/languages/json-source-code.js +++ b/src/languages/json-source-code.js @@ -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 { /** @@ -117,6 +119,26 @@ export class JSONSourceCode extends TextSourceCodeBase { : []; } + /* eslint-disable class-methods-use-this -- Required to complete interface. */ + + /** + * Returns the loc information for the given node or token. + * @param {JSONSyntaxElement} nodeOrToken The node or token to get the loc information for. + * @returns {SourceLocation} The loc information for the node or token. + */ + getLoc(nodeOrToken) { + return nodeOrToken.loc; + } + + /** + * Returns the range information for the given node or token. + * @param {JSONSyntaxElement} nodeOrToken The node or token to get the range information for. + * @returns {SourceRange} The range information for the node or token. + */ + getRange(nodeOrToken) { + return nodeOrToken.range; + } + /** * Returns the value of the given comment. * @param {JSONToken} comment The comment to get the value of. diff --git a/src/types.ts b/src/types.ts index b98ad1b..23e67aa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,11 @@ // Imports //------------------------------------------------------------------------------ -import { RuleVisitor } from "../../rewrite/packages/core/src/types.ts"; +import type { + RuleVisitor, + TextSourceCode, + Language, +} from "../../rewrite/packages/core/src/types.ts"; import { DocumentNode, MemberNode, @@ -21,6 +25,8 @@ import { NaNNode, InfinityNode, IdentifierNode, + AnyNode, + Token, } from "@humanwhocodes/momoa"; //------------------------------------------------------------------------------ @@ -29,6 +35,16 @@ import { type ValueNodeParent = DocumentNode | MemberNode | ElementNode; +/** + * A JSON syntax element, including nodes and tokens. + */ +export type JSONSyntaxElement = Token | AnyNode; + +/** + * Language options provided for JSON files. + */ +export type JSONLanguageOptions = Record; + /** * The visitor format returned from rules in this package. */ @@ -59,3 +75,21 @@ export interface JSONRuleVisitor extends RuleVisitor { "Infinity:exit"?(node: InfinityNode, parent?: ValueNodeParent): void; "Identifier:exit"?(node: IdentifierNode, parent?: ValueNodeParent): void; } + +/** + * The `SourceCode` implementation for JSON files. + */ +export type IJSONSourceCode = TextSourceCode<{ + LangOptions: JSONLanguageOptions; + RootNode: DocumentNode; + Node: JSONSyntaxElement; + SyntaxElementWithLoc: JSONSyntaxElement; + ConfigNode: null; +}>; + +export type IJSONLanguage = Language<{ + LangOptions: JSONLanguageOptions; + Code: IJSONSourceCode; + RootNode: DocumentNode; + Node: AnyNode; +}>; From c9caa6c386cfabf92a2111e7b7fe1fd4a7b947f6 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 21 Nov 2024 14:36:56 -0500 Subject: [PATCH 03/12] fix: Update types from @eslint/core --- src/languages/json-language.js | 5 +---- src/languages/json-source-code.js | 22 +--------------------- src/rules/no-duplicate-keys.js | 8 ++++---- src/rules/no-empty-keys.js | 8 ++++---- src/rules/no-unsafe-values.js | 27 ++++++++++++++++++++++++--- src/types.ts | 27 +++++++++++++++++++++++---- tests/types/types.test.ts | 4 ++-- tools/dedupe-types.js | 2 +- tsconfig.json | 2 +- 9 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/languages/json-language.js b/src/languages/json-language.js index c5e54f0..5a719af 100644 --- a/src/languages/json-language.js +++ b/src/languages/json-language.js @@ -21,11 +21,8 @@ import { visitorKeys } from "@humanwhocodes/momoa"; /** @typedef {import("@eslint/core").OkParseResult} OkParseResult */ /** @typedef {import("@eslint/core").ParseResult} 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 diff --git a/src/languages/json-source-code.js b/src/languages/json-source-code.js index 039fff1..e512f83 100644 --- a/src/languages/json-source-code.js +++ b/src/languages/json-source-code.js @@ -119,26 +119,6 @@ export class JSONSourceCode extends TextSourceCodeBase { : []; } - /* eslint-disable class-methods-use-this -- Required to complete interface. */ - - /** - * Returns the loc information for the given node or token. - * @param {JSONSyntaxElement} nodeOrToken The node or token to get the loc information for. - * @returns {SourceLocation} The loc information for the node or token. - */ - getLoc(nodeOrToken) { - return nodeOrToken.loc; - } - - /** - * Returns the range information for the given node or token. - * @param {JSONSyntaxElement} nodeOrToken The node or token to get the range information for. - * @returns {SourceRange} The range information for the node or token. - */ - getRange(nodeOrToken) { - return nodeOrToken.range; - } - /** * Returns the value of the given comment. * @param {JSONToken} comment The comment to get the value of. @@ -169,7 +149,7 @@ export class JSONSourceCode extends TextSourceCodeBase { ); } - return this.#inlineConfigComments; + return this.#inlineConfigComments ?? []; } /** diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index e511448..e9610c7 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -7,17 +7,17 @@ // Type Definitions //----------------------------------------------------------------------------- -/** @typedef {import("../types.ts").JSONRuleVisitor} JSONRuleVisitor */ -/** @typedef {import("../../../rewrite/packages/core/src/types.ts").RuleDefinition} RuleDefinition */ +/** @typedef {"duplicateKey"} NoDuplicateKeysMessageIds */ +/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoDuplicateKeysMessageIds>} NoDuplicateKeysRuleDefinition */ //----------------------------------------------------------------------------- // Rule Definition //----------------------------------------------------------------------------- -/** @type {RuleDefinition} */ +/** @type {NoDuplicateKeysRuleDefinition} */ export default { meta: { - type: /** @type {const} */ ("problem"), + type: "problem", docs: { description: "Disallow duplicate keys in JSON objects", diff --git a/src/rules/no-empty-keys.js b/src/rules/no-empty-keys.js index 93e8a2d..73983cc 100644 --- a/src/rules/no-empty-keys.js +++ b/src/rules/no-empty-keys.js @@ -7,17 +7,17 @@ // Type Definitions //----------------------------------------------------------------------------- -/** @typedef {import("../types.ts").JSONRuleVisitor} JSONRuleVisitor */ -/** @typedef {import("../../../rewrite/packages/core/src/types.ts").RuleDefinition} RuleDefinition */ +/** @typedef {"emptyKey"} NoEmptyKeysMessageIds */ +/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoEmptyKeysMessageIds>} NoEmptyKeysRuleDefinition */ //----------------------------------------------------------------------------- // Rule Definition //----------------------------------------------------------------------------- -/** @type {RuleDefinition} */ +/** @type {NoEmptyKeysRuleDefinition} */ export default { meta: { - type: /** @type {const} */ ("problem"), + type: "problem", docs: { description: "Disallow empty keys in JSON objects", diff --git a/src/rules/no-unsafe-values.js b/src/rules/no-unsafe-values.js index ed29a48..671362e 100644 --- a/src/rules/no-unsafe-values.js +++ b/src/rules/no-unsafe-values.js @@ -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 = /^-?(?0|([1-9][0-9]*))(?:\.(?[0-9]+))?(?:[eE][+-]?[0-9]+)?$/u; const NON_ZERO = /[1-9]/u; +//----------------------------------------------------------------------------- +// Rule Definition +//----------------------------------------------------------------------------- + +/** @type {NoUnsafeValuesRuleDefinition} */ export default { meta: { - type: /** @type {const} */ ("problem"), + type: "problem", docs: { description: "Disallow JSON values that are unsafe for interchange", diff --git a/src/types.ts b/src/types.ts index 23e67aa..327dd56 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,7 +11,9 @@ import type { RuleVisitor, TextSourceCode, Language, -} from "../../rewrite/packages/core/src/types.ts"; + LanguageOptions, + RuleDefinition, +} from "@eslint/core"; import { DocumentNode, MemberNode, @@ -43,7 +45,12 @@ export type JSONSyntaxElement = Token | AnyNode; /** * Language options provided for JSON files. */ -export type JSONLanguageOptions = Record; +export interface JSONLanguageOptions extends LanguageOptions { + /** + * Whether to allow trailing commas. Only valid in JSONC. + */ + allowTrailingCommas?: boolean; +} /** * The visitor format returned from rules in this package. @@ -82,9 +89,8 @@ export interface JSONRuleVisitor extends RuleVisitor { export type IJSONSourceCode = TextSourceCode<{ LangOptions: JSONLanguageOptions; RootNode: DocumentNode; - Node: JSONSyntaxElement; SyntaxElementWithLoc: JSONSyntaxElement; - ConfigNode: null; + ConfigNode: Token; }>; export type IJSONLanguage = Language<{ @@ -93,3 +99,16 @@ export type IJSONLanguage = Language<{ RootNode: DocumentNode; Node: AnyNode; }>; + +export type JSONRuleDefinition< + JSONRuleOptions extends unknown[], + JSONRuleMessageIds extends string = "", +> = RuleDefinition<{ + LangOptions: JSONLanguageOptions; + Code: IJSONSourceCode; + RuleOptions: JSONRuleOptions; + Visitor: JSONRuleVisitor; + Node: AnyNode; + MessageIds: JSONRuleMessageIds; + ExtRuleDocs: {}; +}>; diff --git a/tests/types/types.test.ts b/tests/types/types.test.ts index a9f5374..6e6edd0 100644 --- a/tests/types/types.test.ts +++ b/tests/types/types.test.ts @@ -1,7 +1,7 @@ import json from "@eslint/json"; -import { ESLint } from "eslint"; +// import { ESLint } from "eslint"; -json satisfies ESLint.Plugin; +// json satisfies ESLint.Plugin; json.meta.name satisfies string; json.meta.version satisfies string; diff --git a/tools/dedupe-types.js b/tools/dedupe-types.js index 0378001..fdaba8d 100644 --- a/tools/dedupe-types.js +++ b/tools/dedupe-types.js @@ -42,7 +42,7 @@ files.forEach(filePath => { // replace references to ../types.ts with types.ts const text = remainingLines .join("\n") - .replace(/\.\.\/types\.ts/gu, "types.ts"); + .replace(/\.\.\/types\.ts/gu, "./types.ts"); fs.writeFileSync(filePath, text, "utf8"); }); diff --git a/tsconfig.json b/tsconfig.json index 0a3d0a1..2e82117 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "allowJs": true, "checkJs": true, "outDir": "dist/esm", - "target": "ES2022", + "target": "ESNext", "moduleResolution": "NodeNext", "module": "NodeNext", "allowImportingTsExtensions": true From e0c55792a1d8f32850f63740cdd49af344d56114 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 4 Dec 2024 16:50:06 -0500 Subject: [PATCH 04/12] Update types --- package.json | 1 - src/rules/no-duplicate-keys.js | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 1c4fb25..730b3fc 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "@humanwhocodes/momoa": "^3.3.4" }, "devDependencies": { - "@types/eslint": "^8.56.10", "c8": "^9.1.0", "dedent": "^1.5.3", "eslint": "^9.11.1", diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index e9610c7..4e54f95 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -9,6 +9,7 @@ /** @typedef {"duplicateKey"} NoDuplicateKeysMessageIds */ /** @typedef {import("../types.ts").JSONRuleDefinition<[], NoDuplicateKeysMessageIds>} NoDuplicateKeysRuleDefinition */ +/** @typedef {import("@humanwhocodes/momoa").MemberNode} MemberNode */ //----------------------------------------------------------------------------- // Rule Definition @@ -29,7 +30,10 @@ export default { }, create(context) { + /** @type {Array|undefined>} */ const objectKeys = []; + + /** @type {Map|undefined} */ let keys; return { @@ -44,7 +48,7 @@ export default { ? node.name.value : node.name.name; - if (keys.has(key)) { + if (keys?.has(key)) { context.report({ loc: node.name.loc, messageId: "duplicateKey", @@ -53,7 +57,7 @@ export default { }, }); } else { - keys.set(key, node); + keys?.set(key, node); } }, "Object:exit"() { From a2651c70728f42e2700704c635d69d08b2f175ff Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Wed, 4 Dec 2024 16:52:35 -0500 Subject: [PATCH 05/12] Add types.ts to JSR definition --- jsr.json | 1 + 1 file changed, 1 insertion(+) diff --git a/jsr.json b/jsr.json index ff3497d..d24bb93 100644 --- a/jsr.json +++ b/jsr.json @@ -6,6 +6,7 @@ "include": [ "dist/esm/index.js", "dist/esm/index.d.ts", + "dist/esm/types.ts", "README.md", "jsr.json", "LICENSE" From a43dbf93aa9f86429ae2f05f86c754246fc3ef0a Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 9 Dec 2024 11:18:03 -0500 Subject: [PATCH 06/12] Clean up no-unsafe-values.js --- src/rules/no-unsafe-values.js | 6 ++++-- src/types.ts | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/rules/no-unsafe-values.js b/src/rules/no-unsafe-values.js index 671362e..6249e23 100644 --- a/src/rules/no-unsafe-values.js +++ b/src/rules/no-unsafe-values.js @@ -17,7 +17,7 @@ /* * 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. */ @@ -106,7 +106,9 @@ export default { loc: node.loc, messageId: "subnormal", // Value included so that it's seen in scientific notation - data: node, + data: { + value, + }, }); } } diff --git a/src/types.ts b/src/types.ts index 327dd56..9c08e8b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -86,12 +86,26 @@ export interface JSONRuleVisitor extends RuleVisitor { /** * The `SourceCode` implementation for JSON files. */ -export type IJSONSourceCode = TextSourceCode<{ - LangOptions: JSONLanguageOptions; - RootNode: DocumentNode; - SyntaxElementWithLoc: JSONSyntaxElement; - ConfigNode: Token; -}>; +export interface IJSONSourceCode + extends TextSourceCode<{ + LangOptions: JSONLanguageOptions; + RootNode: DocumentNode; + SyntaxElementWithLoc: JSONSyntaxElement; + ConfigNode: Token; + }> { + /** + * Get the text of a syntax element. + * @param syntaxElement The syntax element to get the text of. + * @param beforeCount The number of characters to include before the syntax element. + * @param afterCount The number of characters to include after the syntax element. + * @returns The text of the syntax element. + */ + getText( + syntaxElement: JSONSyntaxElement, + beforeCount?: number, + afterCount?: number, + ): string; +} export type IJSONLanguage = Language<{ LangOptions: JSONLanguageOptions; From 88ff7fe6ab082b7a2e940b7e77548db40ec092a5 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 9 Dec 2024 11:21:13 -0500 Subject: [PATCH 07/12] Fix tests --- tests/rules/no-unsafe-values.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rules/no-unsafe-values.test.js b/tests/rules/no-unsafe-values.test.js index 7e8234b..4a75c85 100644 --- a/tests/rules/no-unsafe-values.test.js +++ b/tests/rules/no-unsafe-values.test.js @@ -251,7 +251,7 @@ ruleTester.run("no-unsafe-values", rule, { { messageId: "subnormal", data: { - value: "2.225073858507201e-308", + value: "2.2250738585072009e-308", }, line: 1, column: 1, @@ -266,7 +266,7 @@ ruleTester.run("no-unsafe-values", rule, { { messageId: "subnormal", data: { - value: "-2.225073858507201e-308", + value: "-2.2250738585072009e-308", }, line: 1, column: 1, From c4078b44dfd7c34390933701f79150b822b3aba4 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 12 Dec 2024 16:55:38 -0500 Subject: [PATCH 08/12] Update tools/dedupe-types.js Co-authored-by: Francesco Trotta --- tools/dedupe-types.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dedupe-types.js b/tools/dedupe-types.js index fdaba8d..b4a4ada 100644 --- a/tools/dedupe-types.js +++ b/tools/dedupe-types.js @@ -39,7 +39,7 @@ files.forEach(filePath => { return true; }); - // replace references to ../types.ts with types.ts + // replace references to ../types.ts with ./types.ts const text = remainingLines .join("\n") .replace(/\.\.\/types\.ts/gu, "./types.ts"); From 7875b2ea500ba64c94ef714e9ba0afec5a54c30b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 16 Dec 2024 11:13:57 -0500 Subject: [PATCH 09/12] Update src/rules/no-duplicate-keys.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- src/rules/no-duplicate-keys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index 4e54f95..b9c85df 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -48,7 +48,7 @@ export default { ? node.name.value : node.name.name; - if (keys?.has(key)) { + if (/** @type {Map} */ (keys).has(key)) { context.report({ loc: node.name.loc, messageId: "duplicateKey", From db446a99936108f4c76c6f171c0aea36b0b0e47a Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Mon, 16 Dec 2024 11:21:08 -0500 Subject: [PATCH 10/12] clean up --- src/rules/no-duplicate-keys.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index b9c85df..e3ac3d6 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -48,7 +48,7 @@ export default { ? node.name.value : node.name.name; - if (/** @type {Map} */ (keys).has(key)) { + if (keys.has(key)) { context.report({ loc: node.name.loc, messageId: "duplicateKey", @@ -57,7 +57,7 @@ export default { }, }); } else { - keys?.set(key, node); + keys.set(key, node); } }, "Object:exit"() { From 2f0963a9279578f67b67c3121285866ad7da9f04 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 16 Jan 2025 17:11:38 -0500 Subject: [PATCH 11/12] Fix CJS type definitions --- package.json | 2 +- rollup.config.js | 2 +- tools/build-cts.js | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tools/build-cts.js diff --git a/package.json b/package.json index 730b3fc..58ed0d7 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,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", diff --git a/rollup.config.js b/rollup.config.js index 03a11e1..0e0b3f1 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -16,7 +16,7 @@ export default { plugins: [ copy({ targets: [ - { src: "src/types.ts", dest: "dist/cjs" }, + { src: "src/types.ts", dest: "dist/cjs/types.cts" }, { src: "src/types.ts", dest: "dist/esm" }, ], }), diff --git a/tools/build-cts.js b/tools/build-cts.js new file mode 100644 index 0000000..ade7ae1 --- /dev/null +++ b/tools/build-cts.js @@ -0,0 +1,16 @@ +/** + * @fileoverview Rewrites import expressions for CommonJS compatibility. + * This script creates "dist/cjs/index.d.cts" from "dist/esm/index.d.ts" by modifying imports + * from `"./types.ts"` to `"./types.cts"`. + * + * @author Francesco Trotta + */ + +import { readFile, writeFile } from "node:fs/promises"; + +const oldSourceText = await readFile("dist/esm/index.d.ts", "utf-8"); +const newSourceText = oldSourceText.replaceAll( + 'import("./types.ts")', + 'import("./types.cts")', +); +await writeFile("dist/cjs/index.d.cts", newSourceText); From 71d6b45c3e46f29fff31593819dfca297bcb4e75 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 16 Jan 2025 17:16:34 -0500 Subject: [PATCH 12/12] Fix build step --- rollup.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup.config.js b/rollup.config.js index 0e0b3f1..5b813a8 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -16,7 +16,7 @@ export default { plugins: [ copy({ targets: [ - { src: "src/types.ts", dest: "dist/cjs/types.cts" }, + { src: "src/types.ts", dest: "dist/cjs", rename: "types.cts" }, { src: "src/types.ts", dest: "dist/esm" }, ], }),