Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/add-no-undeclared-styles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@biomejs/biome": minor
---

Added new nursery lint rule [`noUndeclaredStyles`](https://biomejs.dev/linter/rules/no-undeclared-styles/) for HTML. The rule detects CSS class names used in `class="..."` attributes that are not defined in any `<style>` block or linked stylesheet within the same file.

```html
<!-- .typo is used but never defined -->
<html>
<head>
<style>.button { color: blue; }</style>
</head>
<body>
<div class="button typo"></div>
</body>
</html>
```
17 changes: 17 additions & 0 deletions .changeset/add-no-unused-styles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"@biomejs/biome": minor
---

Added new nursery lint rule [`noUnusedStyles`](https://biomejs.dev/linter/rules/no-unused-styles/) for CSS. The rule detects CSS class selectors that are never referenced in any HTML or JSX file that imports the stylesheet. This is a project-domain rule that requires the module graph.

```css
/* styles.css — .ghost is never used in any importing file */
.button { color: blue; }
.ghost { color: red; }
```

```jsx
/* App.jsx */
import "./styles.css";
export default () => <div className="button" />;
```
16 changes: 16 additions & 0 deletions .claude/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ This directory contains specialized skills for AI coding assistants working on B

Skills complement the specialized **agents** in `.claude/agents/` - agents are personas that do the work, skills are the procedural knowledge they reference.

## Universal Coding Standards

**CRITICAL: No Emojis Policy**

Emojis are BANNED in all code contributions and documentation:
- NO emojis in source code
- NO emojis in comments (code comments, rustdoc, etc.)
- NO emojis in diagnostic messages
- NO emojis in test files
- NO emojis in commit messages
- NO emojis in PR descriptions
- NO emojis in skill documents or agent instructions
- NO emojis in any generated code or text

This applies to all agents, all skills, and all contributions. Keep code and documentation professional and emoji-free.

## Available Skills

### Core Development Skills
Expand Down
242 changes: 198 additions & 44 deletions .claude/skills/biome-developer/SKILL.md

Large diffs are not rendered by default.

30 changes: 20 additions & 10 deletions .claude/skills/diagnostics-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ Use this skill when creating diagnostics - the error messages, warnings, and hin
- Actionable: Always suggest how to fix
- Show don't tell: Prefer code frames over textual explanations

**CRITICAL: No Emojis in Diagnostics**

Emojis are BANNED in all diagnostic messages, advice text, and error output:
- NO emojis in diagnostic messages
- NO emojis in advice notes
- NO emojis in code frame annotations
- NO emojis in log messages

Keep all user-facing text professional and emoji-free.

## Common Workflows

### Create a Diagnostic Type
Expand Down Expand Up @@ -240,54 +250,54 @@ Available tags:

**Good messages:**
```rust
// Specific and actionable
// Good: Specific and actionable
"Use 'let' or 'const' instead of 'var'"

// Explains why
// Good: Explains why
"This variable is never reassigned, consider using 'const'"

// Shows what to do
// Good: Shows what to do
"Remove the unused import statement"
```

**Bad messages:**
```rust
// Too vague
// Bad: Too vague
"Invalid syntax"

// Just states the obvious
// Bad: Just states the obvious
"Variable declared with 'var'"

// No guidance
// Bad: No guidance
"This code has a problem"
```

### Advice Guidelines

**Show, don't tell:**
```rust
// Good - shows code frame
// Good: Good - shows code frame
CodeFrameAdvice {
location: node.range(),
source_code: source,
annotation: markup! { "This expression is always truthy" }
}

// Less helpful - just text
// Bad: Less helpful - just text
LogAdvice {
message: markup! { "The expression at line 5 is always truthy" }
}
```

**Provide actionable fixes:**
```rust
// Good - shows exact change
// Good: Good - shows exact change
DiffAdvice {
old: "var x = 1;",
new: "const x = 1;",
}

// Less helpful - describes change
// Bad: Less helpful - describes change
LogAdvice {
message: markup! { "Change 'var' to 'const'" }
}
Expand Down
12 changes: 12 additions & 0 deletions .claude/skills/formatter-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ Use this skill when implementing or modifying Biome's formatters. It covers the
2. Language-specific crates must exist: `biome_{lang}_syntax`, `biome_{lang}_formatter`
3. For Prettier comparison: Install `bun` and run `pnpm install` in repo root

## Code Standards

**CRITICAL: No Emojis**

Emojis are BANNED in all formatter code:
- NO emojis in code comments
- NO emojis in rustdoc documentation
- NO emojis in test files
- NO emojis in debug output or error messages

Keep all code professional and emoji-free.

## Common Workflows

### Generate Formatter Boilerplate
Expand Down
161 changes: 159 additions & 2 deletions .claude/skills/lint-rule-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ Use this skill when creating new lint rules or assist actions for Biome. It prov
2. Ensure `cargo`, `just`, and `pnpm` are available
3. Read `crates/biome_analyze/CONTRIBUTING.md` for in-depth concepts

## Code Standards

**CRITICAL: No Emojis**

Emojis are BANNED in all lint rule code:
- NO emojis in rustdoc comments
- NO emojis in diagnostic messages
- NO emojis in code action descriptions
- NO emojis in test files or test comments
- NO emojis anywhere in the rule implementation

Keep all code and documentation professional and emoji-free.

## Common Workflows

### Create a New Lint Rule
Expand Down Expand Up @@ -74,18 +87,58 @@ impl Rule for UseMyRuleName {
RuleDiagnostic::new(
rule_category!(),
node.range(),
// Pillar 1 — WHAT the error is.
markup! {
"Avoid using this identifier."
"This identifier "<Emphasis>"prohibited_name"</Emphasis>" is not allowed."
},
)
// Pillar 2 — WHY it is triggered / why it is a problem.
.note(markup! {
"This identifier is prohibited because..."
"Using this identifier leads to [specific problem]."
})
// Pillar 3 — WHAT the user should do to fix it.
// Use a code action instead when an automated fix is possible.
.note(markup! {
"Replace it with [alternative] or remove it entirely."
}),
)
}
}
```

### The Three Diagnostic Pillars (REQUIRED)

Every diagnostic **must** follow the three pillars defined in `crates/biome_analyze/CONTRIBUTING.md`:

| Pillar | Question answered | Implemented as |
| --- | --- | --- |
| 1 | **What** is the error? | The `RuleDiagnostic` message (first argument to `markup!`) |
| 2 | **Why** is it a problem? | A `.note()` explaining the consequence or rationale |
| 3 | **What should the user do?** | A code action (`action` fn), or a second `.note()` if no fix is available |

**Example from `noUnusedVariables`:**
```rust
RuleDiagnostic::new(
rule_category!(),
range,
// Pillar 1: what
markup! { "This variable "<Emphasis>{name}</Emphasis>" is unused." },
)
// Pillar 2: why
.note(markup! {
"Unused variables are often the result of typos, incomplete refactors, or other sources of bugs."
})
// Pillar 3: what to do (here as a note; ideally a code action)
.note(markup! {
"Remove the variable or use it."
})
```

**Common mistakes to avoid:**
- Combining pillars 2 and 3 into a single note — keep them separate.
- Writing pillar 3 as the only note, skipping pillar 2.
- Writing a pillar 1 message that already contains "why" — the message should stay short and factual; move the rationale to pillar 2.

### Using Semantic Model

For rules that need binding analysis:
Expand Down Expand Up @@ -187,12 +240,51 @@ tests/specs/nursery/useMyRuleName/
└── options.json # Optional rule configuration
```

**IMPORTANT: Magic Comments for Test Expectations**

All test files MUST include magic comments at the top to set expectations:

- **Valid tests** (should not generate diagnostics):
```javascript
/* should not generate diagnostics */
const allowed_name = 1;
```

- **Invalid tests** (should generate diagnostics):
```javascript
// should generate diagnostics
const prohibited_name = 1;
const another_prohibited = 2;
```

For HTML files:
```html
<!-- should not generate diagnostics -->
<!doctype html>
<html>...</html>
```

For languages that support both comment styles, use `/* */` or `//` as appropriate. The comment should be the very first line of the file.

These magic comments:
- Document the intent of the test file
- Help reviewers understand what's expected
- Serve as a quick reference when debugging test failures

Example `invalid.js`:
```javascript
// should generate diagnostics
const prohibited_name = 1;
const another_prohibited = 2;
```

Example `valid.js`:
```javascript
/* should not generate diagnostics */
const allowed_name = 1;
const another_allowed = 2;
```

Run snapshot tests:
```shell
just test-lintrule useMyRuleName
Expand Down Expand Up @@ -225,6 +317,71 @@ just f # Format code
just l # Lint code
```

## Documenting Rules

### Multi-File Examples

For rules that analyze relationships between multiple files (e.g., import cycles, cross-file dependencies, CSS class references), use the `file=<path>` property:

```rust
/// ### Invalid
///
/// ```js,expect_diagnostic,file=foo.js
/// import { bar } from "./bar.js";
/// export function foo() {
/// return bar();
/// }
/// ```
///
/// ```js,expect_diagnostic,file=bar.js
/// import { foo } from "./foo.js";
/// export function bar() {
/// return foo();
/// }
/// ```
```

**How it works:**
- All files in a documentation section (`### Invalid` or `### Valid`) are collected into an in-memory file system
- The module graph is automatically populated from these files
- Each file with `expect_diagnostic` must emit exactly one diagnostic
- Files without `expect_diagnostic` provide context but aren't expected to trigger the rule

**Supported languages:**
- Supported: JavaScript/TypeScript/JSX/TSX
- Supported: CSS (module graph automatically populated from `file=` blocks)
- Not supported: HTML with `<style>` blocks (requires embedded snippet parsing - not yet implemented)

### The `ignore` Directive

Use `ignore` to exclude code blocks from automatic validation:

```rust
/// ```html,expect_diagnostic,ignore
/// <style>.card { border: 1px solid; }</style>
/// <div class="header">Content</div>
/// ```
```

**When to use `ignore`:**
- Rules that require features not yet available in rustdoc context (e.g., HTML embedded snippets)
- Examples that need special parser configuration
- Illustrative examples where automatic validation isn't critical

**Important:** Even with `ignore`, you should have comprehensive snapshot tests in `tests/specs/`.

### Code Block Property Order

For consistency, properties should be ordered:
```rust
/// ```<language>[,expect_diagnostic][,(options|full_options|use_options)][,ignore][,file=path]
```

Examples:
- `css,expect_diagnostic,file=styles.css`
- `jsx,file=App.jsx`
- `html,expect_diagnostic,ignore`

## Tips

- **Rule naming**: Use `no*` prefix for rules that forbid something (e.g., `noVar`), `use*` for rules that mandate something (e.g., `useConst`)
Expand Down
13 changes: 13 additions & 0 deletions .claude/skills/parser-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ Use this skill when creating or modifying Biome's parsers. Covers grammar author
2. Understand the language syntax you're implementing
3. Read `crates/biome_parser/CONTRIBUTING.md` for detailed concepts

## Code Standards

**CRITICAL: No Emojis**

Emojis are BANNED in all parser code:
- NO emojis in code comments
- NO emojis in rustdoc documentation
- NO emojis in grammar files (.ungram)
- NO emojis in test files
- NO emojis in error messages or diagnostics

Keep all code professional and emoji-free.

## Common Workflows

### Create Grammar for New Language
Expand Down
Loading
Loading