@dvukovic/style-guide 0.3.107 → 0.3.109

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvukovic/style-guide",
3
- "version": "0.3.107",
3
+ "version": "0.3.109",
4
4
  "description": "My own style guide",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,12 +31,12 @@
31
31
  "dependencies": {
32
32
  "@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
33
33
  "@eslint/compat": "^2.0.0",
34
- "@next/eslint-plugin-next": "16.0.10",
34
+ "@next/eslint-plugin-next": "16.1.0",
35
35
  "@prettier/plugin-xml": "3.4.2",
36
36
  "@rimac-technology/eslint-plugin": "1.5.0",
37
37
  "@stylistic/eslint-plugin": "5.6.1",
38
- "@typescript-eslint/parser": "8.49.0",
39
- "@vitest/eslint-plugin": "1.5.2",
38
+ "@typescript-eslint/parser": "8.50.0",
39
+ "@vitest/eslint-plugin": "1.5.4",
40
40
  "eslint-plugin-es-x": "9.3.0",
41
41
  "eslint-plugin-import-x": "4.16.1",
42
42
  "eslint-plugin-jest": "29.4.0",
@@ -51,12 +51,12 @@
51
51
  "eslint-plugin-sonarjs": "3.0.5",
52
52
  "eslint-plugin-sort-destructure-keys": "2.0.0",
53
53
  "eslint-plugin-sort-keys-fix": "1.1.2",
54
- "eslint-plugin-storybook": "10.1.8",
54
+ "eslint-plugin-storybook": "10.1.10",
55
55
  "eslint-plugin-typescript-sort-keys": "3.3.0",
56
56
  "eslint-plugin-unicorn": "62.0.0",
57
57
  "eslint-plugin-unused-imports": "4.3.0",
58
58
  "globals": "16.5.0",
59
- "prettier-plugin-embed": "0.5.0",
59
+ "prettier-plugin-embed": "0.5.1",
60
60
  "prettier-plugin-jsdoc": "1.8.0",
61
61
  "prettier-plugin-packagejson": "2.5.20",
62
62
  "prettier-plugin-prisma": "5.0.0",
@@ -66,10 +66,10 @@
66
66
  "prettier-plugin-toml": "2.0.6",
67
67
  "stylelint-no-unused-selectors": "1.0.40",
68
68
  "stylelint-order": "7.0.0",
69
- "typescript-eslint": "8.49.0"
69
+ "typescript-eslint": "8.50.0"
70
70
  },
71
71
  "devDependencies": {
72
- "@storybook/react": "10.1.8",
72
+ "@storybook/react": "10.1.10",
73
73
  "@types/eslint": "9.6.1",
74
74
  "@types/jest": "30.0.0",
75
75
  "@types/node": "24.10.4",
@@ -81,10 +81,10 @@
81
81
  "prettier": "3.7.4",
82
82
  "react": "19.2.3",
83
83
  "release-it": "19.1.0",
84
- "storybook": "^10.1.8",
84
+ "storybook": "^10.1.10",
85
85
  "stylelint": "16.26.1",
86
86
  "typescript": "5.9.3",
87
- "vitest": "^4.0.15"
87
+ "vitest": "^4.0.16"
88
88
  },
89
89
  "peerDependencies": {
90
90
  "cspell": "9",
@@ -1,4 +1,5 @@
1
1
  import { noCommentedOutCode } from "../rules/no-commented-out-code/no-commented-out-code.js"
2
+ import { noT } from "../rules/no-t/no-t.js"
2
3
 
3
4
  /** @type {import("@eslint/config-helpers").Config} */
4
5
  export const dvukovic = {
@@ -6,10 +7,12 @@ export const dvukovic = {
6
7
  dvukovic: {
7
8
  rules: {
8
9
  "no-commented-out-code": noCommentedOutCode,
10
+ "no-t": noT,
9
11
  },
10
12
  },
11
13
  },
12
14
  rules: {
13
15
  "dvukovic/no-commented-out-code": "error",
16
+ "dvukovic/no-t": "error",
14
17
  },
15
18
  }
@@ -134,6 +134,7 @@ export const typescriptEslint = {
134
134
  ],
135
135
  "@typescript-eslint/no-use-before-define": "error",
136
136
  "@typescript-eslint/no-useless-constructor": "error",
137
+ "@typescript-eslint/no-useless-default-assignment": "error",
137
138
  "@typescript-eslint/no-useless-empty-export": "error",
138
139
  "@typescript-eslint/no-wrapper-object-types": "error",
139
140
  "@typescript-eslint/non-nullable-type-assertion-style": "error",
@@ -0,0 +1,43 @@
1
+ export const noT = {
2
+ create(context) {
3
+ const [{ prefix = "" } = {}] = context.options
4
+
5
+ return {
6
+ "TSTypeParameter > Identifier[name=/^.$/]"(node) {
7
+ context.report({
8
+ data: { name: node.name },
9
+ messageId: "forbidden",
10
+ node,
11
+ })
12
+ },
13
+ "TSTypeParameter > Identifier[name=/^.{2,}$/]"(node) {
14
+ if (prefix && !node.name.startsWith(prefix)) {
15
+ context.report({
16
+ data: { name: node.name, prefix },
17
+ messageId: "prefix",
18
+ node,
19
+ })
20
+ }
21
+ },
22
+ }
23
+ },
24
+ meta: {
25
+ docs: {
26
+ description: "Forbids single-character type parameters.",
27
+ },
28
+ messages: {
29
+ forbidden: `Single-character type parameters are forbidden. Choose a more descriptive name for "{{name}}"`,
30
+ prefix: `Type parameter "{{name}}" does not have prefix "{{prefix}}"`,
31
+ },
32
+ schema: [
33
+ {
34
+ additionalProperties: false,
35
+ properties: {
36
+ prefix: { type: "string" },
37
+ },
38
+ type: "object",
39
+ },
40
+ ],
41
+ type: "problem",
42
+ },
43
+ }
@@ -0,0 +1,85 @@
1
+ import { ESLint } from "eslint"
2
+ import tseslint from "typescript-eslint"
3
+
4
+ import { dvukovic } from "../../plugins/dvukovic.js"
5
+
6
+ const eslint = new ESLint({
7
+ overrideConfig: [
8
+ {
9
+ files: ["**/*.ts"],
10
+ languageOptions: {
11
+ parser: tseslint.parser,
12
+ },
13
+ },
14
+ dvukovic,
15
+ ],
16
+ overrideConfigFile: true,
17
+ })
18
+
19
+ describe("dvukovic/no-t", () => {
20
+ test("detects single-character type parameter", async () => {
21
+ const code = `function foo<T>(arg: T): T { return arg }\n`
22
+
23
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
24
+ const errors = results[0]?.messages.filter((message) => {
25
+ return message.ruleId === "dvukovic/no-t"
26
+ })
27
+
28
+ expect(errors?.length).toBe(1)
29
+ })
30
+
31
+ test("detects multiple single-character type parameters", async () => {
32
+ const code = `type Entry<K, V> = { key: K; value: V }\n`
33
+
34
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
35
+ const errors = results[0]?.messages.filter((message) => {
36
+ return message.ruleId === "dvukovic/no-t"
37
+ })
38
+
39
+ expect(errors?.length).toBe(2)
40
+ })
41
+
42
+ test("allows descriptive type parameters", async () => {
43
+ const code = `function foo<Element>(arg: Element): Element { return arg }\n`
44
+
45
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
46
+ const errors = results[0]?.messages.filter((message) => {
47
+ return message.ruleId === "dvukovic/no-t"
48
+ })
49
+
50
+ expect(errors?.length).toBe(0)
51
+ })
52
+
53
+ test("allows descriptive type parameters in type alias", async () => {
54
+ const code = `type Entry<Key, Value> = { key: Key; value: Value }\n`
55
+
56
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
57
+ const errors = results[0]?.messages.filter((message) => {
58
+ return message.ruleId === "dvukovic/no-t"
59
+ })
60
+
61
+ expect(errors?.length).toBe(0)
62
+ })
63
+
64
+ test("detects single-character in interface", async () => {
65
+ const code = `interface Container<T> { value: T }\n`
66
+
67
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
68
+ const errors = results[0]?.messages.filter((message) => {
69
+ return message.ruleId === "dvukovic/no-t"
70
+ })
71
+
72
+ expect(errors?.length).toBe(1)
73
+ })
74
+
75
+ test("detects single-character in class", async () => {
76
+ const code = `class Box<T> { constructor(public value: T) {} }\n`
77
+
78
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
79
+ const errors = results[0]?.messages.filter((message) => {
80
+ return message.ruleId === "dvukovic/no-t"
81
+ })
82
+
83
+ expect(errors?.length).toBe(1)
84
+ })
85
+ })