@aliou/biome-plugins 0.0.1 → 0.2.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/package.json
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aliou/biome-plugins",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Custom Biome lint rules written as GritQL plugins",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/aliou/biome-plugins"
|
|
9
|
+
},
|
|
6
10
|
"files": [
|
|
7
|
-
"plugins"
|
|
11
|
+
"plugins",
|
|
12
|
+
"skills"
|
|
8
13
|
],
|
|
9
|
-
"
|
|
10
|
-
"
|
|
14
|
+
"pi": {
|
|
15
|
+
"skills": [
|
|
16
|
+
"skills"
|
|
17
|
+
]
|
|
11
18
|
},
|
|
12
19
|
"publishConfig": {
|
|
13
20
|
"access": "public"
|
|
@@ -18,5 +25,8 @@
|
|
|
18
25
|
},
|
|
19
26
|
"peerDependencies": {
|
|
20
27
|
"@biomejs/biome": ">=2.0.0"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "bash scripts/test.sh"
|
|
21
31
|
}
|
|
22
|
-
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
engine biome(1.0)
|
|
2
|
+
language js(typescript,jsx)
|
|
3
|
+
|
|
4
|
+
or {
|
|
5
|
+
`import $_ from $source` where {
|
|
6
|
+
$source <: r".*\.js[\"']$",
|
|
7
|
+
register_diagnostic(
|
|
8
|
+
span = $source,
|
|
9
|
+
message = "Remove the .js extension. Use moduleResolution: bundler in tsconfig.json to resolve imports without file extensions.",
|
|
10
|
+
severity = "error"
|
|
11
|
+
)
|
|
12
|
+
},
|
|
13
|
+
`import $source` where {
|
|
14
|
+
$source <: r".*\.js[\"']$",
|
|
15
|
+
register_diagnostic(
|
|
16
|
+
span = $source,
|
|
17
|
+
message = "Remove the .js extension. Use moduleResolution: bundler in tsconfig.json to resolve imports without file extensions.",
|
|
18
|
+
severity = "error"
|
|
19
|
+
)
|
|
20
|
+
},
|
|
21
|
+
`export * from $source` where {
|
|
22
|
+
$source <: r".*\.js[\"']$",
|
|
23
|
+
register_diagnostic(
|
|
24
|
+
span = $source,
|
|
25
|
+
message = "Remove the .js extension. Use moduleResolution: bundler in tsconfig.json to resolve imports without file extensions.",
|
|
26
|
+
severity = "error"
|
|
27
|
+
)
|
|
28
|
+
},
|
|
29
|
+
JsExport() as $exp where {
|
|
30
|
+
$exp <: contains JsModuleSource() as $source,
|
|
31
|
+
$source <: r".*\.js[\"']$",
|
|
32
|
+
register_diagnostic(
|
|
33
|
+
span = $source,
|
|
34
|
+
message = "Remove the .js extension. Use moduleResolution: bundler in tsconfig.json to resolve imports without file extensions.",
|
|
35
|
+
severity = "error"
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: biome-gritql-plugins
|
|
3
|
+
description: Writing custom Biome lint rules as GritQL plugins. Use when creating, editing, or debugging .grit files for Biome's plugin system. Covers GritQL pattern syntax, AST node matching, metavariables, the register_diagnostic API, and testing patterns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Biome GritQL Plugins
|
|
7
|
+
|
|
8
|
+
GritQL is a structural pattern matching language that operates on Biome's AST. Each plugin is a `.grit` file that matches code patterns and emits diagnostics.
|
|
9
|
+
|
|
10
|
+
## File structure
|
|
11
|
+
|
|
12
|
+
Every `.grit` file requires two headers:
|
|
13
|
+
|
|
14
|
+
```grit
|
|
15
|
+
engine biome(1.0)
|
|
16
|
+
language js(jsx)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Supported language values: `js`, `js(jsx)`, `js(typescript)`, `js(typescript,jsx)`, `css`.
|
|
20
|
+
|
|
21
|
+
After headers, write one pattern with conditions and a `register_diagnostic()` call.
|
|
22
|
+
|
|
23
|
+
## Plugin API
|
|
24
|
+
|
|
25
|
+
One function is available:
|
|
26
|
+
|
|
27
|
+
```grit
|
|
28
|
+
register_diagnostic(
|
|
29
|
+
span = $node, -- required: AST node to underline
|
|
30
|
+
message = "...", -- required: diagnostic message
|
|
31
|
+
severity = "error" -- optional: error (default), warn, info, hint
|
|
32
|
+
)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Pattern syntax
|
|
36
|
+
|
|
37
|
+
### Code snippets
|
|
38
|
+
|
|
39
|
+
Backtick-wrapped code matches structurally (ignores formatting, quote style, whitespace):
|
|
40
|
+
|
|
41
|
+
```grit
|
|
42
|
+
`console.log($msg)`
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Metavariables
|
|
46
|
+
|
|
47
|
+
- `$name` captures an AST node
|
|
48
|
+
- `$_` is a wildcard (match but don't capture)
|
|
49
|
+
- Same variable used twice in a snippet must match the same code: `` `$fn && $fn()` `` matches `foo && foo()` but not `foo && bar()`
|
|
50
|
+
|
|
51
|
+
### Operators
|
|
52
|
+
|
|
53
|
+
| Operator | Meaning | Example |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `<:` | matches | `$method <: "log"` |
|
|
56
|
+
| `contains` | search descendants | `$value <: contains JsTemplateExpression()` |
|
|
57
|
+
| `or { ... }` | match any | `$m <: or { "log", "warn" }` |
|
|
58
|
+
| `not` | negate | `not $name <: r".*Icon"` |
|
|
59
|
+
| `as $var` | alias a match | `contains "color: $c" as $rule` |
|
|
60
|
+
| `where { ... }` | add conditions | `` `$x` where { $x <: `foo` } `` |
|
|
61
|
+
|
|
62
|
+
### Regex
|
|
63
|
+
|
|
64
|
+
Use `r"pattern"` to match captured text against a regex:
|
|
65
|
+
|
|
66
|
+
```grit
|
|
67
|
+
$name <: r".*Icon"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Named AST nodes
|
|
71
|
+
|
|
72
|
+
Use Biome's PascalCase AST types for precise matching:
|
|
73
|
+
|
|
74
|
+
```grit
|
|
75
|
+
jsx_attribute(name = "className", $value) where {
|
|
76
|
+
$value <: contains JsTemplateExpression(),
|
|
77
|
+
register_diagnostic(span = $value, message = "Use cn() instead")
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Common node types:
|
|
82
|
+
- `JsxAttribute`, `JsxElement`, `JsxSelfClosingElement`, `JsxOpeningElement`
|
|
83
|
+
- `JsTemplateExpression`, `JsCallExpression`, `JsIfStatement`
|
|
84
|
+
- `JsxExpressionChild` (for `{expr}` in JSX)
|
|
85
|
+
|
|
86
|
+
Both snake_case (`jsx_attribute`) and PascalCase (`JsxAttribute`) work. Discover node names via the [Biome Playground](https://biomejs.dev/playground/) syntax tree view.
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
### Disallow template literals in className
|
|
91
|
+
|
|
92
|
+
```grit
|
|
93
|
+
engine biome(1.0)
|
|
94
|
+
language js(jsx)
|
|
95
|
+
|
|
96
|
+
jsx_attribute(name = "className", $value) where {
|
|
97
|
+
$value <: contains JsTemplateExpression(),
|
|
98
|
+
register_diagnostic(
|
|
99
|
+
span = $value,
|
|
100
|
+
message = "Use cn() instead of template literal in className",
|
|
101
|
+
severity = "error"
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Disallow Object.assign
|
|
107
|
+
|
|
108
|
+
```grit
|
|
109
|
+
engine biome(1.0)
|
|
110
|
+
language js
|
|
111
|
+
|
|
112
|
+
`$fn($args)` where {
|
|
113
|
+
$fn <: `Object.assign`,
|
|
114
|
+
register_diagnostic(
|
|
115
|
+
span = $fn,
|
|
116
|
+
message = "Prefer object spread instead of Object.assign()"
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### CSS: disallow explicit color declarations
|
|
122
|
+
|
|
123
|
+
```grit
|
|
124
|
+
engine biome(1.0)
|
|
125
|
+
language css
|
|
126
|
+
|
|
127
|
+
`$selector { $props }` where {
|
|
128
|
+
$props <: contains `color: $color` as $rule,
|
|
129
|
+
not $selector <: r"\.color-.*",
|
|
130
|
+
register_diagnostic(
|
|
131
|
+
span = $rule,
|
|
132
|
+
message = "Don't set explicit colors. Use .color-* classes instead."
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Configuration
|
|
138
|
+
|
|
139
|
+
Add plugins in `biome.json`:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"plugins": [
|
|
144
|
+
"plugins/my-rule.grit"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Paths are resolved relative to the `biome.json` file. For plugins installed via npm:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"plugins": [
|
|
154
|
+
"./node_modules/@scope/my-plugins/plugins/rule.grit"
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Testing
|
|
160
|
+
|
|
161
|
+
Create a test file with both violations and valid code, then run:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
biome lint /tmp/test-file.tsx
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Plugin diagnostics appear with the `plugin` category in output.
|
|
168
|
+
|
|
169
|
+
## Limitations
|
|
170
|
+
|
|
171
|
+
- Only JavaScript and CSS target languages are supported
|
|
172
|
+
- No plugin options or configuration per-rule
|
|
173
|
+
- No automatic npm package resolution (must use relative paths)
|
|
174
|
+
- GritQL support in Biome is still experimental; some GritQL features are missing
|
|
175
|
+
|
|
176
|
+
## References
|
|
177
|
+
|
|
178
|
+
- Plugin docs: https://biomejs.dev/linter/plugins
|
|
179
|
+
- GritQL reference: https://biomejs.dev/reference/gritql
|
|
180
|
+
- GritQL language: https://docs.grit.io/language/overview
|
|
181
|
+
- Feature tracking: https://github.com/biomejs/biome/issues/2582
|