feat(html): directives parsing and formatting#8719
Conversation
🦋 Changeset detectedLatest commit: 119ce98 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughThis pull request implements parsing and formatting support for Svelte directives in the HTML formatter. The changes introduce lexer and parser support for eight directive types ( Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/biome_html_parser/benches/html_parser.rs (1)
1-6: Remove the duplicateBenchCaseimport.You've imported
BenchCasefrom bothbiome_bench_utils(line 1) andbiome_test_utils(line 6). The latter shadows the former, making line 1's import unused. Please remove whichever import is incorrect.🧹 Proposed fix
If
biome_bench_utils::BenchCaseis the correct one to use:-use biome_bench_utils::BenchCase; - use biome_diagnostics::{DiagnosticExt, print_diagnostic_to_string}; use biome_html_parser::{HtmlParseOptions, parse_html, parse_html_with_cache}; use biome_html_syntax::HtmlFileSource; use biome_rowan::NodeCache; -use biome_test_utils::BenchCase; +use biome_bench_utils::BenchCase;If
biome_test_utils::BenchCaseis the correct one to use:-use biome_bench_utils::BenchCase; - use biome_diagnostics::{DiagnosticExt, print_diagnostic_to_string}; use biome_html_parser::{HtmlParseOptions, parse_html, parse_html_with_cache}; use biome_html_syntax::HtmlFileSource; use biome_rowan::NodeCache; use biome_test_utils::BenchCase;crates/biome_html_parser/src/syntax/mod.rs (1)
356-378: Duplicate match arm detected.Lines 356-365 and 367-378 both match
T!["{{"]. The second arm (367-378) is unreachable code. This looks like an unintended duplication—one of these should likely be removed.🐛 Proposed fix
match p.cur() { T!["{{"] => { let m = p.start(); DoubleTextExpressions .parse_exclusive_syntax( p, |p| parse_double_text_expression(p, HtmlLexContext::InsideTag), |p, marker| disabled_interpolation(p, marker.range(p)), ) .ok(); Present(m.complete(p, HTML_ATTRIBUTE)) } - T!["{{"] => { - let m = p.start(); - HtmlSyntaxFeatures::DoubleTextExpressions - .parse_exclusive_syntax( - p, - |p| parse_double_text_expression(p, HtmlLexContext::InsideTag), - |p, marker| disabled_interpolation(p, marker.range(p)), - ) - .ok(); - - Present(m.complete(p, HTML_ATTRIBUTE)) - } T![:] => HtmlSyntaxFeatures::Vue.parse_exclusive_syntax(
🤖 Fix all issues with AI agents
In @.github/workflows/benchmark_html.yml:
- Line 1: The workflow name string "Benchmarks JS" should be updated to reflect
that it benchmarks HTML crates; replace the name value with something like
"Benchmarks HTML" (update the top-level name field in the workflow where
"Benchmarks JS" appears) so the workflow title matches the
biome_html_parser/biome_html_formatter/biome_html_analyze targets.
In @crates/biome_html_formatter/src/html/any/attribute_initializer.rs:
- Line 1: The file-level comment indicates the file is autogenerated but was
manually edited; either re-run the generator (cargo codegen formatter) to
regenerate crates/biome_html_formatter/src/html/any/attribute_initializer.rs so
the generated header is accurate, or remove/replace the "This is a generated
file. Don't modify it by hand!" comment and update the module comment to reflect
that attribute_initializer.rs is now hand-maintained (keep the compact mode
changes intact if manual).
In @crates/biome_html_parser/src/syntax/svelte.rs:
- Around line 1185-1190: The parse_element function currently swallows missing
modifier names by calling parse_name(p).ok(); instead detect when parse_name(p)
returns Absent and emit a parse diagnostic before completing the node so a
trailing pipe like `bind:value|` produces an error. Replace the `.ok()` call
with an explicit match on the parse_name(p) result and on the Absent branch call
the parser's error reporting (e.g., p.error(...) or the project's equivalent)
with a message like "expected modifier name", then still complete m as
SVELTE_DIRECTIVE_MODIFIER.
In
@crates/biome_html_parser/tests/html_specs/error/svelte/directives/in_invalid_params.svelte:
- Line 1: The test fixture uses an unquoted '>' that prematurely closes the
start tag; change the Svelte snippet so the error stays inside the directive
parameters (i.e., keep the start tag and braces balanced) and make the
expression inside the in:fly params syntactically invalid—for example close the
tag/braces but leave the object or expression incomplete or malformed inside the
{{ ... }} of the in:fly directive so the parser reports an error specific to
directive params (refer to the in:fly directive in this file).
In @crates/biome_html_syntax/src/text_ext.rs:
- Around line 5-10: Update the rustdoc for the method string_value() to clarify
it returns the string value of a text expression (unquoted content like
{expression}) rather than implying it strips quotes; e.g., change "Returns the
string value of the attribute, if available, without quotes." to something like
"Returns the string value of the text expression, if available." and ensure the
comment references that this is for HtmlTextExpression/unquoted content to avoid
implying quote removal.
In @xtask/codegen/html.ungram:
- Around line 558-563: The SvelteDirectiveValue production has inconsistent
indentation (line with "initializer: HtmlAttributeInitializerClause?" uses two
spaces instead of a tab); update the indentation to match the other lines (use a
tab before "initializer: HtmlAttributeInitializerClause?") so the
SvelteDirectiveValue block aligns with the rest of the grammar; verify the
change around the SvelteDirectiveValue symbol and ensure no other lines in that
production use spaces.
- Around line 498-507: The grammar rule AnySvelteDirective contains inconsistent
indentation: SvelteInDirective through SvelteStyleDirective are indented with
two spaces while the rest of the file uses tabs; normalize the indentation by
replacing those two-space indents with a single tab so all alternatives
(SvelteBindDirective, SvelteTransitionDirective, SvelteInDirective,
SvelteOutDirective, SvelteUseDirective, SvelteAnimateDirective,
SvelteStyleDirective, SvelteClassDirective) align with the existing tab-based
formatting for the grammar.
🧹 Nitpick comments (8)
crates/biome_html_parser/tests/quick_test.rs (1)
4-19: Test input updated to exercise Svelte directive parsing.The new test input correctly exercises the
style:directive shorthand, aligning with the PR's Svelte directive parsing feature.Minor observation: The blank line at line 8 appears deliberate but seems unnecessary for this test case. If it's intentional for whitespace handling validation, consider adding a comment to clarify.
crates/biome_html_parser/tests/html_specs/error/svelte/directives/class_invalid_expression.svelte (1)
1-1: Consider adding the closing brace for test clarity.The fixture tests two error conditions simultaneously: an invalid expression (
>Invalid) and a missing closing brace. To isolate what's being tested, consider:<div class:active={>Invalid}></div>. The missing brace could be covered in a separate test likeclass_missing_closing_brace.svelte.crates/biome_html_parser/tests/html_specs/error/svelte/directives/use_invalid_expression.svelte (1)
1-1: Verify if multiple syntax errors are intentional.This test fixture contains several syntax errors: an invalid expression (
>Invalid), a missing closing brace for the expression, and an unclosed opening tag. Whilst testing compound error scenarios can be valuable, a test nameduse_invalid_expressionmight be clearer if it isolated the expression error.Consider whether you want:
- Current: Multiple errors for compound error recovery testing
- Alternative:
<div use:tooltip={>Invalid}></div>(isolates invalid expression)- Alternative:
<div use:tooltip={1 + )}></div>(incomplete expression)Is the compound error scenario intentional for this test case?
crates/biome_html_parser/tests/html_specs/ok/svelte/directives/bind_value_basic.svelte (1)
1-1: Solid baseline forbind:with an explicit expression.Optional follow-up (if not already covered elsewhere): add
bind:value={value}to directly exercise the formatter’s shorthand rewrite path.crates/biome_html_formatter/src/html/auxiliary/string.rs (1)
12-15: Unnecessary.clone()call.
value_tokenis already aSyntaxResult<SyntaxToken>, so the.clone()is superfluous. This differs from the pattern incrates/biome_html_formatter/src/svelte/auxiliary/literal.rs:12which usesnode.value_token()?directly.♻️ Proposed simplification
if self.compact { - let value_token = value_token.clone()?; + let value_token = value_token?; return format_removed(&value_token).fmt(f); }crates/biome_html_formatter/src/html/auxiliary/single_text_expression.rs (1)
21-27: Optional: simplify by removing intermediate bindings and clones.The cloning and intermediate bindings can be avoided:
if self.compact { format_removed(&l_curly_token?).fmt(f)?; format_removed(&r_curly_token?).fmt(f)?; expression?.format().with_options(self.compact).fmt(f) } else {This is cleaner and avoids the clones, though the performance impact is likely negligible.
crates/biome_html_formatter/src/utils/svelte_directive.rs (1)
15-20: Consider removing unused_nodefield.The
_nodefield is stored but never read. If it's reserved for future debugging or comments handling, a brief doc comment would clarify intent. Otherwise, it can be removed to reduce struct size.♻️ If unused, consider removing
pub(crate) struct FmtSvelteDirective<'a> { - _node: &'a HtmlSyntaxNode, token: SyntaxResult<HtmlSyntaxToken>, value: SyntaxResult<SvelteDirectiveValue>, allows_compact: bool, }And update each
Fromimplementation to remove the_node/value.syntax()assignment.crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs (1)
152-160: Redundantclone()calls and explicitreturn.The
eq_tokenandvaluebindings from line 72 are already available here. The.clone()calls and explicitreturn Ok(())can be simplified:♻️ Proposed simplification
CompactKind::Remove => { - let eq_token = eq_token.clone()?; - let value = value.clone()?; + let eq_token = eq_token?; + let value = value?; write!( f, [format_removed(&eq_token), value.format().with_options(true),] - )?; - return Ok(()); + ) }
crates/biome_html_parser/tests/html_specs/error/svelte/directives/in_invalid_params.svelte
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
Cargo.toml (1)
23-23: Relocate to the "not publish" section.
biome_bench_utilsappears to be an internal benchmarking utility that won't be published. It should be moved below the# not publishcomment (line 24) to align with the versioning pattern—published crates have versions, unpublished ones don't.♻️ Proposed relocation
Remove from line 23 and add it after line 24 in the "not publish" section, for example after
biome_cli:-biome_bench_utils = { path = "./crates/biome_bench_utils" } # not publish +biome_bench_utils = { path = "./crates/biome_bench_utils" } biome_cli = { path = "./crates/biome_cli" }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Cargo.toml
🧰 Additional context used
📓 Path-based instructions (1)
**/Cargo.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/Cargo.toml: Use workspace dependencies withworkspace = truefor internal crates in Cargo.toml
Use path dependencies for dev-dependencies in crates to avoid requiring published versions
Files:
Cargo.toml
🧠 Learnings (15)
📓 Common learnings
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Applies to **/Cargo.toml : Use workspace dependencies with `workspace = true` for internal crates in Cargo.toml
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/Cargo.toml : Include development dependencies in `Cargo.toml` for formatter tests: `biome_formatter_test`, `biome_<language>_factory`, `biome_<language>_parser`, `biome_parser`, `biome_service`, `countme`, `iai`, `quickcheck`, `quickcheck_macros`, and `tests_macros`
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests
Applied to files:
Cargo.toml
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Build debug binaries using `cargo build --bin biome` for development and triaging
Applied to files:
Cargo.toml
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Applies to **/Cargo.toml : Use path dependencies for dev-dependencies in crates to avoid requiring published versions
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/server.rs : Use WorkspaceServer implementation for maintaining workspace state in daemon mode and CLI daemonless mode
Applied to files:
Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use helper functions like `map`, `filter`, and `and_then` to avoid excessive nested `if let` statements
Applied to files:
Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Rule options must be defined in the `biome_rule_options` crate with a file named after the rule
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Create two new crates `biome_{language}_syntax` and `biome_{language}_factory` using `cargo new --lib` for new language parsers
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:04:47.058Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_aria_metadata/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:04:47.058Z
Learning: Applies to crates/biome_aria_metadata/**/build.rs : The `build.rs` script uses `aria-data.json` to generate ARIA metadata
Applied to files:
Cargo.toml
📚 Learning: 2025-11-24T18:04:57.309Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:04:57.309Z
Learning: Applies to crates/biome_diagnostics/**/*.rs : Use helper types from the biome_diagnostics::v2 module (CodeFrameAdvice, CommandAdvice, DiffAdvice, LogAdvice) or implement the Advices trait yourself for custom advice handling
Applied to files:
Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Apply `#[serde(rename_all = "camelCase")]` to rule option structs to match JSON configuration naming convention
Applied to files:
Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `.ok()?` to transform `Result` types into `Option` or `let else` pattern to handle errors when the function returns `Vec`
Applied to files:
Cargo.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Check Dependencies
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Bench (biome_html_analyze)
- GitHub Check: Documentation
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_html_parser)
| b'!' => self.consume_byte(T![!]), | ||
| b'{' if self.at_svelte_opening_block() => self.consume_svelte_opening_block(), | ||
| b'{' => { | ||
| let dispatched = lookup_byte(current); |
There was a problem hiding this comment.
It speeds things up. We should always use the lookup table
biome/crates/biome_css_parser/src/lexer/mod.rs
Lines 288 to 290 in c4f2650
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
xtask/codegen/html.ungram (1)
3-3: Fix the copy-paste error in the comment.The comment incorrectly states this grammar specifies "Rust's concrete syntax tree". It should reference HTML instead.
📝 Proposed fix
-// This grammar specifies the structure of Rust's concrete syntax tree. +// This grammar specifies the structure of HTML's concrete syntax tree.crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs (1)
19-34: Docs don’t match behaviour forcompact/CompactKind.The field docs say “in compact mode, all tokens and children are removed”, but
CompactKind::Curlykeeps the value and only sometimes removes=. Consider updating the docs to describe each variant precisely (None/Remove/Curly).Also applies to: 37-45
🤖 Fix all issues with AI agents
In
@crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs:
- Around line 74-90: The CompactKind::Remove branch currently calls
value.format().with_options(true) which uses an opaque bool that behaves
inconsistently for HtmlString vs HtmlSingleTextExpression; update this by
introducing a clear options type (e.g., RemoveOptions with a flag like
remove_entire_value vs remove_outer_wrapper) and thread it through
value.format().with_options(...) instead of a bare bool, or alternatively detect
the value variant (AnyHtmlAttributeInitializer::HtmlString vs
HtmlSingleTextExpression) in the CompactKind::Remove handling and call
format_removed(value) for HtmlString and the appropriate wrapper-only removal
for HtmlSingleTextExpression so that format_removed() is used when the entire
value must be omitted and only the braces are removed when intended.
- Around line 92-107: The match arm currently checks (Some("iframe"),
Some("allow")) using a case-sensitive comparison on self.tag_name and
self.attribute_name; change it to a case-insensitive check by comparing with
eq_ignore_ascii_case (e.g., check self.tag_name.as_deref().map(|s|
s.eq_ignore_ascii_case("iframe")) and similarly for attribute_name) or normalize
the stored values to lowercase before matching so the special iframe/allow
handling triggers for mixed- or upper-case HTML names.
In @crates/biome_html_parser/src/syntax/svelte.rs:
- Around line 941-945: parse_binding_literal currently always consumes a token;
modify it to follow the parser pattern by first checking p.at(HTML_LITERAL) and
returning Absent if false, otherwise proceed to start the marker (m =
p.start()), call p.bump_with_context(HTML_LITERAL, HtmlLexContext::InsideTag),
and complete the marker with SVELTE_LITERAL (Present(m.complete(...))). Ensure
you reference the same symbols: parse_binding_literal, p.at(HTML_LITERAL),
p.bump_with_context, m.start(), m.complete(..., SVELTE_LITERAL), and return
Absent when the token check fails.
🧹 Nitpick comments (3)
crates/biome_html_analyze/benches/html_analyzer.rs (2)
28-31: Simplify the single-entry HashMap.The
all_suitesHashMap contains only one entry. Consider directly using the string constant or removing the intermediate HashMap structure for clarity.♻️ Simplified version
- let mut all_suites = HashMap::new(); - all_suites.insert("html", include_str!("libs-html.txt")); - let mut libs = vec![]; - libs.extend(all_suites.values().flat_map(|suite| suite.lines())); + let libs: Vec<_> = include_str!("libs-html.txt").lines().collect();
36-77: Consider validating parse success.The benchmark directly uses the parse result without checking for parse errors. Whilst benchmarking malformed HTML is valuable, you might want to verify that test cases parse successfully to avoid skewing results with error paths.
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs (1)
110-116: Nice: iframeallowlist formatting; small clean-up opportunity.This is readable and matches the intended behaviour. Minor:
JoinWithSemicoloncould be aconst/fn returning a formatter (or usejoin_with+ closure) to reduce local type noise, but it’s not a blocker.Also applies to: 117-143
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lockand included by**
📒 Files selected for processing (7)
.github/workflows/benchmark_html.ymlcrates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rscrates/biome_html_analyze/benches/libs-html.txtcrates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rscrates/biome_html_parser/src/syntax/svelte.rsxtask/codegen/html.ungram
✅ Files skipped from review due to trivial changes (1)
- crates/biome_html_analyze/benches/libs-html.txt
🧰 Additional context used
📓 Path-based instructions (2)
**/Cargo.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/Cargo.toml: Use workspace dependencies withworkspace = truefor internal crates in Cargo.toml
Use path dependencies for dev-dependencies in crates to avoid requiring published versions
Files:
crates/biome_html_analyze/Cargo.toml
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use thedbg!()macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests
Files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rscrates/biome_html_parser/src/syntax/svelte.rscrates/biome_html_analyze/benches/html_analyzer.rs
🧠 Learnings (49)
📓 Common learnings
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/Cargo.toml : Include development dependencies in `Cargo.toml` for formatter tests: `biome_formatter_test`, `biome_<language>_factory`, `biome_<language>_parser`, `biome_parser`, `biome_service`, `countme`, `iai`, `quickcheck`, `quickcheck_macros`, and `tests_macros`
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Avoid string allocations by using `&str` or `TokenText` instead of `to_string()`
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : The first paragraph of rule documentation must be written in a single line to ensure proper rendering in the rules overview table
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `Markup!` macro for diagnostic messages and code action descriptions to ensure proper formatting
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_parser/src/syntax/svelte.rscrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Create two new crates `biome_{language}_syntax` and `biome_{language}_factory` using `cargo new --lib` for new language parsers
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_node_union!` macro to query multiple node types together to avoid redundant traversal passes
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2025-12-22T09:27:13.161Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:27:13.161Z
Learning: In crates/biome_analyze/**/*analyze/src/**/*.rs, the `fix_kind` field in `declare_lint_rule!` should only be specified when the rule implements the `action` function. Rules that only emit diagnostics without providing code fixes should not include `fix_kind` in their metadata.
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_parser/src/syntax/svelte.rscrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Build debug binaries using `cargo build --bin biome` for development and triaging
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Applies to **/Cargo.toml : Use path dependencies for dev-dependencies in crates to avoid requiring published versions
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Applies to **/Cargo.toml : Use workspace dependencies with `workspace = true` for internal crates in Cargo.toml
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace*.rs : Implement the Workspace trait in the Biome Service to manage internal state of projects, including open documents, project layout instances, and module graph instances
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Apply `#[serde(rename_all = "camelCase")]` to rule option structs to match JSON configuration naming convention
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Use `Box<[Box<str>]>` instead of `Vec<String>` for collections of strings in rule options to save memory
Applied to files:
crates/biome_html_analyze/Cargo.tomlcrates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/spec_tests.rs : Use the `tests_macros::gen_tests!` macro in `spec_tests.rs` to generate test functions for each specification file matching the pattern `tests/specs/<language>/**/*.<ext>`
Applied to files:
crates/biome_html_analyze/Cargo.toml
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When formatting AST nodes, use mandatory tokens from the AST instead of hardcoding token strings (e.g., use `node.l_paren_token().format()` instead of `token("(")`)
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Define `FormatHtmlSyntaxNode` struct in a `cst.rs` file implementing `FormatRule<HtmlSyntaxNode>`, `AsFormat<HtmlFormatContext>`, and `IntoFormat<HtmlFormatContext>` traits using the provided boilerplate code
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rscrates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the `FormatNode` trait and implement it for your Node when creating formatters in biome_js_formatter
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/lib.rs : Expose a public `format_node` function that accepts formatting options and a root syntax node, returning a `FormatResult<Formatted<Context>>` with appropriate documentation
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For tokens that are not mandatory, use helper functions instead of hardcoding
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/context.rs : Define `<Language>FormatContext` struct in a `context.rs` file containing `comments` and `source_map` fields, implementing `FormatContext` and `CstFormatContext` traits
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/lib.rs : Define a type alias `<Language>Formatter<'buf>` as `Formatter<'buf, <Language>FormatContext>` in the main formatter crate
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Create a new formatter crate using the command `just new-crate biome_<language>_formatter` where `<language>` is the target language (e.g., `biome_html_formatter` for HTML)
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use the `dbg_write!` macro to debug formatter output instead of other logging methods
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Implement the `FormatNodeRule<N>` trait with `fmt_fields` as the only required method; default implementations of `fmt`, `is_suppressed`, `fmt_leading_comments`, `fmt_dangling_comments`, and `fmt_trailing_comments` are provided
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_initializer_clause.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ConditionalParsedSyntax` for syntax that is only valid in specific contexts (e.g., strict mode, file types, language versions) and call `or_invalid_to_bogus()` to convert to a bogus node if not supported
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Parse rules must take a mutable reference to the parser as their only parameter and return a `ParsedSyntax`
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `p.eat(token)` for optional tokens, `p.expect(token)` for required tokens, `parse_rule(p).ok(p)` for optional nodes, and `parse_rule(p).or_add_diagnostic(p, error)` for required nodes
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Parse rules must return `ParsedSyntax::Absent` if the rule can't predict by the next token(s) if they form the expected node, and must not progress the parser in this case
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `diagnostic` function to provide error messages explaining what the error is, why it is triggered, and what the user should do
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : Nodes for enclosing syntax errors must have the `Bogus` word, e.g., `HtmlBogusAttribute`, and must be part of a variant
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-09T12:47:46.298Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8031
File: crates/biome_html_parser/src/syntax/svelte.rs:140-147
Timestamp: 2025-11-09T12:47:46.298Z
Learning: In the Biome HTML parser, `expect` and `expect_with_context` consume the current token and then lex the next token. The context parameter in `expect_with_context` controls how the next token (after the consumed one) is lexed, not the current token being consumed. For example, in Svelte parsing, after `bump_with_context(T!["{:"], HtmlLexContext::Svelte)`, the next token is already lexed in the Svelte context, so `expect(T![else])` is sufficient unless the token after `else` also needs to be lexed in a specific context.
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : All grammar nodes must start with the prefix of the language, e.g., `HtmlSimpleAttribute`
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : A parser struct must implement the `Parser` trait and save the token source, parser context, and optional parser options
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ParseSeparatedList` and `ParseNodeList` for parsing lists with error recovery to avoid infinite loops
Applied to files:
crates/biome_html_parser/src/syntax/svelte.rs
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
Applied to files:
.github/workflows/benchmark_html.yml
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use helper functions like `map`, `filter`, and `and_then` to avoid excessive nested `if let` statements
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Invalid code snippets in rule documentation must emit exactly one diagnostic
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `try operator (?)` to transform `Result` types into `Option` when the `run` function returns `Option`
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `.ok()?` to transform `Result` types into `Option` or `let else` pattern to handle errors when the function returns `Vec`
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement custom `Queryable` and `Visitor` types for rules that require deep inspection of child nodes to avoid inefficient traversals
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `run` function to return `Option<Self::State>` or `Vec<Self::State>` (as `Box<[Self::State]>`) depending on whether the rule reports one or multiple signals
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `rule_category!()` macro to refer to the diagnostic category instead of dynamically parsing its string name
Applied to files:
crates/biome_html_analyze/benches/html_analyzer.rs
🧬 Code graph analysis (1)
crates/biome_html_analyze/benches/html_analyzer.rs (2)
crates/biome_html_parser/src/lib.rs (1)
parse_html(37-40)crates/biome_html_syntax/src/file_source.rs (1)
html(43-47)
🪛 actionlint (1.7.10)
.github/workflows/benchmark_html.yml
42-42: label "depot-ubuntu-24.04-arm-16" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-11-arm", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xlarge", "macos-latest-large", "macos-26-xlarge", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xlarge", "macos-14-large", "macos-14", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
- GitHub Check: Check Dependencies
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: End-to-end tests
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Documentation
- GitHub Check: Bench (biome_module_graph)
- GitHub Check: Validate rules documentation
- GitHub Check: Bench (biome_package)
- GitHub Check: autofix
- GitHub Check: Bench (biome_tailwind_parser)
- GitHub Check: Bench (biome_css_parser)
- GitHub Check: Bench (biome_html_analyze)
- GitHub Check: Bench (biome_css_formatter)
- GitHub Check: Bench (biome_js_formatter)
- GitHub Check: Bench (biome_js_analyze)
- GitHub Check: Bench (biome_js_parser)
- GitHub Check: Bench (biome_json_formatter)
- GitHub Check: Bench (biome_json_analyze)
- GitHub Check: Bench (biome_html_parser)
- GitHub Check: Bench (biome_html_formatter)
- GitHub Check: Bench (biome_json_parser)
- GitHub Check: Bench (biome_css_analyze)
- GitHub Check: Bench (biome_graphql_parser)
- GitHub Check: Bench (biome_graphql_formatter)
- GitHub Check: Bench (biome_configuration)
🔇 Additional comments (11)
.github/workflows/benchmark_html.yml (3)
1-35: Workflow structure looks solid.Trigger conditions and path filters are appropriate for an HTML benchmark workflow.
73-79: Verify that the CODSPEED_TOKEN secret is configured.The CodSpeed action requires the
CODSPEED_TOKENsecret to upload benchmark results. Ensure this is configured in your repository secrets.
42-42: This runner is fine—it's Depot.dev in action.The
depot-ubuntu-24.04-arm-16label is used throughout your CI/CD pipeline (48+ workflows) without issue. Actionlint flags it as "unknown" because it doesn't recognise third-party runners by default, but Depot.dev integration is properly configured at the repository level. No changes needed here.crates/biome_html_analyze/Cargo.toml (2)
41-45: The dev-dependencies fortikv-jemallocatorandmimallocalready useworkspace = true, which is the correct approach per our guidelines. No changes needed here.Likely an incorrect or invalid review comment.
37-37: The exact version constraint=3.0.5for codspeed-criterion-compat is consistent across the entire codebase and appears intentional. No change needed here.Likely an incorrect or invalid review comment.
crates/biome_html_parser/src/syntax/svelte.rs (4)
1089-1128: LGTM!The two-phase approach (string prefix check followed by re-lexing) correctly handles the lexer's initial tokenisation of directive syntax. The context differentiation for
classandstyledirectives properly supports binding literals.
1130-1155: Solid implementation of directive value parsing.The empty text check (line 1138) correctly validates that content follows the colon, and the context-based branching appropriately handles different directive types. The re-lex at line 1151 properly resets context when no initialiser is present.
1158-1207: LGTM!The
parse_directivehelper andModifiersListimplementation follow the established parser patterns correctly. The use ofexpect_with_contextfor the pipe token is safe sinceparse_elementis only called when the token is present.
1228-1255: LGTM!The keyword additions and directive start detection correctly handle the lexer's initial tokenisation, enabling proper directive recognition. The string prefix matching in
is_at_svelte_directive_startis the appropriate approach for pre-lexing detection.xtask/codegen/html.ungram (2)
508-575: Well-structured and consistent directive grammar.The directive definitions follow a clean, consistent pattern across all 8 types, with a shared
SvelteDirectiveValuestructure. The grammar is intentionally permissive (allowing modifiers and literals on all directives), which aligns perfectly with the PR objective to defer semantic validation to a separate rule.The support for optional initialisers enables shorthand formatting (e.g.,
bind:valuewhen the variable name matches), which addresses the core requirement from issue #8600.
498-507: Confirm whether event handler directives are intentionally out of scope.The
on:directive for event handlers (e.g.,on:click={handler}) isn't implemented—no event handler parsing code exists in the codebase. Just confirming this is by design (Svelte 5 focus, deferred to a future PR, etc.) or if it should be added.
Summary
Closes #8600
This PR adds a specialised parsing of Svelte directives.
As decided in #8600, the parser won't check if the value of a directive is actually valid or not. We will do that in a separate rule (probably a syntax rule).
I also added benchmarks for HTML. I believe it's time, we're almost getting there.
Test Plan
I used AI to generate the tests.
Docs