diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 78e7f27..8032c17 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.11.0"
+ ".": "0.12.0"
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c88f549..b20f6dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## [0.12.0](https://github.com/eslint/json/compare/json-v0.11.0...json-v0.12.0) (2025-04-16)
+
+
+### ⚠ BREAKING CHANGES
+
+* Update package types for better reuse ([#91](https://github.com/eslint/json/issues/91))
+
+### Features
+
+* Update package types for better reuse ([#91](https://github.com/eslint/json/issues/91)) ([dce4601](https://github.com/eslint/json/commit/dce4601b1a40ceaeb4b61fbcbef0170a67b73e37))
+
+
+### Bug Fixes
+
+* Update `types.ts` for compatibility with `verbatimModuleSyntax` ([#88](https://github.com/eslint/json/issues/88)) ([d099c78](https://github.com/eslint/json/commit/d099c78318f8ca9a426d233717728304418425a1))
+
## [0.11.0](https://github.com/eslint/json/compare/json-v0.10.0...json-v0.11.0) (2025-03-14)
diff --git a/README.md b/README.md
index 99fa01f..1795393 100644
--- a/README.md
+++ b/README.md
@@ -254,10 +254,11 @@ Apache 2.0
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
-
Platinum Sponsors
+Diamond Sponsors
+
Platinum Sponsors
Gold Sponsors
Silver Sponsors
-
Bronze Sponsors
+
Bronze Sponsors
Technology Sponsors
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.
diff --git a/jsr.json b/jsr.json
index e1a37b3..5c5cf76 100644
--- a/jsr.json
+++ b/jsr.json
@@ -1,6 +1,6 @@
{
"name": "@eslint/json",
- "version": "0.11.0",
+ "version": "0.12.0",
"exports": "./dist/esm/index.js",
"publish": {
"include": [
diff --git a/package.json b/package.json
index 0ee75eb..1f29c94 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@eslint/json",
- "version": "0.11.0",
+ "version": "0.12.0",
"description": "JSON linting plugin for ESLint",
"author": "Nicholas C. Zakas",
"type": "module",
@@ -81,7 +81,7 @@
"devDependencies": {
"c8": "^9.1.0",
"dedent": "^1.5.3",
- "eslint": "^9.11.1",
+ "eslint": "^9.23.0",
"eslint-config-eslint": "^11.0.0",
"eslint-plugin-eslint-plugin": "^6.3.2",
"got": "^14.4.2",
@@ -90,6 +90,7 @@
"prettier": "^3.4.1",
"rollup": "^4.16.2",
"rollup-plugin-copy": "^3.5.0",
+ "rollup-plugin-delete": "^3.0.1",
"typescript": "^5.4.5",
"yorkie": "^2.0.0"
},
diff --git a/rollup.config.js b/rollup.config.js
index 5b813a8..cf06b2d 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,4 +1,5 @@
import copy from "rollup-plugin-copy";
+import del from "rollup-plugin-delete";
export default {
input: "src/index.js",
@@ -14,6 +15,7 @@ export default {
},
],
plugins: [
+ del({ targets: "dist/*" }),
copy({
targets: [
{ src: "src/types.ts", dest: "dist/cjs", rename: "types.cts" },
diff --git a/src/index.js b/src/index.js
index 178dca5..99a5ca9 100644
--- a/src/index.js
+++ b/src/index.js
@@ -23,7 +23,7 @@ import topLevelInterop from "./rules/top-level-interop.js";
const plugin = {
meta: {
name: "@eslint/json",
- version: "0.11.0", // x-release-please-version
+ version: "0.12.0", // x-release-please-version
},
languages: {
json: new JSONLanguage({ mode: "json" }),
@@ -57,4 +57,5 @@ const plugin = {
}
export default plugin;
-export { JSONLanguage, JSONSourceCode };
+export { JSONSourceCode };
+export * from "./languages/json-language.js";
diff --git a/src/languages/json-language.js b/src/languages/json-language.js
index 5a719af..22a3222 100644
--- a/src/languages/json-language.js
+++ b/src/languages/json-language.js
@@ -15,14 +15,16 @@ import { visitorKeys } from "@humanwhocodes/momoa";
// Types
//-----------------------------------------------------------------------------
-/** @typedef {import("@humanwhocodes/momoa").DocumentNode} DocumentNode */
-/** @typedef {import("@humanwhocodes/momoa").Node} JSONNode */
-/** @typedef {import("@eslint/core").Language} Language */
-/** @typedef {import("@eslint/core").OkParseResult} OkParseResult */
-/** @typedef {import("@eslint/core").ParseResult} ParseResult */
-/** @typedef {import("@eslint/core").File} File */
-/** @typedef {import("../types.ts").IJSONLanguage} IJSONLanguage */
-/** @typedef {import("../types.ts").JSONLanguageOptions} JSONLanguageOptions */
+/**
+ * @import { DocumentNode, AnyNode } from "@humanwhocodes/momoa";
+ * @import { Language, OkParseResult, ParseResult, File } from "@eslint/core";
+ *
+ * @typedef {OkParseResult} JSONOkParseResult
+ * @typedef {ParseResult} JSONParseResult
+ *
+ * @typedef {Object} JSONLanguageOptions
+ * @property {boolean} [allowTrailingCommas] Whether to allow trailing commas in JSONC mode.
+ */
//-----------------------------------------------------------------------------
// Exports
@@ -30,7 +32,7 @@ import { visitorKeys } from "@humanwhocodes/momoa";
/**
* JSON Language Object
- * @implements {IJSONLanguage}
+ * @implements {Language<{ LangOptions: JSONLanguageOptions; Code: JSONSourceCode; RootNode: DocumentNode; Node: AnyNode }>}
*/
export class JSONLanguage {
/**
@@ -107,7 +109,7 @@ export class JSONLanguage {
* Parses the given file into an AST.
* @param {File} file The virtual file to parse.
* @param {{languageOptions: JSONLanguageOptions}} context The options to use for parsing.
- * @returns {ParseResult} The result of parsing.
+ * @returns {JSONParseResult} The result of parsing.
*/
parse(file, context) {
// Note: BOM already removed
@@ -155,7 +157,7 @@ export class JSONLanguage {
/**
* Creates a new `JSONSourceCode` object from the given information.
* @param {File} file The virtual file to create a `JSONSourceCode` object from.
- * @param {OkParseResult} parseResult The result returned from `parse()`.
+ * @param {JSONOkParseResult} parseResult The result returned from `parse()`.
* @returns {JSONSourceCode} The new `JSONSourceCode` object.
*/
createSourceCode(file, parseResult) {
diff --git a/src/languages/json-source-code.js b/src/languages/json-source-code.js
index e512f83..1ee69f3 100644
--- a/src/languages/json-source-code.js
+++ b/src/languages/json-source-code.js
@@ -19,19 +19,12 @@ import {
// Types
//-----------------------------------------------------------------------------
-/** @typedef {import("@humanwhocodes/momoa").DocumentNode} DocumentNode */
-/** @typedef {import("@humanwhocodes/momoa").Node} JSONNode */
-/** @typedef {import("@humanwhocodes/momoa").Token} JSONToken */
-/** @typedef {import("@eslint/core").SourceRange} SourceRange */
-/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
-/** @typedef {import("@eslint/core").File} File */
-/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
-/** @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 */
+/**
+ * @import { DocumentNode, Node, Token } from "@humanwhocodes/momoa";
+ * @import { SourceLocation, FileProblem, DirectiveType, RulesConfig, TextSourceCode} from "@eslint/core";
+ * @import { JSONSyntaxElement } from "../types.ts";
+ * @import { JSONLanguageOptions } from "./json-language.js";
+ */
//-----------------------------------------------------------------------------
// Helpers
@@ -48,14 +41,14 @@ const INLINE_CONFIG =
class JSONTraversalStep extends VisitNodeStep {
/**
* The target of the step.
- * @type {JSONNode}
+ * @type {Node}
*/
target = undefined;
/**
* Creates a new instance.
* @param {Object} options The options for the step.
- * @param {JSONNode} options.target The target of the step.
+ * @param {Node} options.target The target of the step.
* @param {1|2} options.phase The phase of the step.
* @param {Array} options.args The arguments of the step.
*/
@@ -72,7 +65,7 @@ class JSONTraversalStep extends VisitNodeStep {
/**
* JSON Source Code Object
- * @implements {IJSONSourceCode}
+ * @implements {TextSourceCode<{LangOptions: JSONLanguageOptions, RootNode: DocumentNode, SyntaxElementWithLoc: JSONSyntaxElement, ConfigNode: Token}>}
*/
export class JSONSourceCode extends TextSourceCodeBase {
/**
@@ -83,13 +76,13 @@ export class JSONSourceCode extends TextSourceCodeBase {
/**
* Cache of parent nodes.
- * @type {WeakMap}
+ * @type {WeakMap}
*/
#parents = new WeakMap();
/**
* Collection of inline configuration comments.
- * @type {Array}
+ * @type {Array}
*/
#inlineConfigComments;
@@ -101,7 +94,7 @@ export class JSONSourceCode extends TextSourceCodeBase {
/**
* The comment node in the source code.
- * @type {Array|undefined}
+ * @type {Array|undefined}
*/
comments;
@@ -121,7 +114,7 @@ export class JSONSourceCode extends TextSourceCodeBase {
/**
* Returns the value of the given comment.
- * @param {JSONToken} comment The comment to get the value of.
+ * @param {Token} comment The comment to get the value of.
* @returns {string} The value of the comment.
* @throws {Error} When an unexpected comment type is passed.
*/
@@ -140,7 +133,7 @@ export class JSONSourceCode extends TextSourceCodeBase {
/**
* Returns an array of all inline configuration nodes found in the
* source code.
- * @returns {Array} An array of all inline configuration nodes.
+ * @returns {Array} An array of all inline configuration nodes.
*/
getInlineConfigNodes() {
if (!this.#inlineConfigComments) {
@@ -251,8 +244,8 @@ export class JSONSourceCode extends TextSourceCodeBase {
/**
* Returns the parent of the given node.
- * @param {JSONNode} node The node to get the parent of.
- * @returns {JSONNode|undefined} The parent of the node.
+ * @param {Node} node The node to get the parent of.
+ * @returns {Node|undefined} The parent of the node.
*/
getParent(node) {
return this.#parents.get(node);
diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js
index 6897acb..08a96e2 100644
--- a/src/rules/no-duplicate-keys.js
+++ b/src/rules/no-duplicate-keys.js
@@ -7,9 +7,13 @@
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"duplicateKey"} NoDuplicateKeysMessageIds */
-/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoDuplicateKeysMessageIds>} NoDuplicateKeysRuleDefinition */
-/** @typedef {import("@humanwhocodes/momoa").MemberNode} MemberNode */
+/**
+ * @import { MemberNode } from "@humanwhocodes/momoa";
+ * @import { JSONRuleDefinition } from "../types.ts";
+ *
+ * @typedef {"duplicateKey"} NoDuplicateKeysMessageIds
+ * @typedef {JSONRuleDefinition<{ MessageIds: NoDuplicateKeysMessageIds }>} NoDuplicateKeysRuleDefinition
+ */
//-----------------------------------------------------------------------------
// Rule Definition
diff --git a/src/rules/no-empty-keys.js b/src/rules/no-empty-keys.js
index a85aa91..69f00a2 100644
--- a/src/rules/no-empty-keys.js
+++ b/src/rules/no-empty-keys.js
@@ -7,8 +7,12 @@
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"emptyKey"} NoEmptyKeysMessageIds */
-/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoEmptyKeysMessageIds>} NoEmptyKeysRuleDefinition */
+/**
+ * @import { JSONRuleDefinition } from "../types.ts";
+ *
+ * @typedef {"emptyKey"} NoEmptyKeysMessageIds
+ * @typedef {JSONRuleDefinition<{ MessageIds: NoEmptyKeysMessageIds }>} NoEmptyKeysRuleDefinition
+ */
//-----------------------------------------------------------------------------
// Rule Definition
diff --git a/src/rules/no-unnormalized-keys.js b/src/rules/no-unnormalized-keys.js
index b5a52bb..9ac9a6a 100644
--- a/src/rules/no-unnormalized-keys.js
+++ b/src/rules/no-unnormalized-keys.js
@@ -7,8 +7,13 @@
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds */
-/** @typedef {import("../types.ts").JSONRuleDefinition<[{form:string}], NoUnnormalizedKeysMessageIds>} NoUnnormalizedKeysRuleDefinition */
+/**
+ * @import { JSONRuleDefinition } from "../types.ts";
+ *
+ * @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds
+ * @typedef {{ form: string }} NoUnnormalizedKeysOptions
+ * @typedef {JSONRuleDefinition<{ RuleOptions: [NoUnnormalizedKeysOptions], MessageIds: NoUnnormalizedKeysMessageIds }>} NoUnnormalizedKeysRuleDefinition
+ */
//-----------------------------------------------------------------------------
// Rule Definition
diff --git a/src/rules/no-unsafe-values.js b/src/rules/no-unsafe-values.js
index 63bc519..e40e5bc 100644
--- a/src/rules/no-unsafe-values.js
+++ b/src/rules/no-unsafe-values.js
@@ -7,8 +7,12 @@
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds */
-/** @typedef {import("../types.ts").JSONRuleDefinition<[], NoUnsafeValuesMessageIds>} NoUnsafeValuesRuleDefinition */
+/**
+ * @import { JSONRuleDefinition } from "../types.ts";
+ *
+ * @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds
+ * @typedef {JSONRuleDefinition<{ MessageIds: NoUnsafeValuesMessageIds }>} NoUnsafeValuesRuleDefinition
+ */
//-----------------------------------------------------------------------------
// Helpers
diff --git a/src/rules/sort-keys.js b/src/rules/sort-keys.js
index 3d6cfc7..e7f7b13 100644
--- a/src/rules/sort-keys.js
+++ b/src/rules/sort-keys.js
@@ -14,22 +14,23 @@ import naturalCompare from "natural-compare";
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"sortKeys"} SortKeysMessageIds */
-
/**
+ * @import { JSONRuleDefinition } from "../types.ts";
+ * @import { MemberNode } from "@humanwhocodes/momoa";
+ *
* @typedef {Object} SortOptions
* @property {boolean} caseSensitive
* @property {boolean} natural
* @property {number} minKeys
* @property {boolean} allowLineSeparatedGroups
+ *
+ * @typedef {"sortKeys"} SortKeysMessageIds
+ * @typedef {"asc"|"desc"} SortDirection
+ * @typedef {[SortDirection, SortOptions]} SortKeysRuleOptions
+ * @typedef {JSONRuleDefinition<{ RuleOptions: SortKeysRuleOptions, MessageIds: SortKeysMessageIds }>} SortKeysRuleDefinition
+ * @typedef {(a:string,b:string) => boolean} Comparator
*/
-/** @typedef {"asc"|"desc"} SortDirection */
-/** @typedef {[SortDirection, SortOptions]} SortKeysRuleOptions */
-/** @typedef {import("../types.ts").JSONRuleDefinition} SortKeysRuleDefinition */
-/** @typedef {(a:string,b:string) => boolean} Comparator */
-/** @typedef {import("@humanwhocodes/momoa").MemberNode} MemberNode */
-
//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------
diff --git a/src/rules/top-level-interop.js b/src/rules/top-level-interop.js
index 96fb232..9a7ff65 100644
--- a/src/rules/top-level-interop.js
+++ b/src/rules/top-level-interop.js
@@ -7,8 +7,12 @@
// Type Definitions
//-----------------------------------------------------------------------------
-/** @typedef {"topLevel"} TopLevelInteropMessageIds */
-/** @typedef {import("../types.ts").JSONRuleDefinition<[], TopLevelInteropMessageIds>} TopLevelInteropRuleDefinition */
+/**
+ * @import { JSONRuleDefinition } from "../types.ts";
+ *
+ * @typedef {"topLevel"} TopLevelInteropMessageIds
+ * @typedef {JSONRuleDefinition<{ MessageIds: TopLevelInteropMessageIds }>} TopLevelInteropRuleDefinition
+ */
//-----------------------------------------------------------------------------
// Rule Definition
diff --git a/src/types.ts b/src/types.ts
index f8dc7e1..f3077ad 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -7,14 +7,8 @@
// Imports
//------------------------------------------------------------------------------
+import type { RuleVisitor, RuleDefinition } from "@eslint/core";
import type {
- RuleVisitor,
- TextSourceCode,
- Language,
- LanguageOptions,
- RuleDefinition,
-} from "@eslint/core";
-import {
DocumentNode,
MemberNode,
ElementNode,
@@ -30,6 +24,7 @@ import {
AnyNode,
Token,
} from "@humanwhocodes/momoa";
+import type { JSONLanguageOptions, JSONSourceCode } from "./index.js";
//------------------------------------------------------------------------------
// Types
@@ -42,16 +37,6 @@ type ValueNodeParent = DocumentNode | MemberNode | ElementNode;
*/
export type JSONSyntaxElement = Token | AnyNode;
-/**
- * Language options provided for JSON files.
- */
-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.
*/
@@ -83,56 +68,25 @@ export interface JSONRuleVisitor extends RuleVisitor {
"Identifier:exit"?(node: IdentifierNode, parent?: ValueNodeParent): void;
}
-/**
- * The `SourceCode` implementation for JSON files.
- */
-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;
-
- /**
- * Any comments found in a JSONC or JSON5 file.
- */
- comments: Array | undefined;
-
- /**
- * The lines of text found in the file.
- */
- lines: Array;
-}
-
-export type IJSONLanguage = Language<{
- LangOptions: JSONLanguageOptions;
- Code: IJSONSourceCode;
- RootNode: DocumentNode;
- Node: AnyNode;
-}>;
+export type JSONRuleDefinitionTypeOptions = {
+ RuleOptions: unknown[];
+ MessageIds: string;
+ ExtRuleDocs: Record;
+};
export type JSONRuleDefinition<
- JSONRuleOptions extends unknown[],
- JSONRuleMessageIds extends string = "",
-> = RuleDefinition<{
- LangOptions: JSONLanguageOptions;
- Code: IJSONSourceCode;
- RuleOptions: JSONRuleOptions;
- Visitor: JSONRuleVisitor;
- Node: AnyNode;
- MessageIds: JSONRuleMessageIds;
- ExtRuleDocs: {};
-}>;
+ Options extends Partial = {},
+> = RuleDefinition<
+ // Language specific type options (non-configurable)
+ {
+ LangOptions: JSONLanguageOptions;
+ Code: JSONSourceCode;
+ Visitor: JSONRuleVisitor;
+ Node: AnyNode;
+ } & Required<
+ // Rule specific type options (custom)
+ Options &
+ // Rule specific type options (defaults)
+ Omit
+ >
+>;
diff --git a/tests/types/tsconfig.json b/tests/types/tsconfig.json
index c6bd5a6..105220c 100644
--- a/tests/types/tsconfig.json
+++ b/tests/types/tsconfig.json
@@ -3,7 +3,9 @@
"compilerOptions": {
"noEmit": true,
"rootDir": "../..",
- "strict": true
+ "strict": true,
+ "verbatimModuleSyntax": true,
+ "erasableSyntaxOnly": true
},
"files": [],
"include": [".", "../../dist"]
diff --git a/tests/types/types.test.ts b/tests/types/types.test.ts
index 6e6edd0..8d0701e 100644
--- a/tests/types/types.test.ts
+++ b/tests/types/types.test.ts
@@ -1,7 +1,8 @@
import json from "@eslint/json";
-// import { ESLint } from "eslint";
+import { ESLint } from "eslint";
+import type { JSONSyntaxElement, JSONRuleDefinition } from "@eslint/json/types";
-// json satisfies ESLint.Plugin;
+json satisfies ESLint.Plugin;
json.meta.name satisfies string;
json.meta.version satisfies string;
@@ -21,3 +22,86 @@ json.configs.recommended.plugins satisfies object;
// Check that all recommended rule names match the names of existing rules in this plugin.
null as AssertAllNamesIn;
}
+
+// Check that types are imported correctly from `@humanwhocodes/momoa`.
+({
+ start: { line: 1, column: 1, offset: 1 },
+ end: { line: 1, column: 1, offset: 1 },
+}) satisfies JSONSyntaxElement["loc"];
+({
+ // @ts-expect-error -- This is not a valid Location.
+ start: 100,
+ end: { line: 1, column: 1, offset: 1 },
+}) satisfies JSONSyntaxElement["loc"];
+
+// All options optional - JSONRuleDefinition and JSONRuleDefinition<{}>
+// should be the same type.
+(rule1: JSONRuleDefinition, rule2: JSONRuleDefinition<{}>) => {
+ rule1 satisfies typeof rule2;
+ rule2 satisfies typeof rule1;
+};
+
+// Type restrictions should be enforced
+(): JSONRuleDefinition<{
+ RuleOptions: [string, number];
+ MessageIds: "foo" | "bar";
+ ExtRuleDocs: { foo: string; bar: number };
+}> => ({
+ meta: {
+ messages: {
+ foo: "FOO",
+
+ // @ts-expect-error Wrong type for message ID
+ bar: 42,
+ },
+ docs: {
+ foo: "FOO",
+
+ // @ts-expect-error Wrong type for declared property
+ bar: "BAR",
+
+ // @ts-expect-error Wrong type for predefined property
+ description: 42,
+ },
+ },
+ create({ options }) {
+ // Types for rule options
+ options[0] satisfies string;
+ options[1] satisfies number;
+
+ return {};
+ },
+});
+
+// Undeclared properties should produce an error
+(): JSONRuleDefinition<{
+ MessageIds: "foo" | "bar";
+ ExtRuleDocs: { foo: number; bar: string };
+}> => ({
+ meta: {
+ messages: {
+ foo: "FOO",
+
+ // Declared message ID is not required
+ // bar: "BAR",
+
+ // @ts-expect-error Undeclared message ID is not allowed
+ baz: "BAZ",
+ },
+ docs: {
+ foo: 42,
+
+ // Declared property is not required
+ // bar: "BAR",
+
+ // @ts-expect-error Undeclared property key is not allowed
+ baz: "BAZ",
+
+ // Predefined property is allowed
+ description: "Lorem ipsum",
+ },
+ },
+ create() {
+ return {};
+ },
+});
diff --git a/tools/build-cts.js b/tools/build-cts.js
index ade7ae1..873a2ae 100644
--- a/tools/build-cts.js
+++ b/tools/build-cts.js
@@ -3,14 +3,19 @@
* This script creates "dist/cjs/index.d.cts" from "dist/esm/index.d.ts" by modifying imports
* from `"./types.ts"` to `"./types.cts"`.
*
+ * Also updates "types.cts" to reference "index.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")',
-);
+const newSourceText = oldSourceText.replaceAll('"./types.ts"', '"./types.cts"');
await writeFile("dist/cjs/index.d.cts", newSourceText);
+
+// Now update the types.cts to reference index.cts
+const typesText = await readFile("dist/cjs/types.cts", "utf-8");
+const updatedTypesText = typesText.replaceAll('"./index.js"', '"./index.cjs"');
+
+await writeFile("dist/cjs/types.cts", updatedTypesText);
diff --git a/tools/dedupe-types.js b/tools/dedupe-types.js
index b4a4ada..4145cc3 100644
--- a/tools/dedupe-types.js
+++ b/tools/dedupe-types.js
@@ -4,7 +4,7 @@
* it encounters a duplicate typedef.
*
* Usage:
- * node scripts/strip-typedefs.js filename1.js filename2.js ...
+ * node tools/dedupe-types.js filename1.js filename2.js ...
*
* @author Nicholas C. Zakas
*/
@@ -19,26 +19,61 @@ import fs from "node:fs";
// Main
//-----------------------------------------------------------------------------
+const importRegExp =
+ /^\s*\*\s*@import\s*\{\s*(?[^,}]+(?:\s*,\s*[^,}]+)*)\s*\}\s*from\s*"(?[^"]+)"/u;
+
// read files from the command line
const files = process.argv.slice(2);
files.forEach(filePath => {
const lines = fs.readFileSync(filePath, "utf8").split(/\r?\n/gu);
- const typedefs = new Set();
+ const imports = new Map();
+ // find all imports and remove them
const remainingLines = lines.filter(line => {
- if (!line.startsWith("/** @typedef {import")) {
+ if (!line.startsWith(" * @import")) {
return true;
}
- if (typedefs.has(line)) {
- return false;
+ const match = importRegExp.exec(line);
+
+ if (!match) {
+ throw Error("Something is very wrong");
}
- typedefs.add(line);
- return true;
+ const source = match.groups.source;
+ const ids = match.groups.ids.split(/,/gu).map(id => id.trim());
+
+ // save the import data
+
+ if (!imports.has(source)) {
+ imports.set(source, new Set());
+ }
+
+ const existingIds = imports.get(source);
+ ids.forEach(id => existingIds.add(id));
+
+ return false;
});
+ // create a new import statement for each unique import
+ const jsdocBlock = ["/**"];
+
+ imports.forEach((ids, source) => {
+ // if it's a local file, we don't need it
+ if (source.startsWith("./")) {
+ return;
+ }
+
+ const idList = Array.from(ids).join(", ");
+ jsdocBlock.push(` * @import { ${idList} } from "${source}"`);
+ });
+
+ // add the new import statements to the top of the file
+ jsdocBlock.push(" */");
+ remainingLines.unshift(...jsdocBlock);
+ remainingLines.unshift(""); // add a blank line before the block
+
// replace references to ../types.ts with ./types.ts
const text = remainingLines
.join("\n")
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy