@dvukovic/style-guide 0.3.96 → 0.3.98

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.
Files changed (58) hide show
  1. package/README.md +93 -159
  2. package/package.json +16 -16
  3. package/src/cspell/base.txt +12 -0
  4. package/src/eslint/configs/core.js +42 -30
  5. package/src/eslint/configs/core.test.js +4 -4
  6. package/src/eslint/configs/jest.js +26 -3
  7. package/src/eslint/configs/jest.test.js +3 -3
  8. package/src/eslint/configs/mobx.js +15 -3
  9. package/src/eslint/configs/mobx.test.js +3 -3
  10. package/src/eslint/configs/next.js +15 -3
  11. package/src/eslint/configs/next.test.js +3 -3
  12. package/src/eslint/configs/node.js +16 -4
  13. package/src/eslint/configs/node.test.js +3 -3
  14. package/src/eslint/configs/playwright.js +26 -3
  15. package/src/eslint/configs/playwright.test.js +3 -3
  16. package/src/eslint/configs/react.js +16 -4
  17. package/src/eslint/configs/react.test.js +3 -3
  18. package/src/eslint/configs/storybook.js +15 -3
  19. package/src/eslint/configs/storybook.test.js +3 -3
  20. package/src/eslint/configs/typescript-strict.js +14 -2
  21. package/src/eslint/configs/typescript-strict.test.js +6 -4
  22. package/src/eslint/configs/typescript.js +37 -4
  23. package/src/eslint/configs/typescript.test.js +6 -4
  24. package/src/eslint/configs/vitest.js +26 -3
  25. package/src/eslint/configs/vitest.test.js +3 -3
  26. package/src/eslint/index.js +25 -0
  27. package/src/eslint/plugins/dvukovic.js +15 -0
  28. package/src/eslint/plugins/es-x.js +7 -6
  29. package/src/eslint/plugins/eslint-comments.js +4 -6
  30. package/src/eslint/plugins/eslint.js +9 -3
  31. package/src/eslint/plugins/eslint.test.js +42 -0
  32. package/src/eslint/plugins/import-x.js +10 -6
  33. package/src/eslint/plugins/jest.js +4 -5
  34. package/src/eslint/plugins/mobx.js +4 -5
  35. package/src/eslint/plugins/n.js +4 -6
  36. package/src/eslint/plugins/next.js +4 -5
  37. package/src/eslint/plugins/playwright.js +4 -5
  38. package/src/eslint/plugins/promise.js +4 -5
  39. package/src/eslint/plugins/react-hooks.js +4 -5
  40. package/src/eslint/plugins/react.js +4 -5
  41. package/src/eslint/plugins/rimac.js +4 -5
  42. package/src/eslint/plugins/security-node.js +4 -5
  43. package/src/eslint/plugins/simple-import-sort.js +4 -5
  44. package/src/eslint/plugins/sonarjs.js +261 -37
  45. package/src/eslint/plugins/sort-destructure-keys.js +4 -5
  46. package/src/eslint/plugins/sort-keys-fix.js +4 -5
  47. package/src/eslint/plugins/storybook.js +4 -5
  48. package/src/eslint/plugins/stylistic.js +4 -5
  49. package/src/eslint/plugins/typescript-eslint.js +4 -5
  50. package/src/eslint/plugins/typescript-sort-keys.js +4 -5
  51. package/src/eslint/plugins/unicorn.js +4 -5
  52. package/src/eslint/plugins/unused-imports.js +4 -5
  53. package/src/eslint/plugins/vitest.js +4 -5
  54. package/src/eslint/rules/no-commented-out-code/no-commented-out-code.js +80 -0
  55. package/src/eslint/rules/no-commented-out-code/no-commented-out-code.test.js +89 -0
  56. package/src/eslint/rules/no-commented-out-code/no-commented-out-code.utils.js +119 -0
  57. package/src/eslint/types.js +19 -0
  58. package/src/eslint/plugins/etc.js +0 -3
@@ -0,0 +1,89 @@
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-commented-out-code", () => {
20
+ test("detects commented-out code", async () => {
21
+ const code = `// const x = 1\nconst y = 2\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-commented-out-code"
26
+ })
27
+
28
+ expect(errors?.length).toBe(1)
29
+ })
30
+
31
+ test("detects multi-line commented-out code", async () => {
32
+ const code = `// function foo() {
33
+ // return 1
34
+ // }
35
+ const y = 2
36
+ `
37
+
38
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
39
+ const errors = results[0]?.messages.filter((message) => {
40
+ return message.ruleId === "dvukovic/no-commented-out-code"
41
+ })
42
+
43
+ expect(errors?.length).toBe(1)
44
+ })
45
+
46
+ test("detects block commented-out code", async () => {
47
+ const code = `/* const x = 1 */\nconst y = 2\n`
48
+
49
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
50
+ const errors = results[0]?.messages.filter((message) => {
51
+ return message.ruleId === "dvukovic/no-commented-out-code"
52
+ })
53
+
54
+ expect(errors?.length).toBe(1)
55
+ })
56
+
57
+ test("allows regular comments", async () => {
58
+ const code = `// This is a regular comment\nconst y = 2\n`
59
+
60
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
61
+ const errors = results[0]?.messages.filter((message) => {
62
+ return message.ruleId === "dvukovic/no-commented-out-code"
63
+ })
64
+
65
+ expect(errors?.length).toBe(0)
66
+ })
67
+
68
+ test("allows TODO comments", async () => {
69
+ const code = `// TODO: fix this later\nconst y = 2\n`
70
+
71
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
72
+ const errors = results[0]?.messages.filter((message) => {
73
+ return message.ruleId === "dvukovic/no-commented-out-code"
74
+ })
75
+
76
+ expect(errors).toHaveLength(0)
77
+ })
78
+
79
+ test("allows region comments", async () => {
80
+ const code = `// #region\nconst y = 2\n// #endregion\n`
81
+
82
+ const results = await eslint.lintText(code, { filePath: "test.ts" })
83
+ const errors = results[0]?.messages.filter((message) => {
84
+ return message.ruleId === "dvukovic/no-commented-out-code"
85
+ })
86
+
87
+ expect(errors).toHaveLength(0)
88
+ })
89
+ })
@@ -0,0 +1,119 @@
1
+ export function isExpressionOrIdentifierOrLiteral(node) {
2
+ if (node.type === "Identifier") {
3
+ return true
4
+ }
5
+
6
+ if (node.type === "Literal") {
7
+ return true
8
+ }
9
+
10
+ if (node.type === "BinaryExpression") {
11
+ return (
12
+ isExpressionOrIdentifierOrLiteral(node.left) &&
13
+ isExpressionOrIdentifierOrLiteral(node.right)
14
+ )
15
+ }
16
+
17
+ return false
18
+ }
19
+
20
+ export function hasEmptyBody(program) {
21
+ return program.type === "Program" && program.body.length === 0
22
+ }
23
+
24
+ export function hasExpressionBody(program) {
25
+ return (
26
+ program.type === "Program" &&
27
+ program.body.every((statement) => {
28
+ return (
29
+ statement.type === "ExpressionStatement" &&
30
+ isExpressionOrIdentifierOrLiteral(statement.expression)
31
+ )
32
+ })
33
+ )
34
+ }
35
+
36
+ export function hasLabeledStatementBody(program) {
37
+ return (
38
+ program.type === "Program" &&
39
+ program.body.length === 1 &&
40
+ program.body[0]?.type === "LabeledStatement"
41
+ )
42
+ }
43
+
44
+ export function isRegionComment(content) {
45
+ return /\s*#(end)?region/.test(content)
46
+ }
47
+
48
+ export function toBlocks(comments) {
49
+ const blocks = []
50
+ let prevLine
51
+
52
+ for (const comment of comments) {
53
+ if (comment.type === "Block") {
54
+ blocks.push({
55
+ content: comment.value.replace(/^\s*\*/, "").replaceAll(/\n\s*\*/g, "\n"),
56
+ loc: { ...comment.loc },
57
+ })
58
+ prevLine = undefined
59
+ } else if (comment.type === "Line") {
60
+ if (prevLine && prevLine.loc.start.line === comment.loc.start.line - 1) {
61
+ const previousBlock = blocks.at(-1)
62
+
63
+ previousBlock.content = `${previousBlock.content}\n${comment.value}`
64
+ previousBlock.loc.end = comment.loc.end
65
+ } else {
66
+ blocks.push({
67
+ content: comment.value,
68
+ loc: { ...comment.loc },
69
+ })
70
+ }
71
+
72
+ prevLine = comment
73
+ } else {
74
+ prevLine = undefined
75
+ }
76
+ }
77
+
78
+ return blocks
79
+ }
80
+
81
+ export function wrapContent(content, node) {
82
+ switch (node?.type) {
83
+ case "ArrayExpression": {
84
+ return `let wrapper = [${content}]`
85
+ }
86
+
87
+ case "ClassBody": {
88
+ return `class Wrapper { ${content} }`
89
+ }
90
+
91
+ case "ImportDeclaration": {
92
+ return `import { ${content} } from "wrapper"`
93
+ }
94
+
95
+ case "ObjectExpression": {
96
+ return `let wrapper = { ${content} }`
97
+ }
98
+
99
+ case "FunctionDeclaration": {
100
+ return `function wrapper(${content}) {}`
101
+ }
102
+
103
+ case "SwitchStatement": {
104
+ return `switch (wrapper) { ${content} }`
105
+ }
106
+
107
+ case "TSInterfaceBody": {
108
+ return `interface Wrapper { ${content} }`
109
+ }
110
+
111
+ case "TSTypeLiteral": {
112
+ return `type Wrapper = { ${content} }`
113
+ }
114
+
115
+ default: {
116
+ return null
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @typedef {Object} ConfigOptions
3
+ * @property {boolean} [replace=false] - If true, replaces default config entirely with custom
4
+ * configs. Default is `false`
5
+ * @property {any[]} [configs=[]] - Additional configs to append or use as replacement. Default is
6
+ * `[]`
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} TypeScriptConfigOptions
11
+ * @property {boolean} [replace=false] - If true, replaces default config entirely with custom
12
+ * configs. Default is `false`
13
+ * @property {any[]} [configs=[]] - Additional configs to append or use as replacement. Default is
14
+ * `[]`
15
+ * @property {string} [tsconfigPath="./tsconfig.json"] - Path to tsconfig.json file. Default is
16
+ * `"./tsconfig.json"`
17
+ */
18
+
19
+ export {}
@@ -1,3 +0,0 @@
1
- const plugin = {}
2
-
3
- export default plugin