@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.1",
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
- "scripts": {
10
- "test": "bash scripts/test.sh"
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