eslint-plugin-package-json 0.60.0 β†’ 0.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,23 @@
1
1
  # Changelog
2
2
 
3
- # [0.60.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.59.1...v0.60.0) (2025-11-03)
3
+ # [0.62.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.61.0...v0.62.0) (2025-11-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **scripts-name-casing:** add new rule ([#1344](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1344)) ([e735595](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/e735595537e6857c771eac12a1efcd55cb2d3564)), closes [#61](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/61)
4
9
 
10
+ # [0.61.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.60.0...v0.61.0) (2025-11-03)
11
+
12
+ ### Features
13
+
14
+ - add new stylistic config ([#1342](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1342)) ([3d01cce](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/3d01cce99a1718a7485669c7b8cf6143a255b094)), closes [#1341](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1341)
15
+
16
+ # [0.60.0](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.59.1...v0.60.0) (2025-11-03)
5
17
 
6
18
  ### Features
7
19
 
8
- * **valid-author:** create more precise reports ([#1337](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1337)) ([e79ff9a](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/e79ff9ac602d85bf999686b018de6ace3a7bee36)), closes [#000](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/000)
20
+ - **valid-author:** create more precise reports ([#1337](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1337)) ([e79ff9a](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/e79ff9ac602d85bf999686b018de6ace3a7bee36)), closes [#000](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/000)
9
21
 
10
22
  ## [0.59.1](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.59.0...v0.59.1) (2025-10-30)
11
23
 
package/README.md CHANGED
@@ -28,13 +28,12 @@ npm install eslint eslint-plugin-package-json --save-dev
28
28
 
29
29
  ## Usage
30
30
 
31
- ### Config
31
+ ### Recommended Config
32
32
 
33
33
  This plugin's recommended configuration enables its rules on `**/package.json` files, parsing them with [`jsonc-eslint-parser`](https://github.com/ota-meshi/jsonc-eslint-parser).
34
34
 
35
- In your ESLint configuration file:
36
-
37
35
  ```ts
36
+ // eslint.config.ts
38
37
  import packageJson from "eslint-plugin-package-json";
39
38
 
40
39
  export default [
@@ -46,6 +45,7 @@ export default [
46
45
  If you want to override the recommended rules:
47
46
 
48
47
  ```ts
48
+ // eslint.config.ts
49
49
  import packageJson from "eslint-plugin-package-json";
50
50
 
51
51
  export default [
@@ -61,7 +61,23 @@ export default [
61
61
 
62
62
  See [ESLint's _Configuration Files_ guide](https://eslint.org/docs/latest/use/configure/configuration-files-new) for details on how to customize your rules and other config settings.
63
63
 
64
- ### Legacy Config (deprecated)
64
+ ### Stylistic Config
65
+
66
+ The stylistic configuration enables sets up the parser and files similar to the recommended config, but includes rules that are more opinionated about the style of a package.json.
67
+ This can be used in addition to the recommended config, or on its own.
68
+
69
+ ```ts
70
+ // eslint.config.ts
71
+ import packageJson from "eslint-plugin-package-json";
72
+
73
+ export default [
74
+ // your other ESLint configurations
75
+ packageJson.configs.recommended,
76
+ packageJson.configs.stylistic,
77
+ ];
78
+ ```
79
+
80
+ ### Legacy Recommended Config (deprecated)
65
81
 
66
82
  Usage with ESLint's legacy ("eslintrc") format requires also installing [`jsonc-eslint-parser`](https://github.com/ota-meshi/jsonc-eslint-parser):
67
83
 
@@ -160,13 +176,14 @@ The default settings don't conflict, and Prettier plugins can quickly fix up ord
160
176
  πŸ’Ό Configurations enabled in.\
161
177
  βœ”οΈ Set in the `legacy-recommended` configuration.\
162
178
  βœ… Set in the `recommended` configuration.\
179
+ 🎨 Set in the `stylistic` configuration.\
163
180
  πŸ”§ Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
164
181
  πŸ’‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\
165
182
  ❌ Deprecated.
166
183
 
167
184
  | NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | πŸ”§ | πŸ’‘ | ❌ |
168
185
  | :------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | :--- | :- | :- | :- |
169
- | [exports-subpaths-style](docs/rules/exports-subpaths-style.md) | Enforce consistent format for the exports field (implicit or explicit subpaths). | | πŸ”§ | | |
186
+ | [exports-subpaths-style](docs/rules/exports-subpaths-style.md) | Enforce consistent format for the exports field (implicit or explicit subpaths). | 🎨 | πŸ”§ | | |
170
187
  | [no-empty-fields](docs/rules/no-empty-fields.md) | Reports on unnecessary empty arrays and objects. | βœ”οΈ βœ… | | πŸ’‘ | |
171
188
  | [no-redundant-files](docs/rules/no-redundant-files.md) | Prevents adding unnecessary / redundant files. | βœ”οΈ βœ… | | πŸ’‘ | |
172
189
  | [order-properties](docs/rules/order-properties.md) | Package properties must be declared in standard order | βœ”οΈ βœ… | πŸ”§ | | |
@@ -188,6 +205,7 @@ The default settings don't conflict, and Prettier plugins can quickly fix up ord
188
205
  | [require-types](docs/rules/require-types.md) | Requires the `types` property to be present. | | | | |
189
206
  | [require-version](docs/rules/require-version.md) | Requires the `version` property to be present. | βœ”οΈ βœ… | | | |
190
207
  | [restrict-dependency-ranges](docs/rules/restrict-dependency-ranges.md) | Restricts the range of dependencies to allow or disallow specific types of ranges. | | | πŸ’‘ | |
208
+ | [scripts-name-casing](docs/rules/scripts-name-casing.md) | Enforce that names for `scripts` are in kebab case (optionally separated by colons). | 🎨 | | πŸ’‘ | |
191
209
  | [sort-collections](docs/rules/sort-collections.md) | Selected collections must be in a consistent order (lexicographical for most; lifecycle-aware for scripts). | βœ”οΈ βœ… | πŸ”§ | | |
192
210
  | [unique-dependencies](docs/rules/unique-dependencies.md) | Checks a dependency isn't specified more than once (i.e. in `dependencies` and `devDependencies`) | βœ”οΈ βœ… | | πŸ’‘ | |
193
211
  | [valid-author](docs/rules/valid-author.md) | Enforce that the `author` property is valid. | βœ”οΈ βœ… | | | |
package/lib/index.d.ts CHANGED
@@ -30,6 +30,19 @@ declare const configs: {
30
30
  }];
31
31
  };
32
32
  };
33
+ stylistic: {
34
+ files: string[];
35
+ languageOptions: {
36
+ parser: typeof jsonc_eslint_parser0;
37
+ };
38
+ name: string;
39
+ plugins: {
40
+ readonly "package-json": eslint0.ESLint.Plugin;
41
+ };
42
+ rules: {
43
+ [k: string]: "error";
44
+ };
45
+ };
33
46
  };
34
47
  //#endregion
35
48
  export { type PackageJsonPluginSettings, configs, plugin as default, rules };
package/lib/plugin.d.ts CHANGED
@@ -30,6 +30,19 @@ declare const plugin: {
30
30
  }];
31
31
  };
32
32
  };
33
+ stylistic: {
34
+ files: string[];
35
+ languageOptions: {
36
+ parser: typeof parserJsonc;
37
+ };
38
+ name: string;
39
+ plugins: {
40
+ readonly "package-json": ESLint.Plugin;
41
+ };
42
+ rules: {
43
+ [k: string]: "error";
44
+ };
45
+ };
33
46
  };
34
47
  meta: {
35
48
  name: string;
package/lib/plugin.js CHANGED
@@ -5,16 +5,17 @@ import { rule as rule$3 } from "./rules/order-properties.js";
5
5
  import { rule as rule$4 } from "./rules/repository-shorthand.js";
6
6
  import { rules } from "./rules/require-properties.js";
7
7
  import { rule as rule$5 } from "./rules/restrict-dependency-ranges.js";
8
- import { rule as rule$6 } from "./rules/sort-collections.js";
9
- import { rule as rule$7 } from "./rules/unique-dependencies.js";
10
- import { rule as rule$8 } from "./rules/valid-author.js";
11
- import { rule as rule$9 } from "./rules/valid-bin.js";
12
- import { rule as rule$10 } from "./rules/valid-local-dependency.js";
13
- import { rule as rule$11 } from "./rules/valid-name.js";
14
- import { rule as rule$12 } from "./rules/valid-package-definition.js";
8
+ import { rule as rule$6 } from "./rules/scripts-name-casing.js";
9
+ import { rule as rule$7 } from "./rules/sort-collections.js";
10
+ import { rule as rule$8 } from "./rules/unique-dependencies.js";
11
+ import { rule as rule$9 } from "./rules/valid-author.js";
12
+ import { rule as rule$10 } from "./rules/valid-bin.js";
13
+ import { rule as rule$11 } from "./rules/valid-local-dependency.js";
14
+ import { rule as rule$12 } from "./rules/valid-name.js";
15
+ import { rule as rule$13 } from "./rules/valid-package-definition.js";
15
16
  import { rules as rules$1 } from "./rules/valid-properties.js";
16
- import { rule as rule$13 } from "./rules/valid-repository-directory.js";
17
- import { rule as rule$14 } from "./rules/valid-version.js";
17
+ import { rule as rule$14 } from "./rules/valid-repository-directory.js";
18
+ import { rule as rule$15 } from "./rules/valid-version.js";
18
19
  import { createRequire } from "node:module";
19
20
  import * as parserJsonc from "jsonc-eslint-parser";
20
21
 
@@ -28,22 +29,24 @@ const rules$2 = {
28
29
  ...rules,
29
30
  "repository-shorthand": rule$4,
30
31
  "restrict-dependency-ranges": rule$5,
31
- "sort-collections": rule$6,
32
- "unique-dependencies": rule$7,
32
+ "scripts-name-casing": rule$6,
33
+ "sort-collections": rule$7,
34
+ "unique-dependencies": rule$8,
33
35
  ...rules$1,
34
- "valid-author": rule$8,
35
- "valid-bin": rule$9,
36
- "valid-local-dependency": rule$10,
37
- "valid-name": rule$11,
38
- "valid-package-definition": rule$12,
39
- "valid-repository-directory": rule$13,
40
- "valid-version": rule$14
36
+ "valid-author": rule$9,
37
+ "valid-bin": rule$10,
38
+ "valid-local-dependency": rule$11,
39
+ "valid-name": rule$12,
40
+ "valid-package-definition": rule$13,
41
+ "valid-repository-directory": rule$14,
42
+ "valid-version": rule$15
41
43
  };
42
- const baseRecommendedRules = { ...Object.fromEntries(Object.entries(rules$2).filter(([, rule$15]) => rule$15.meta.docs?.recommended).map(([name$1]) => ["package-json/" + name$1, "error"])) };
44
+ const baseRecommendedRules = { ...Object.fromEntries(Object.entries(rules$2).filter(([, rule$16]) => rule$16.meta.docs?.recommended).map(([name$1]) => ["package-json/" + name$1, "error"])) };
43
45
  const recommendedRules = {
44
46
  ...baseRecommendedRules,
45
47
  "package-json/valid-package-definition": ["error", { ignoreProperties: Object.entries(baseRecommendedRules).filter(([name$1]) => name$1.startsWith("package-json/valid-") && name$1 !== "package-json/valid-package-definition").map(([name$1]) => name$1.replace("package-json/valid-", "")) }]
46
48
  };
49
+ const stylisticRules = { ...Object.fromEntries(Object.entries(rules$2).filter(([, rule$16]) => rule$16.meta.docs?.category === "Stylistic").map(([name$1]) => ["package-json/" + name$1, "error"])) };
47
50
  const plugin = {
48
51
  configs: {
49
52
  "legacy-recommended": {
@@ -58,6 +61,15 @@ const plugin = {
58
61
  return plugin;
59
62
  } },
60
63
  rules: recommendedRules
64
+ },
65
+ stylistic: {
66
+ files: ["**/package.json"],
67
+ languageOptions: { parser: parserJsonc },
68
+ name: "package-json/stylistic",
69
+ plugins: { get "package-json"() {
70
+ return plugin;
71
+ } },
72
+ rules: stylisticRules
61
73
  }
62
74
  },
63
75
  meta: {
@@ -46,7 +46,7 @@ const rule = createRule({
46
46
  meta: {
47
47
  defaultOptions: [{ prefer: "explicit" }],
48
48
  docs: {
49
- category: "Best Practices",
49
+ category: "Stylistic",
50
50
  description: "Enforce consistent format for the exports field (implicit or explicit subpaths).",
51
51
  recommended: false
52
52
  },
@@ -0,0 +1,6 @@
1
+ import { PackageJsonRuleModule } from "../createRule.js";
2
+
3
+ //#region src/rules/scripts-name-casing.d.ts
4
+ declare const rule: PackageJsonRuleModule<[], []>;
5
+ //#endregion
6
+ export { rule };
@@ -0,0 +1,43 @@
1
+ import { createRule } from "../createRule.js";
2
+ import { kebabCase } from "change-case";
3
+
4
+ //#region src/rules/scripts-name-casing.ts
5
+ const rule = createRule({
6
+ create(context) {
7
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=scripts]"(node) {
8
+ if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
9
+ const key = property.key;
10
+ const kebabCaseKey = key.value.split(":").map((segment) => kebabCase(segment)).join(":");
11
+ if (kebabCaseKey !== key.value) context.report({
12
+ data: { property: key.value },
13
+ messageId: "invalidCase",
14
+ node: key,
15
+ suggest: [{
16
+ data: { property: key.value },
17
+ fix: (fixer) => {
18
+ return fixer.replaceText(key, JSON.stringify(kebabCaseKey));
19
+ },
20
+ messageId: "convertToKebabCase"
21
+ }]
22
+ });
23
+ }
24
+ } };
25
+ },
26
+ meta: {
27
+ docs: {
28
+ category: "Stylistic",
29
+ description: "Enforce that names for `scripts` are in kebab case (optionally separated by colons)."
30
+ },
31
+ hasSuggestions: true,
32
+ messages: {
33
+ convertToKebabCase: "Convert {{ property }} to kebab case.",
34
+ invalidCase: "Script name {{ property }} should be in kebab case."
35
+ },
36
+ schema: [],
37
+ type: "suggestion"
38
+ },
39
+ name: "scripts-name-casing"
40
+ });
41
+
42
+ //#endregion
43
+ export { rule };
@@ -1,7 +1,7 @@
1
1
  import { createRule } from "../createRule.js";
2
2
  import { formatErrors } from "../utils/formatErrors.js";
3
- import { validateBin } from "package-json-validator";
4
3
  import { kebabCase } from "change-case";
4
+ import { validateBin } from "package-json-validator";
5
5
 
6
6
  //#region src/rules/valid-bin.ts
7
7
  const rule = createRule({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "0.60.0",
3
+ "version": "0.62.0",
4
4
  "description": "Rules for consistent, readable, and valid package.json files. πŸ—‚οΈ",
5
5
  "homepage": "https://github.com/JoshuaKGoldberg/eslint-plugin-package-json#readme",
6
6
  "bugs": {