@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,35 @@
|
|
|
1
|
+
id: VBC-077
|
|
2
|
+
name: deceptive-function-name
|
|
3
|
+
severity: error
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
- semantic
|
|
8
|
+
match:
|
|
9
|
+
ast_check:
|
|
10
|
+
type: lying-function-names
|
|
11
|
+
message: >-
|
|
12
|
+
Lying function name detected: '{name}' implies a non-mutating action but contains side-effect
|
|
13
|
+
keywords (set, delete, update). This is major vibecoding.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- |
|
|
17
|
+
function getUser(id) {
|
|
18
|
+
this.cache.set(id, 1);
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
21
|
+
quiet:
|
|
22
|
+
- |
|
|
23
|
+
function getUser(id) {
|
|
24
|
+
return this.users[id];
|
|
25
|
+
}
|
|
26
|
+
- |
|
|
27
|
+
function getOffset(node) {
|
|
28
|
+
return node.dataset.offset;
|
|
29
|
+
}
|
|
30
|
+
- |
|
|
31
|
+
function getAll() {
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const x of this.buffer) out.push(x);
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-079
|
|
2
|
+
name: debugger-statements
|
|
3
|
+
severity: error
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: debugger;
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
debugger; statement found at line {line}. This should never reach production.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- debugger;
|
|
17
|
+
quiet:
|
|
18
|
+
- inspect(state);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-080
|
|
2
|
+
name: browser-alert
|
|
3
|
+
severity: error
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: \balert\(
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Avoid using alert() at line {line}. Use a modern UI notification system.
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- alert("saved");
|
|
17
|
+
quiet:
|
|
18
|
+
- showToast("saved");
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: VBC-084
|
|
2
|
+
name: long-line-limit
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: ^.{120,}$
|
|
9
|
+
scan: all
|
|
10
|
+
file_types:
|
|
11
|
+
- js
|
|
12
|
+
- ts
|
|
13
|
+
- py
|
|
14
|
+
- go
|
|
15
|
+
message: >-
|
|
16
|
+
Line is too long ({count} characters). Consider wrapping it. Max recommended: 120.
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- >-
|
|
20
|
+
const message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
|
21
|
+
quiet:
|
|
22
|
+
- const message = "short";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: VBC-086
|
|
2
|
+
name: target-blank-rel
|
|
3
|
+
severity: error
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- security
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
<a\b(?![^>]*\brel\s*=\s*["'{][^"'}]*(?:noopener|noreferrer))[^>]*\btarget\s*=\s*["'{]{0,2}_blank
|
|
10
|
+
multiline: true
|
|
11
|
+
file_types:
|
|
12
|
+
- html
|
|
13
|
+
- js
|
|
14
|
+
- ts
|
|
15
|
+
- tsx
|
|
16
|
+
message: target='_blank' without rel='noopener' detected at line {line}.
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- <a href="/x" target="_blank">docs</a>
|
|
20
|
+
quiet:
|
|
21
|
+
- <a href="/x" target="_blank" rel="noopener">docs</a>
|
|
22
|
+
- <a href="/x" rel="noreferrer" target="_blank">docs</a>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: VBC-090
|
|
2
|
+
name: passive-aggressive-comments
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- team-culture
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
(blame \w+|fix later|hope it works|idk why this works|this is cursed|wtf is this|no idea
|
|
10
|
+
why|pray it works|don't touch this|shouldn't work but|works on my machine)
|
|
11
|
+
flags: i
|
|
12
|
+
scan: comments
|
|
13
|
+
file_types:
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- py
|
|
17
|
+
- sh
|
|
18
|
+
- c
|
|
19
|
+
- cpp
|
|
20
|
+
- md
|
|
21
|
+
message: >-
|
|
22
|
+
Passive-aggressive or helpless comment '{match}' detected at line {line}. Replace with a
|
|
23
|
+
technical explanation of the actual constraint or a link to the relevant issue tracker ticket.
|
|
24
|
+
tests:
|
|
25
|
+
fire:
|
|
26
|
+
- // fix later, hope it works
|
|
27
|
+
quiet:
|
|
28
|
+
- // retries three times, then gives up
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-096
|
|
2
|
+
name: complex-regex-no-comment
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: /(?:[^/\n\\]|\\.){30,}/[dgimsuvy]*
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
message: >-
|
|
13
|
+
Long regular expression literal at line {line} with no explanation. Add a comment stating
|
|
14
|
+
what it matches, or build it from named parts.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- const re = /^[a-z0-9]+(?:[-_][a-z0-9]+)*@example\.com$/;
|
|
18
|
+
quiet:
|
|
19
|
+
- const re = /^\d+$/;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: VBC-097
|
|
2
|
+
name: br-tags-for-layout
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- html
|
|
7
|
+
- accessibility
|
|
8
|
+
match:
|
|
9
|
+
regex: <br\s*/?>(\s*<br\s*/?>)+
|
|
10
|
+
multiline: true
|
|
11
|
+
file_types:
|
|
12
|
+
- html
|
|
13
|
+
- js
|
|
14
|
+
- ts
|
|
15
|
+
- tsx
|
|
16
|
+
message: Multiple <br> tags used for layout. Use CSS margin or padding instead.
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- <p>one<br /><br />two</p>
|
|
20
|
+
quiet:
|
|
21
|
+
- <p>one<br />two</p>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
id: VBC-098
|
|
2
|
+
name: z-index-war
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- css
|
|
7
|
+
match:
|
|
8
|
+
regex: z-index\s*:\s*[0-9]{4,}
|
|
9
|
+
file_types:
|
|
10
|
+
- css
|
|
11
|
+
- scss
|
|
12
|
+
- less
|
|
13
|
+
message: Extremely high z-index value detected at line {line} (z-index wars).
|
|
14
|
+
tests:
|
|
15
|
+
fire:
|
|
16
|
+
- '.modal { z-index: 99999; }'
|
|
17
|
+
quiet:
|
|
18
|
+
- '.modal { z-index: 10; }'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
id: VBC-101
|
|
2
|
+
name: img-missing-alt
|
|
3
|
+
severity: error
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- accessibility
|
|
7
|
+
match:
|
|
8
|
+
regex: <img\b(?![^>]*\balt\s*=)[^>]*>
|
|
9
|
+
multiline: true
|
|
10
|
+
file_types:
|
|
11
|
+
- html
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
- tsx
|
|
15
|
+
message: Image missing 'alt' attribute at line {line}.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- |
|
|
19
|
+
<img
|
|
20
|
+
src="/logo.png"
|
|
21
|
+
/>
|
|
22
|
+
quiet:
|
|
23
|
+
- <img src="/logo.png" alt="Logo" />
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: VBC-102
|
|
2
|
+
name: multi-statement-one-liner
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
ast_check:
|
|
9
|
+
type: one-liner-limit
|
|
10
|
+
message: >-
|
|
11
|
+
Multiple statements on a single line detected. This reduces readability.
|
|
12
|
+
tests:
|
|
13
|
+
fire:
|
|
14
|
+
- function run() { start(); stop(); }
|
|
15
|
+
quiet:
|
|
16
|
+
- |
|
|
17
|
+
function run() {
|
|
18
|
+
start();
|
|
19
|
+
stop();
|
|
20
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: VBC-103
|
|
2
|
+
name: ascii-art-block
|
|
3
|
+
severity: warning
|
|
4
|
+
category: docs
|
|
5
|
+
tags:
|
|
6
|
+
- docs
|
|
7
|
+
- style
|
|
8
|
+
match:
|
|
9
|
+
regex: >-
|
|
10
|
+
(?:^[ \t]*(?:#|//)(?=[^\nA-Za-z0-9]*$)[^\n]*[-=*#_|/\\+~^]{6,}[^\n]*$\n){3,}
|
|
11
|
+
flags: m
|
|
12
|
+
multiline: true
|
|
13
|
+
file_types:
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- py
|
|
17
|
+
- sh
|
|
18
|
+
message: >-
|
|
19
|
+
Block of decoration at line {line}: three or more comment lines that are shape and nothing
|
|
20
|
+
else. A rule around a section heading is punctuation and is not reported; a banner is furniture
|
|
21
|
+
that has to be maintained.
|
|
22
|
+
tests:
|
|
23
|
+
fire:
|
|
24
|
+
- |
|
|
25
|
+
# ####################
|
|
26
|
+
# ####################
|
|
27
|
+
# ####################
|
|
28
|
+
quiet:
|
|
29
|
+
- |
|
|
30
|
+
# --------------------------------
|
|
31
|
+
# Shared fixtures from public data
|
|
32
|
+
# --------------------------------
|
|
33
|
+
- |
|
|
34
|
+
# ------------------------------
|
|
35
|
+
- '# - handles retries'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
id: VBC-104
|
|
2
|
+
name: inconsistent-import
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
^\s*import\s[\s\S]*?^\s*(?:const|let|var)\s[^\n]*=\s*require\(|^\s*(?:const|let|var)\s[^\n]*=\s*require\([\s\S]*?^\s*import\s
|
|
10
|
+
flags: m
|
|
11
|
+
multiline: true
|
|
12
|
+
file_types:
|
|
13
|
+
- js
|
|
14
|
+
- ts
|
|
15
|
+
message: Mixing 'require' and 'import' in the same file at line {line}.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- |
|
|
19
|
+
import fs from 'fs';
|
|
20
|
+
const path = require('path');
|
|
21
|
+
quiet:
|
|
22
|
+
- |
|
|
23
|
+
import fs from 'fs';
|
|
24
|
+
import path from 'path';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
id: VBC-106
|
|
2
|
+
name: spaces-in-filenames
|
|
3
|
+
severity: error
|
|
4
|
+
category: git
|
|
5
|
+
tags:
|
|
6
|
+
- git
|
|
7
|
+
- cross-platform
|
|
8
|
+
match:
|
|
9
|
+
git_check: spaces_in_filenames
|
|
10
|
+
message: >-
|
|
11
|
+
Filename '{file}' contains spaces. This causes issues on some operating systems and CLI
|
|
12
|
+
tools.
|
|
13
|
+
tests:
|
|
14
|
+
external: 'git-checker.test.ts: needs a staged file list'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: VBC-112
|
|
2
|
+
name: scroll-hijacking
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: window\.addEventListener\(['"]wheel['"]|\bscroll-behavior:\s*smooth
|
|
9
|
+
file_types:
|
|
10
|
+
- js
|
|
11
|
+
- ts
|
|
12
|
+
- css
|
|
13
|
+
message: >-
|
|
14
|
+
Potential scroll hijacking or forced smooth scrolling detected at line {line}.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- window.addEventListener('wheel', onWheel);
|
|
18
|
+
- 'html { scroll-behavior: smooth; }'
|
|
19
|
+
quiet:
|
|
20
|
+
- window.addEventListener('scroll', onScroll);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-113
|
|
2
|
+
name: disable-zoom
|
|
3
|
+
severity: error
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- accessibility
|
|
7
|
+
match:
|
|
8
|
+
regex: user-scalable\s*=\s*(?:no|0)\b|maximum-scale\s*=\s*1(?:\.0+)?(?![\d.])
|
|
9
|
+
flags: i
|
|
10
|
+
file_types:
|
|
11
|
+
- html
|
|
12
|
+
message: Disabling pinch-to-zoom is an accessibility violation.
|
|
13
|
+
tests:
|
|
14
|
+
fire:
|
|
15
|
+
- <meta name="viewport" content="width=device-width, user-scalable=no">
|
|
16
|
+
- <meta name="viewport" content="width=device-width, maximum-scale=1">
|
|
17
|
+
quiet:
|
|
18
|
+
- <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
19
|
+
- <meta name="viewport" content="maximum-scale=10">
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: VBC-117
|
|
2
|
+
name: block-paste
|
|
3
|
+
severity: error
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- security
|
|
8
|
+
match:
|
|
9
|
+
regex: >-
|
|
10
|
+
onPaste=['"]return false['"]|\.addEventListener\(['"]paste['"],.*?\.preventDefault\(
|
|
11
|
+
file_types:
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
- html
|
|
15
|
+
message: >-
|
|
16
|
+
Blocking paste in input fields harms both UX and security (password managers).
|
|
17
|
+
tests:
|
|
18
|
+
fire:
|
|
19
|
+
- input.addEventListener('paste', e => e.preventDefault());
|
|
20
|
+
quiet:
|
|
21
|
+
- input.addEventListener('paste', e => normalise(e));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
id: VBC-123
|
|
2
|
+
name: placeholder-as-label
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- accessibility
|
|
8
|
+
match:
|
|
9
|
+
regex: >-
|
|
10
|
+
<input\b(?![^>]*(?:aria-label|aria-labelledby|\bid\s*=))[^>]*\bplaceholder\s*=
|
|
11
|
+
multiline: true
|
|
12
|
+
file_types:
|
|
13
|
+
- html
|
|
14
|
+
- js
|
|
15
|
+
- ts
|
|
16
|
+
- tsx
|
|
17
|
+
message: >-
|
|
18
|
+
Using placeholder as the only label at line {line} is bad for accessibility.
|
|
19
|
+
tests:
|
|
20
|
+
fire:
|
|
21
|
+
- |
|
|
22
|
+
<input
|
|
23
|
+
type="email"
|
|
24
|
+
placeholder="Email"
|
|
25
|
+
/>
|
|
26
|
+
quiet:
|
|
27
|
+
- |
|
|
28
|
+
<label for="email">Email</label>
|
|
29
|
+
<input id="email" placeholder="you@example.com" />
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
id: VBC-131
|
|
2
|
+
name: video-background
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: <video\b(?=[^>]*\bautoplay\b)(?=[^>]*\bloop\b)(?=[^>]*\bmuted\b)[^>]*>
|
|
9
|
+
multiline: true
|
|
10
|
+
file_types:
|
|
11
|
+
- html
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
- tsx
|
|
15
|
+
message: Autoplay video backgrounds can be distracting and impact performance.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- <video autoplay loop muted src="bg.mp4"></video>
|
|
19
|
+
quiet:
|
|
20
|
+
- <video controls src="talk.mp4"></video>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: VBC-150
|
|
2
|
+
name: production-todo
|
|
3
|
+
severity: warning
|
|
4
|
+
category: core
|
|
5
|
+
tags:
|
|
6
|
+
- maintenance
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
\b(?:TODO|FIXME|HACK|XXX)\b(?=\s*[\(\[][^)\]\n]+[\)\]]|\s*:?\s*(?:#\d+|[A-Z][A-Z0-9]+-\d+))
|
|
10
|
+
scan: comments
|
|
11
|
+
file_types:
|
|
12
|
+
- js
|
|
13
|
+
- ts
|
|
14
|
+
- py
|
|
15
|
+
- sh
|
|
16
|
+
- c
|
|
17
|
+
- cpp
|
|
18
|
+
message: >-
|
|
19
|
+
Tracked debt marker still in the code at line {line}. It is attributed, so close the ticket
|
|
20
|
+
or delete the marker before shipping.
|
|
21
|
+
tests:
|
|
22
|
+
fire:
|
|
23
|
+
- '// TODO(fab): rework the cache key'
|
|
24
|
+
- '// FIXME #1234 flaky under load'
|
|
25
|
+
quiet:
|
|
26
|
+
- '// TODO: rework the cache key'
|
|
27
|
+
- // explains the cache key
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: VBC-153
|
|
2
|
+
name: sudo-setup
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- dx
|
|
7
|
+
- security
|
|
8
|
+
match:
|
|
9
|
+
regex: sudo\s+npm\s+install|sudo\s+pip\s+install
|
|
10
|
+
file_types:
|
|
11
|
+
- md
|
|
12
|
+
- sh
|
|
13
|
+
message: >-
|
|
14
|
+
Setup instructions requiring sudo detected at line {line}. Use local environments instead.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- file: fixture.md
|
|
18
|
+
code: Run `sudo npm install -g slopless`.
|
|
19
|
+
quiet:
|
|
20
|
+
- file: fixture.md
|
|
21
|
+
code: Run `npm install -D slopless`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
id: VBC-158
|
|
2
|
+
name: fouc-prevention
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: '@import'
|
|
9
|
+
file_types:
|
|
10
|
+
- css
|
|
11
|
+
message: Use of @import in CSS can cause Flash of Unstyled Content (FOUC).
|
|
12
|
+
tests:
|
|
13
|
+
fire:
|
|
14
|
+
- '@import url("theme.css");'
|
|
15
|
+
quiet:
|
|
16
|
+
- '.card { color: red; }'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: VBC-161
|
|
2
|
+
name: oversized-sticky-header
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: position:\s*sticky[\s\S]{0,200}?height:\s*(?:[3-9][0-9]|1[0-9][0-9])vh
|
|
9
|
+
multiline: true
|
|
10
|
+
file_types:
|
|
11
|
+
- css
|
|
12
|
+
message: Oversized sticky header (>30vh) detected at line {line}.
|
|
13
|
+
tests:
|
|
14
|
+
fire:
|
|
15
|
+
- |
|
|
16
|
+
.hero {
|
|
17
|
+
position: sticky;
|
|
18
|
+
top: 0;
|
|
19
|
+
height: 60vh;
|
|
20
|
+
}
|
|
21
|
+
quiet:
|
|
22
|
+
- |
|
|
23
|
+
.hero {
|
|
24
|
+
position: sticky;
|
|
25
|
+
top: 0;
|
|
26
|
+
height: 8vh;
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
id: VBC-172
|
|
2
|
+
name: hamburger-on-desktop
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
match:
|
|
8
|
+
regex: >-
|
|
9
|
+
@media[^{]*min-width:\s*(?:1[2-9][0-9][0-9]|[2-9][0-9]{3})px[^{]*\{[\s\S]{0,400}?\.(?:hamburger|burger|menu-toggle|nav-toggle)
|
|
10
|
+
multiline: true
|
|
11
|
+
file_types:
|
|
12
|
+
- css
|
|
13
|
+
- scss
|
|
14
|
+
message: Hamburger menu detected on desktop resolutions at line {line}.
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- |
|
|
18
|
+
@media (min-width: 1280px) {
|
|
19
|
+
.hamburger-menu { display: block; }
|
|
20
|
+
}
|
|
21
|
+
quiet:
|
|
22
|
+
- |
|
|
23
|
+
@media (max-width: 640px) {
|
|
24
|
+
.hamburger-menu { display: block; }
|
|
25
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
id: VBC-197
|
|
2
|
+
name: hardcoded-node-version
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- dx
|
|
7
|
+
- portability
|
|
8
|
+
match:
|
|
9
|
+
regex: node\s+-v|node\s+--version
|
|
10
|
+
file_types:
|
|
11
|
+
- sh
|
|
12
|
+
- json
|
|
13
|
+
message: >-
|
|
14
|
+
Hardcoded system version check detected at line {line}. Use an .nvmrc or engine field in
|
|
15
|
+
package.json instead.
|
|
16
|
+
tests:
|
|
17
|
+
fire:
|
|
18
|
+
- file: fixture.sh
|
|
19
|
+
code: node -v
|
|
20
|
+
quiet:
|
|
21
|
+
- file: fixture.sh
|
|
22
|
+
code: node build.js
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
id: VBC-201
|
|
2
|
+
name: redundant-async
|
|
3
|
+
severity: warning
|
|
4
|
+
category: clean-code
|
|
5
|
+
tags:
|
|
6
|
+
- clean-code
|
|
7
|
+
- performance
|
|
8
|
+
match:
|
|
9
|
+
file_types:
|
|
10
|
+
- ts
|
|
11
|
+
- tsx
|
|
12
|
+
- js
|
|
13
|
+
- jsx
|
|
14
|
+
ast_check:
|
|
15
|
+
type: async-without-await
|
|
16
|
+
message: >-
|
|
17
|
+
async function with no await at line {line}. The async keyword only wraps the return value
|
|
18
|
+
in a Promise here; drop it or await something.
|
|
19
|
+
tests:
|
|
20
|
+
fire:
|
|
21
|
+
- |
|
|
22
|
+
async function load() {
|
|
23
|
+
return cached;
|
|
24
|
+
}
|
|
25
|
+
quiet:
|
|
26
|
+
- |
|
|
27
|
+
async function load() {
|
|
28
|
+
return await fetchIt();
|
|
29
|
+
}
|
|
30
|
+
- |
|
|
31
|
+
function load() {
|
|
32
|
+
return cached;
|
|
33
|
+
}
|
|
34
|
+
- |
|
|
35
|
+
const spy = vi.fn(async (name) => undefined);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
id: VBC-206
|
|
2
|
+
name: pure-black-background
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- ux
|
|
7
|
+
- design
|
|
8
|
+
match:
|
|
9
|
+
regex: background-color:\s*#000000|background:\s*#000
|
|
10
|
+
file_types:
|
|
11
|
+
- css
|
|
12
|
+
message: >-
|
|
13
|
+
Pure black backgrounds (#000000) can cause eye strain. Consider a soft dark grey (e.g.,
|
|
14
|
+
#121212).
|
|
15
|
+
tests:
|
|
16
|
+
fire:
|
|
17
|
+
- 'body { background-color: #000000; }'
|
|
18
|
+
quiet:
|
|
19
|
+
- 'body { background-color: #12151b; }'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
id: VBC-208
|
|
2
|
+
name: hardcoded-colors
|
|
3
|
+
severity: warning
|
|
4
|
+
category: ux-dx
|
|
5
|
+
tags:
|
|
6
|
+
- design
|
|
7
|
+
- maintainability
|
|
8
|
+
match:
|
|
9
|
+
regex: color:\s*(#[0-9a-fA-F]{3,6}|rgba?\(.*?\))
|
|
10
|
+
file_types:
|
|
11
|
+
- css
|
|
12
|
+
- scss
|
|
13
|
+
exclude_files:
|
|
14
|
+
- '**/theme.css'
|
|
15
|
+
- '**/vars.css'
|
|
16
|
+
- '**/variables.css'
|
|
17
|
+
- '**/tokens.css'
|
|
18
|
+
- '**/*.tokens.*'
|
|
19
|
+
message: >-
|
|
20
|
+
Hardcoded color value detected at line {line}. Consider using a CSS variable or theme token.
|
|
21
|
+
tests:
|
|
22
|
+
fire:
|
|
23
|
+
- '.card { color: #ff0044; }'
|
|
24
|
+
quiet:
|
|
25
|
+
- '.card { color: var(--text); }'
|
|
26
|
+
- file: theme.css
|
|
27
|
+
code: '.card { color: #ff0044; }'
|