@fabriziosalmi/slopless 1.4.1
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/LICENSE +21 -0
- package/README.md +142 -0
- package/dist/engine/api.d.ts +16 -0
- package/dist/engine/api.js +543 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +590 -0
- package/package.json +59 -0
- package/rules/VBC-001.yaml +33 -0
- package/rules/VBC-002.yaml +13 -0
- package/rules/VBC-003.yaml +36 -0
- package/rules/VBC-004.yaml +33 -0
- package/rules/VBC-005.yaml +24 -0
- package/rules/VBC-006.yaml +16 -0
- package/rules/VBC-007.yaml +28 -0
- package/rules/VBC-008.yaml +21 -0
- package/rules/VBC-009.yaml +24 -0
- package/rules/VBC-010.yaml +24 -0
- package/rules/VBC-011.yaml +21 -0
- package/rules/VBC-012.yaml +21 -0
- package/rules/VBC-013.yaml +17 -0
- package/rules/VBC-014.yaml +15 -0
- package/rules/VBC-015.yaml +40 -0
- package/rules/VBC-016.yaml +21 -0
- package/rules/VBC-017.yaml +23 -0
- package/rules/VBC-018.yaml +19 -0
- package/rules/VBC-019.yaml +42 -0
- package/rules/VBC-020.yaml +22 -0
- package/rules/VBC-021.yaml +22 -0
- package/rules/VBC-022.yaml +21 -0
- package/rules/VBC-023.yaml +22 -0
- package/rules/VBC-024.yaml +26 -0
- package/rules/VBC-025.yaml +13 -0
- package/rules/VBC-026.yaml +17 -0
- package/rules/VBC-027.yaml +27 -0
- package/rules/VBC-028.yaml +18 -0
- package/rules/VBC-029.yaml +22 -0
- package/rules/VBC-030.yaml +22 -0
- package/rules/VBC-032.yaml +20 -0
- package/rules/VBC-033.yaml +26 -0
- package/rules/VBC-034.yaml +41 -0
- package/rules/VBC-035.yaml +30 -0
- package/rules/VBC-039.yaml +18 -0
- package/rules/VBC-042.yaml +26 -0
- package/rules/VBC-045.yaml +13 -0
- package/rules/VBC-046.yaml +13 -0
- package/rules/VBC-048.yaml +23 -0
- package/rules/VBC-049.yaml +19 -0
- package/rules/VBC-051.yaml +23 -0
- package/rules/VBC-052.yaml +19 -0
- package/rules/VBC-053.yaml +19 -0
- package/rules/VBC-054.yaml +29 -0
- package/rules/VBC-056.yaml +28 -0
- package/rules/VBC-057.yaml +18 -0
- package/rules/VBC-058.yaml +18 -0
- package/rules/VBC-059.yaml +21 -0
- package/rules/VBC-063-B.yaml +15 -0
- package/rules/VBC-063.yaml +18 -0
- package/rules/VBC-065.yaml +33 -0
- package/rules/VBC-066.yaml +16 -0
- package/rules/VBC-068.yaml +21 -0
- package/rules/VBC-070.yaml +19 -0
- package/rules/VBC-077.yaml +35 -0
- package/rules/VBC-079.yaml +18 -0
- package/rules/VBC-080.yaml +18 -0
- package/rules/VBC-084.yaml +22 -0
- package/rules/VBC-086.yaml +22 -0
- package/rules/VBC-090.yaml +28 -0
- package/rules/VBC-096.yaml +19 -0
- package/rules/VBC-097.yaml +21 -0
- package/rules/VBC-098.yaml +18 -0
- package/rules/VBC-101.yaml +23 -0
- package/rules/VBC-102.yaml +20 -0
- package/rules/VBC-103.yaml +35 -0
- package/rules/VBC-104.yaml +24 -0
- package/rules/VBC-106.yaml +14 -0
- package/rules/VBC-112.yaml +20 -0
- package/rules/VBC-113.yaml +19 -0
- package/rules/VBC-117.yaml +21 -0
- package/rules/VBC-123.yaml +29 -0
- package/rules/VBC-131.yaml +20 -0
- package/rules/VBC-150.yaml +27 -0
- package/rules/VBC-153.yaml +21 -0
- package/rules/VBC-158.yaml +16 -0
- package/rules/VBC-161.yaml +27 -0
- package/rules/VBC-172.yaml +25 -0
- package/rules/VBC-197.yaml +22 -0
- package/rules/VBC-201.yaml +35 -0
- package/rules/VBC-206.yaml +19 -0
- package/rules/VBC-208.yaml +27 -0
- package/rules/VBC-212.yaml +19 -0
- package/rules/VBC-215.yaml +24 -0
- package/rules/VBC-305.yaml +20 -0
- package/rules/VBC-324.yaml +24 -0
- package/rules/VBC-334.yaml +23 -0
- package/rules/VBC-338.yaml +32 -0
- package/rules/VBC-340.yaml +22 -0
- package/rules/VBC-344.yaml +19 -0
- package/rules/VBC-347.yaml +21 -0
- package/rules/VBC-348.yaml +19 -0
- package/rules/VBC-385.yaml +21 -0
- package/rules/VBC-398.yaml +22 -0
- package/rules/VBC-401.yaml +12 -0
- package/rules/VBC-414.yaml +23 -0
- package/rules/VBC-421.yaml +20 -0
- package/rules/VBC-501.yaml +18 -0
- package/rules/VBC-502.yaml +23 -0
- package/rules/VBC-503.yaml +18 -0
- package/rules/VBC-504.yaml +20 -0
- package/rules/VBC-800.yaml +17 -0
- package/rules/VBC-901.yaml +48 -0
- package/rules/VBC-902.yaml +19 -0
- package/rules/VBC-903.yaml +17 -0
- package/rules/VBC-904.yaml +21 -0
- package/rules/VBC-905.yaml +17 -0
- package/rules/VBC-906.yaml +29 -0
- package/rules/VBC-907.yaml +24 -0
- package/rules/VBC-908.yaml +22 -0
- package/rules/VBC-909.yaml +21 -0
- package/rules/VBC-910.yaml +18 -0
- package/rules/VBC-911.yaml +21 -0
- package/rules/VBC-913.yaml +30 -0
- package/rules/VBC-914.yaml +31 -0
- package/rules/VBC-915.yaml +19 -0
- package/rules/VBC-916.yaml +24 -0
- package/rules/VBC-917.yaml +21 -0
- package/rules/VBC-918.yaml +22 -0
- package/rules/VBC-920.yaml +20 -0
- package/rules/VBC-921.yaml +45 -0
- package/rules/VBC-922.yaml +15 -0
- package/rules/VBC-923.yaml +15 -0
- package/rules/VBC-924.yaml +12 -0
- package/rules/VBC-925.yaml +14 -0
- package/rules/VBC-926.yaml +14 -0
- package/rules/VBC-927.yaml +24 -0
- package/rules/VBC-928.yaml +25 -0
- package/rules/VBC-929.yaml +21 -0
- package/rules/VBC-930.yaml +16 -0
- package/rules/VBC-931.yaml +16 -0
- package/rules/VBC-932.yaml +16 -0
- package/rules/VBC-933.yaml +28 -0
- package/rules/VBC-934.yaml +24 -0
- package/rules/VBC-935.yaml +26 -0
- package/rules/VBC-936.yaml +24 -0
- package/rules/VBC-937.yaml +24 -0
- package/rules/VBC-938.yaml +23 -0
- package/rules/VBC-939.yaml +23 -0
- package/rules/VBC-940.yaml +30 -0
- package/rules/VBC-941.yaml +28 -0
- package/rules/VBC-942.yaml +23 -0
- package/rules/VBC-943.yaml +22 -0
- package/rules/VBC-944.yaml +26 -0
- package/rules/VBC-945.yaml +33 -0
- package/rules/VBC-946.yaml +26 -0
- package/rules/VBC-947.yaml +22 -0
- package/rules/VBC-948.yaml +26 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: VBC-025
|
|
2
|
+
name: missing-gitignore
|
|
3
|
+
severity: error
|
|
4
|
+
category: git
|
|
5
|
+
tags:
|
|
6
|
+
- git
|
|
7
|
+
- project-health
|
|
8
|
+
match:
|
|
9
|
+
git_check: missing_gitignore
|
|
10
|
+
message: >-
|
|
11
|
+
Missing .gitignore file. This often lead to committed dependencies or secrets.
|
|
12
|
+
tests:
|
|
13
|
+
external: 'git-checker.test.ts: needs a repository working tree'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
id: VBC-026
|
|
2
|
+
name: empty-file
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
- project-health
|
|
8
|
+
match:
|
|
9
|
+
ast_check:
|
|
10
|
+
type: empty-file
|
|
11
|
+
message: Empty code file detected. This clutters the repository.
|
|
12
|
+
tests:
|
|
13
|
+
fire:
|
|
14
|
+
- ''
|
|
15
|
+
- " \n"
|
|
16
|
+
quiet:
|
|
17
|
+
- export const answer = 42;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: VBC-027
|
|
2
|
+
name: parallax-overuse
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- performance
|
|
8
|
+
- accessibility
|
|
9
|
+
match:
|
|
10
|
+
regex: >-
|
|
11
|
+
(scrollY\s*\*\s*0\.[0-9]+|\.parallax\b|parallax[-_]container|data-parallax)
|
|
12
|
+
flags: i
|
|
13
|
+
file_types:
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- css
|
|
17
|
+
- scss
|
|
18
|
+
message: >-
|
|
19
|
+
Parallax scrolling effect detected at line {line}. Parallax effects can trigger vestibular
|
|
20
|
+
disorders (nausea, dizziness) in sensitive users, carry significant GPU cost, and break
|
|
21
|
+
on mobile. Respect prefers-reduced-motion and consider whether the effect adds genuine value.
|
|
22
|
+
tests:
|
|
23
|
+
fire:
|
|
24
|
+
- el.style.top = scrollY * 0.4 + "px";
|
|
25
|
+
- '.parallax { top: 0; }'
|
|
26
|
+
quiet:
|
|
27
|
+
- el.style.top = offset + "px";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-028
|
|
2
|
+
name: function-params-limit
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: function-params-limit
|
|
10
|
+
threshold: 5
|
|
11
|
+
message: >-
|
|
12
|
+
Function takes {count} parameters at line {line}, over the limit of {threshold}. Positional
|
|
13
|
+
arguments are easy to pass in the wrong order. Take an options object, or split the function.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- function build(a, b, c, d, e, f) { return a; }
|
|
17
|
+
quiet:
|
|
18
|
+
- function build(a, b) { return a + b; }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: VBC-029
|
|
2
|
+
name: glassmorphism-overuse
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- performance
|
|
8
|
+
match:
|
|
9
|
+
regex: backdrop-filter:\s*blur\(
|
|
10
|
+
file_types:
|
|
11
|
+
- css
|
|
12
|
+
- scss
|
|
13
|
+
- less
|
|
14
|
+
message: >-
|
|
15
|
+
backdrop-filter:blur() (glassmorphism) at line {line}. This effect forces GPU compositing
|
|
16
|
+
on every frame, severely impacting performance on low-end and mobile devices. It also frequently
|
|
17
|
+
reduces text contrast below accessibility thresholds. Use sparingly and test on real hardware.
|
|
18
|
+
tests:
|
|
19
|
+
fire:
|
|
20
|
+
- '.card { backdrop-filter: blur(12px); }'
|
|
21
|
+
quiet:
|
|
22
|
+
- '.card { background: var(--surface); }'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: VBC-030
|
|
2
|
+
name: confetti-overuse
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- performance
|
|
8
|
+
match:
|
|
9
|
+
regex: (confetti\(|canvas-confetti|party\.js|tsParticles\.load)
|
|
10
|
+
flags: i
|
|
11
|
+
file_types:
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
message: >-
|
|
15
|
+
Confetti or particle animation library detected at line {line}. Overusing celebration effects
|
|
16
|
+
devalues them and creates visual noise. Reserve confetti for genuinely significant milestones
|
|
17
|
+
(first purchase, account creation) rather than every successful action.
|
|
18
|
+
tests:
|
|
19
|
+
fire:
|
|
20
|
+
- 'confetti({ particleCount: 120 });'
|
|
21
|
+
quiet:
|
|
22
|
+
- showSuccessToast();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: VBC-032
|
|
2
|
+
name: css-important
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- style
|
|
7
|
+
- css
|
|
8
|
+
match:
|
|
9
|
+
regex: '!important'
|
|
10
|
+
file_types:
|
|
11
|
+
- css
|
|
12
|
+
- scss
|
|
13
|
+
- less
|
|
14
|
+
message: >-
|
|
15
|
+
Global '!important' detected in CSS at line {line}. This breaks the cascade.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- '.card { color: red !important; }'
|
|
19
|
+
quiet:
|
|
20
|
+
- '.card { color: red; }'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: VBC-033
|
|
2
|
+
name: placeholder-image-src
|
|
3
|
+
severity: error
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- slop
|
|
8
|
+
match:
|
|
9
|
+
regex: >-
|
|
10
|
+
(src|href)=['"](https?://)?(via\.placeholder\.com|picsum\.photos|placehold\.co|dummyimage\.com|loremflickr\.com|placekitten\.com)[^'"]*['"]
|
|
11
|
+
flags: i
|
|
12
|
+
file_types:
|
|
13
|
+
- html
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- tsx
|
|
17
|
+
- jsx
|
|
18
|
+
message: >-
|
|
19
|
+
Placeholder image service URL detected at line {line}. External placeholder services break
|
|
20
|
+
when the service is down, look unfinished, and represent content that was never completed.
|
|
21
|
+
Replace with real production images.
|
|
22
|
+
tests:
|
|
23
|
+
fire:
|
|
24
|
+
- <img src="https://via.placeholder.com/400" alt="x" />
|
|
25
|
+
quiet:
|
|
26
|
+
- <img src="/assets/hero.png" alt="Hero" />
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
id: VBC-034
|
|
2
|
+
name: http-not-https
|
|
3
|
+
severity: error
|
|
4
|
+
category: security
|
|
5
|
+
tags:
|
|
6
|
+
- security
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
http://(?!localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\]|test\b|example\.(?:com|org)|www\.w3\.org|schemas?\.|json-schema\.org|purl\.org|ns\.adobe|www\.apache\.org)
|
|
10
|
+
scan: strings
|
|
11
|
+
file_types:
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
- py
|
|
15
|
+
- html
|
|
16
|
+
exclude_files:
|
|
17
|
+
- '**/test/**'
|
|
18
|
+
- '**/tests/**'
|
|
19
|
+
- '**/__tests__/**'
|
|
20
|
+
- '**/testdata/**'
|
|
21
|
+
- '**/fixtures/**'
|
|
22
|
+
- '**/test_*.py'
|
|
23
|
+
- '**/*_test.py'
|
|
24
|
+
- '**/test.py'
|
|
25
|
+
- '**/conftest.py'
|
|
26
|
+
- '**/*_test.go'
|
|
27
|
+
- '**/*_bench.go'
|
|
28
|
+
- '**/*.test.*'
|
|
29
|
+
- '**/*.spec.*'
|
|
30
|
+
- '**/bench/**'
|
|
31
|
+
- '**/benchmark*'
|
|
32
|
+
- '**/*corpus*'
|
|
33
|
+
- '**/*payload*'
|
|
34
|
+
message: Insecure http:// link detected at line {line}. Use https:// instead.
|
|
35
|
+
tests:
|
|
36
|
+
fire:
|
|
37
|
+
- const api = 'http://api.example.com/v1';
|
|
38
|
+
quiet:
|
|
39
|
+
- const api = 'https://api.example.com/v1';
|
|
40
|
+
- const dev = 'http://localhost:3000';
|
|
41
|
+
- const svg = 'http://www.w3.org/2000/svg';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: VBC-035
|
|
2
|
+
name: aria-label-icon-button
|
|
3
|
+
severity: error
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- accessibility
|
|
7
|
+
match:
|
|
8
|
+
regex: <button\b(?![^>]*(?:aria-label|aria-labelledby|title))[^>]*>\s*<svg
|
|
9
|
+
multiline: true
|
|
10
|
+
file_types:
|
|
11
|
+
- html
|
|
12
|
+
- tsx
|
|
13
|
+
- jsx
|
|
14
|
+
message: >-
|
|
15
|
+
Icon-only button without aria-label at line {line}. A button containing only an SVG icon
|
|
16
|
+
has no accessible name, making it completely opaque to screen readers. Add aria-label="Descriptive
|
|
17
|
+
action" to every icon-only button.
|
|
18
|
+
tests:
|
|
19
|
+
fire:
|
|
20
|
+
- file: fixture.tsx
|
|
21
|
+
code: |
|
|
22
|
+
<button onClick={close}>
|
|
23
|
+
<svg viewBox="0 0 24 24" />
|
|
24
|
+
</button>
|
|
25
|
+
quiet:
|
|
26
|
+
- file: fixture.tsx
|
|
27
|
+
code: |
|
|
28
|
+
<button aria-label="Close" onClick={close}>
|
|
29
|
+
<svg viewBox="0 0 24 24" />
|
|
30
|
+
</button>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-039
|
|
2
|
+
name: use-eval
|
|
3
|
+
severity: error
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- security
|
|
7
|
+
match:
|
|
8
|
+
regex: eval\(
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Use of 'eval()' detected at line {line}. This is a massive security risk.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- eval(userInput);
|
|
17
|
+
quiet:
|
|
18
|
+
- JSON.parse(userInput);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
id: VBC-042
|
|
2
|
+
name: too-many-comments
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: (?:^[ \t]*//.*\n){10,}
|
|
9
|
+
flags: m
|
|
10
|
+
multiline: true
|
|
11
|
+
scan: all
|
|
12
|
+
file_types:
|
|
13
|
+
- js
|
|
14
|
+
- ts
|
|
15
|
+
- py
|
|
16
|
+
message: >-
|
|
17
|
+
Too many consecutive comment lines at line {line}. Code should be self-documenting.
|
|
18
|
+
tests:
|
|
19
|
+
fire:
|
|
20
|
+
- code: |
|
|
21
|
+
// filler comment line
|
|
22
|
+
repeat: 12
|
|
23
|
+
quiet:
|
|
24
|
+
- |
|
|
25
|
+
// one explanatory comment
|
|
26
|
+
const answer = 42;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: VBC-045
|
|
2
|
+
name: missing-license
|
|
3
|
+
severity: warning
|
|
4
|
+
category: git
|
|
5
|
+
tags:
|
|
6
|
+
- git
|
|
7
|
+
- project-health
|
|
8
|
+
match:
|
|
9
|
+
git_check: missing_license
|
|
10
|
+
message: >-
|
|
11
|
+
Missing LICENSE file. Every open source project should define its terms of use.
|
|
12
|
+
tests:
|
|
13
|
+
external: 'git-checker.test.ts: needs a repository working tree'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
id: VBC-046
|
|
2
|
+
name: binary-files-in-git
|
|
3
|
+
severity: warning
|
|
4
|
+
category: git
|
|
5
|
+
tags:
|
|
6
|
+
- git
|
|
7
|
+
- performance
|
|
8
|
+
match:
|
|
9
|
+
git_check: binary_file
|
|
10
|
+
message: >-
|
|
11
|
+
Binary file committed to Git. Large binaries should use Git LFS or be stored externally.
|
|
12
|
+
tests:
|
|
13
|
+
external: 'git-checker.test.ts: needs a staged file list'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: VBC-048
|
|
2
|
+
name: meaningless-variable-names
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
\b(?:let|const|var)\s+(?:temp|tmp|obj|variable|thing|stuff|foo|bar|baz|qux|myVar|test1|data2)\b
|
|
10
|
+
file_types:
|
|
11
|
+
- js
|
|
12
|
+
- ts
|
|
13
|
+
- py
|
|
14
|
+
message: >-
|
|
15
|
+
Meaningless variable name '{match}' detected at line {line}. Use descriptive names that
|
|
16
|
+
convey intent.
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- const temp = load();
|
|
20
|
+
- let thing = compute();
|
|
21
|
+
quiet:
|
|
22
|
+
- const invoiceTotal = load();
|
|
23
|
+
- const data = await response.json();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-049
|
|
2
|
+
name: magic-boolean
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: \b[a-zA-Z0-9_]+\((true|false)\s*,
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Magic boolean passed as first argument at line {line}. Use named parameters or a descriptive
|
|
14
|
+
variable.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- renderList(true, items);
|
|
18
|
+
quiet:
|
|
19
|
+
- 'renderList({ compact: true }, items);'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: VBC-051
|
|
2
|
+
name: mixed-casing
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
- style
|
|
8
|
+
match:
|
|
9
|
+
regex: >-
|
|
10
|
+
((?<![.'\"])\b[a-z]+_[a-z]+\b(?!\s*[:?]).*?\b[a-z]+[A-Z][a-z]+\b)|(\b[a-z]+[A-Z][a-z]+\b.*?(?<![.'\"])\b[a-z]+_[a-z]+\b(?!\s*[:?]))
|
|
11
|
+
file_types:
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
message: >-
|
|
15
|
+
snake_case and camelCase mixed at line {line}. Pick one convention per file. Object keys
|
|
16
|
+
are not reported: a wire format often dictates those names.
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- const user_name = userName;
|
|
20
|
+
quiet:
|
|
21
|
+
- const userName = firstName;
|
|
22
|
+
- 'max_tokens: Math.min(maxTokens, 1024),'
|
|
23
|
+
- 'const body = { used_tokens: usedTokens };'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-052
|
|
2
|
+
name: single-letter-variables
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: \b(?:let|const|var)\s+(?!(?:i|j|k|n|x|y|z|e|t|_)\b)[a-z]\b
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Single-letter variable name detected at line {line}. Use more descriptive names.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- const p = loadProfile();
|
|
17
|
+
quiet:
|
|
18
|
+
- const profile = loadProfile();
|
|
19
|
+
- for (const i of items) { use(i); }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-053
|
|
2
|
+
name: redundant-interpolation
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: '`\$\{[a-zA-Z0-9_]+\}`'
|
|
9
|
+
scan: all
|
|
10
|
+
file_types:
|
|
11
|
+
- js
|
|
12
|
+
- ts
|
|
13
|
+
message: >-
|
|
14
|
+
Redundant string interpolation detected at line {line}. Use the variable directly.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- const label = `${count}`;
|
|
18
|
+
quiet:
|
|
19
|
+
- const label = `${count} items`;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
id: VBC-054
|
|
2
|
+
name: unnecessary-else
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: \breturn\b[^\n]*;?\s*\n?\s*\}\s*else\s*\{
|
|
9
|
+
multiline: true
|
|
10
|
+
file_types:
|
|
11
|
+
- js
|
|
12
|
+
- ts
|
|
13
|
+
message: >-
|
|
14
|
+
Unnecessary 'else' after 'return' at line {line}. Remove the else and flatten the code.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- |
|
|
18
|
+
if (ready) {
|
|
19
|
+
return 1;
|
|
20
|
+
} else {
|
|
21
|
+
return 2;
|
|
22
|
+
}
|
|
23
|
+
quiet:
|
|
24
|
+
- |
|
|
25
|
+
if (ready) {
|
|
26
|
+
start();
|
|
27
|
+
} else {
|
|
28
|
+
stop();
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: VBC-056
|
|
2
|
+
name: stale-todo
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- docs
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
\b(?:TODO|FIXME|HACK)\b[^\n]{0,90}?\b(?:temporar\w+|for now|quick fix|before (?:launch|release|prod\w*)|remove
|
|
10
|
+
(?:this|later|before)|revisit|come back)\b
|
|
11
|
+
flags: i
|
|
12
|
+
scan: comments
|
|
13
|
+
file_types:
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- py
|
|
17
|
+
- sh
|
|
18
|
+
supersedes:
|
|
19
|
+
- VBC-907
|
|
20
|
+
- VBC-150
|
|
21
|
+
message: >-
|
|
22
|
+
Debt marker that admits it is temporary at line {line}. Temporary code that ships is permanent
|
|
23
|
+
code. Give it an owner and a deadline, or finish it.
|
|
24
|
+
tests:
|
|
25
|
+
fire:
|
|
26
|
+
- '// TODO: temporary shim until the new API lands'
|
|
27
|
+
quiet:
|
|
28
|
+
- '// TODO(fab): rework the cache key'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-057
|
|
2
|
+
name: use-any
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- typescript
|
|
7
|
+
match:
|
|
8
|
+
regex: :\s*any\b
|
|
9
|
+
file_types:
|
|
10
|
+
- ts
|
|
11
|
+
- tsx
|
|
12
|
+
message: >-
|
|
13
|
+
Avoid using 'any' type at line {line}. Use a more specific type or 'unknown'.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- 'function parse(input: any) { return input; }'
|
|
17
|
+
quiet:
|
|
18
|
+
- 'function parse(input: unknown) { return input; }'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-058
|
|
2
|
+
name: overly-long-variable-name
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: \b(let|const|var)\s+[a-zA-Z0-9_]{35,}\b
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Overly long variable name (>35 chars) detected at line {line}. This is getting too vibey.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- const theAbsolutelyEnormousConfigurationObject = {};
|
|
17
|
+
quiet:
|
|
18
|
+
- const config = {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: VBC-059
|
|
2
|
+
name: file-length-limit
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: file-length-limit
|
|
10
|
+
threshold: 500
|
|
11
|
+
message: >-
|
|
12
|
+
File is too long ({count} lines). Consider splitting it into smaller modules. Max recommended:
|
|
13
|
+
{threshold}.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- code: |
|
|
17
|
+
const line = 1;
|
|
18
|
+
repeat: 520
|
|
19
|
+
quiet:
|
|
20
|
+
- |
|
|
21
|
+
const line = 1;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
id: VBC-063-B
|
|
2
|
+
name: empty-block
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: empty-block
|
|
10
|
+
message: Empty block detected at line {line}. This code does nothing.
|
|
11
|
+
tests:
|
|
12
|
+
fire:
|
|
13
|
+
- function noop() {}
|
|
14
|
+
quiet:
|
|
15
|
+
- function run() { start(); }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-063
|
|
2
|
+
name: empty-else
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: else\s*\{\s*\}
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
- py
|
|
13
|
+
message: Empty else block detected at line {line}. This clutters the code.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- if (ready) { start(); } else {}
|
|
17
|
+
quiet:
|
|
18
|
+
- if (ready) { start(); } else { stop(); }
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: VBC-065
|
|
2
|
+
name: hadouken-nested-logic
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: nested-blocks-limit
|
|
10
|
+
threshold: 4
|
|
11
|
+
message: >-
|
|
12
|
+
Nested logic is {count} levels deep at line {line}, over the limit of {threshold}. Return
|
|
13
|
+
early, extract the inner block, or invert a condition.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- |
|
|
17
|
+
function deep(a) {
|
|
18
|
+
if (a) {
|
|
19
|
+
for (;;) {
|
|
20
|
+
while (a) {
|
|
21
|
+
if (a) {
|
|
22
|
+
switch (a) { default: break; }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
quiet:
|
|
29
|
+
- |
|
|
30
|
+
function shallow(a) {
|
|
31
|
+
if (a) { return 1; }
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
id: VBC-066
|
|
2
|
+
name: redundant-if-true
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: redundant-if-true
|
|
10
|
+
message: >-
|
|
11
|
+
Redundant 'if(true)' detected at line {line}. This logic is either debug code or unnecessary.
|
|
12
|
+
tests:
|
|
13
|
+
fire:
|
|
14
|
+
- if (true) { start(); }
|
|
15
|
+
quiet:
|
|
16
|
+
- if (ready) { start(); }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: VBC-068
|
|
2
|
+
name: overuse-ternary
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
\?(?![.:])[^\n]*?:[^\n]*?\?(?![.:])[^\n]*?:|\?(?![.:])[^\n]*?\?(?![.:])[^\n]*?:[^\n]*?:
|
|
10
|
+
file_types:
|
|
11
|
+
- js
|
|
12
|
+
- ts
|
|
13
|
+
message: >-
|
|
14
|
+
Chained or nested ternary at line {line}. Stacked conditionals are hard to read and hard
|
|
15
|
+
to debug; use an if/else block or a lookup table.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- 'const size = big ? ''lg'' : medium ? ''md'' : ''sm'';'
|
|
19
|
+
quiet:
|
|
20
|
+
- 'const size = big ? ''lg'' : ''sm'';'
|
|
21
|
+
- 'function f(a?: string, b?: number) {}'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-070
|
|
2
|
+
name: use-innerhtml
|
|
3
|
+
severity: error
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- security
|
|
7
|
+
match:
|
|
8
|
+
regex: \.innerHTML\s*=(?!=)
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Use of 'innerHTML' detected at line {line}. Use 'textContent' or a sanitizer to avoid XSS.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- el.innerHTML = markup;
|
|
17
|
+
quiet:
|
|
18
|
+
- el.textContent = text;
|
|
19
|
+
- if (el.innerHTML === "") { init(); }
|