2.4.5
Patch Changes
-
#9185
e43e730Thanks @dyc3! - Added the nursery ruleuseVueScopedStylesfor Vue SFCs. This rule enforces that<style>blocks have thescopedattribute (ormodulefor CSS Modules), preventing style leakage and conflicts between components. -
#9184
49c8fdeThanks @chocky335! - Improved plugin performance by batching all plugins into a single syntax visitor with a kind-to-plugin lookup map, reducing per-node dispatch overhead from O(N) to O(1) where N is the number of plugins. -
#9283
071c700Thanks @dyc3! - FixednoUndeclaredVariableserroneously flagging functions and variables defined in the<script setup>section of Vue SFCs. -
#9221
4612133Thanks @ematipico! - Fixed an issue where the JSON reporter didn't contain the duration of the command. -
#9294
1805c8fThanks @Netail! - Extra rule source reference.biome migrate eslintshould do a bit better detecting rules in your eslint configurations. -
#9178
101b3bbThanks @Bertie690! - Fixed #9172 and #9168:
Biome now considers more constructs as valid test assertions.Previously,
assert,expectTypeOfandassertType
were not recognized as valid assertions by Biome's linting rules, producing false positives inlint/nursery/useExpectand other similar rules.Now, these rules will no longer produce errors in test cases that used these constructs instead of
expect:import { expectTypeOf, assert, assertType } from "vitest"; const myStr = "Hello from vitest!"; it("should be a string", () => { expectTypeOf(myStr).toBeString(); }); test("should still be a string", () => { assertType<string>(myStr); }); it.todo("should still still be a string", () => { assert(typeof myStr === "string"); });
-
#9173
32dad2dThanks @dyc3! - Added parsing support for Svelte's new comments-in-tags feature.The HTML parser will now accept JS style comments in tags in Svelte files.
<button // single-line comment onclick={doTheThing} >click me</button> <div /* block comment */ class="foo" >text</div>
-
#8952
1d2ca15Thanks @pkallos! - Added the nursery ruleuseNullishCoalescing. This rule suggests using the nullish coalescing operator (??) instead of logical OR (||) when the left operand may be nullish. This prevents bugs where falsy values like0,'', orfalseare incorrectly treated as missing. Addresses #8043// Invalid declare const x: string | null; const value = x || "default"; // Valid const value = x ?? "default";
-
#9243
1992a85Thanks @Netail! - Fixed #7813: improved the diagnostic of the ruleuseExhaustiveDependencies. The diagnostic now shows the name of the variable to add to the dependency array. -
#9063
3d0648fThanks @taga3s! - Added the nursery rulenoVueRefAsOperand. This rule disallows cases where a ref is used as an operand.The following code is now flagged:
import { ref } from "vue"; const count = ref(0); count++; // Should be: count.value++
import { ref } from "vue"; const ok = ref(false); if (ok) { // Should be: if (ok.value) // }
-
#9273
f239e20Thanks @denbezrukov! - Fixed #9253: parsing of@container scroll-state(...)queries.@container scroll-state(scrolled: bottom) { } @container scroll-state(stuck) { } @container scroll-state(not (stuck)) { } @container scroll-state((stuck) and (scrolled: bottom)) { } @container scroll-state((stuck) or (snapped: x)) { } @container main-layout scroll-state(not ((stuck) and (scrolled: bottom))) { }
-
#9259
96939c0Thanks @ematipico! - Fixed CSS formatter incorrectly collapsing selectors when a BOM (Byte Order Mark) character is present at the start of the file. The formatter now correctly preserves line breaks between comments and selectors in BOM-prefixed CSS files, matching Prettier's behavior. -
#9251
59e33fbThanks @ematipico! - Fixed #9249: The CSS formatter no longer incorrectly breaks ratio values (like1 / -1) across lines when followed by comments. -
#9284
ec3a17fThanks @denbezrukov! - Fixed #9253: removed false-positive diagnostics for valid@container/@supportsgeneral-enclosed queries.@container scroll-state(scrolled: bottom) { } @supports foo(bar: baz) { }
-
#9215
b2619a1Thanks @FrederickStempfle! - Fixed #9189:biome ciin GitHub Actions now correctly disables colors so that::error/::warningworkflow commands are not wrapped in ANSI escape codes. -
#9256
65ae4c1Thanks @ematipico! - Fixed JSON reporter escaping of special characters in diagnostic messages. The JSON reporter now properly escapes double quotes, backslashes, and control characters in error messages and advice text, preventing invalid JSON output when diagnostics contain these characters. -
#9223
5b9da81Thanks @ematipico! - Fixed an issue where the JSON reporter didn't write output to a file when--reporter-filewas specified. The output is now correctly written to the specified file instead of always going to stdout. -
#9154
c487e54Thanks @abossenbroek! - Fixed #9115: ThenoPlaywrightMissingAwaitrule no longer produces false positives on jest-dom matchers liketoBeVisible,toBeChecked,toHaveAttribute, etc. For matchers shared between Playwright and jest-dom, the rule now checks whetherexpect()'s argument is a Playwright locator or page object before flagging. Added semantic variable resolution so that extracted Playwright locators (e.g.const loc = page.locator('.item'); expect(loc).toBeVisible()) are still correctly flagged. -
#9269
33e5cdfThanks @dyc3! - Fixed a false positive wherenoUndeclaredVariablesreported bindings from Vue<script setup>as undeclared when used in<template>.This change ensures embedded bindings collected from script snippets (like imports and
defineModelresults) are respected by the rule. -
#9267
2c2e060Thanks @ematipico! - Fixed #9143 and #8849: ThenoUnresolvedImportsrule no longer reports false positives for several common patterns:node:fs,node:path,node:url, and other Node.js built-in modules with thenode:prefix are now accepted.- Packages that declare their TypeScript entry point via
"typings"(instead of"types") inpackage.jsonnow resolve correctly. - Named imports from aliased re-export chains (e.g.
export { x as y } from "...") are now resolved correctly through the alias. - Namespace re-exports (e.g.
export * as Ns from "...") are now recognized as own exports of the barrel module.
-
#9254
f7bf12bThanks @ematipico! - Fixed #8842: The CSS formatter now correctly formats@container scroll-state()without adding an unwanted space between the function name and opening parenthesis. -
#9211
2d0b8e6Thanks @ematipico! - Fixed #7905. Improved the accuracy of type-aware lint rules when analyzing re-exported functions and values.Previously, when a binding was imported from another module, its type was not correctly inferred during the type analysis phase. This caused type-aware lint rules to fail to detect issues when working with re-exported imports.
The following rules now correctly handle re-exported imports:
Example of now-working detection:
// getValue.ts export async function getValue(): Promise<number> { return 42; } // reexport.ts export { getValue } from "./getValue"; // index.ts import { getValue } from "./reexport"; // Previously: no diagnostic (type was unknown) // Now: correctly detects that getValue() returns a Promise await getValue(); // Valid - properly awaited getValue(); // Diagnostic - floating promise
-
#8934
b49707cThanks @tim-we! - Fixed #8265: Biome now correctly detects test framework calls that use three arguments (label, options, callback) (e.g.,describe("foo", { retry: 2 }, () => {})). This fixes both formatting and thenoDuplicateTestHookslint rule for test frameworks like Vitest. -
#9191
688fd34Thanks @dyc3! - Fixed #9180: fixed a panic caused by an interaction betweennoRedundantUseStrictand the formatter -
#9048
9bbdf4dThanks @ff1451! - Added the nursery ruleuseNamedCaptureGroup.
The rule enforces using named capture groups in regular expressions instead of numbered ones. It supports both regex literals andRegExpconstructor calls.// Invalid: unnamed capture group /(foo)/; new RegExp("(foo)"); // Valid: named capture group /(?<id>foo)/; new RegExp("(?<id>foo)");
-
#9255
9b6685bThanks @ematipico! - Fixed#9234, where some nursery rules panicked when they were configured with the optionlevelwithout the correspondingoptions. -
#8968
a2b4494Thanks @LouisLau-art! - Fixed #8812:lint/suspicious/noArrayIndexKeywill now report index usage anywhere in JSXkeytemplate or binary expressions, not only in the last visited identifier. -
#9266
84935a4Thanks @dyc3! - Fixed #9250:noVueDuplicateKeyswill no longer flag keys underwatch, preventing false positives. -
#9056
1f2fe2eThanks @ruidosujeira! - Added the nursery ruleuseArraySometo prefer.some()over verbose existence checks likefilter(...).length > 0andfindIndex(...) !== -1, with suggestions forfind/findLastexistence checks. This also applies to ES2025 iterator helpers such asIterator.prototype.find. -
#9163
f87acf6Thanks @JUSTIVE! - Addedgraphqlto valid embedded graphql template tags inside JavaScript files, when the featurejavascript.experimentalEmbeddedSnippetsEnabledis enabled. This allows proper support for graphql tags used in RelayJS.Now, code snippets like the following are correctly formatted and limited:
import { graphql } from "react-relay"; const query = graphql` query { user(id: 1) { id name } } `;
-
#8773
6b01778Thanks @xcb3d! - Added the new nursery ruleuseUnicodeRegex.The rule enforces the use of the
uorvflag for regular expressions. This ensures proper handling of Unicode characters like emoji.// Invalid /foo/; new RegExp("foo", "gi"); // Valid /foo/u; new RegExp("foo", "giu");
What's Changed
- test(markdown): add minimal service plumbing for formatter integration by @jfmcdowell in #9070
- feat(biome_js_analyze): implement
noVueRefAsOperandby @taga3s in #9063 - perf(parse/tailwind): use
lookup_bytefor slightly better throughput by @dyc3 in #9183 - refactor(core): move js semantic model by @ematipico in #8361
- feat(markdown): add prettier tests for markdown formatter by @tidefield in #9076
- fix(lint): code action for
noRedundantUseStrictno longer produces syntactically invalid nodes by @dyc3 in #9191 - chore(deps): update github-actions by @renovate[bot] in #9198
- chore(deps): update rust crate anyhow to 1.0.102 by @renovate[bot] in #9200
- chore(deps): update rust crate jiff to 0.2.21 by @renovate[bot] in #9201
- chore(deps): update pnpm to v10.30.1 by @renovate[bot] in #9204
- fix(deps): update @biomejs packages by @renovate[bot] in #9203
- chore(deps): update dependency tombi to v0.7.31 by @renovate[bot] in #9199
- feat: graphql as valid graphql tag by @JUSTIVE in #9163
- ci: reduce workflow triggering to cron schedule by @ematipico in #9207
- perf(linter): batch plugins into single visitor with anchor-kind dispatch by @chocky335 in #9184
- refactor(markdown): split list item parser by @jfmcdowell in #9167
- fix(lint): consider more constructs as valid test assertions by @Bertie690 in #9178
- feat(css): scss basic expressions by @denbezrukov in #9212
- fix(cli): json reporter by @ematipico in #9221
- fix(markdown-parser): promote blockquote prefix markers from skipped trivia to explicit CST nodes by @jfmcdowell in #9219
- fix(cli): json reporter file by @ematipico in #9223
- feat(css): add SCSS unary and binary expression by @denbezrukov in #9222
- fix: redact duration propertly by @ematipico in #9225
- feat(css): add scss keyword and arbitrary arguments by @denbezrukov in #9227
- feat(lint): add useNullishCoalescing nursery rule by @pkallos in #8952
- chore(deps): update rust crate regex to 1.12.3 by @renovate[bot] in #9202
- refactor(css): inline function argument expressions by @denbezrukov in #9241
- feat(parse/html/svelte): new svelte syntax for comments inside tags by @dyc3 in #9173
- fix(js_analyze): mention which dependency the useExhaustiveDependencies fix adds to the list by @Netail in #9243
- fix(cli): disable colors when GitHub Actions auto-enables github reporter by @FrederickStempfle in #9215
- ci: fix autofix by @ematipico in #9247
- refactor(yaml): accept a list of properties by @l0ngvh in #9220
- fix(noPlaywrightMissingAwait): fix false positives with jest-dom matchers by @abossenbroek in #9154
- feat: prefer-array-some from eslint-plugin-unicorn by @ruidosujeira in #9056
- fix(noDuplicateTestHooks): check for options argument by @tim-we in #8934
- refactor: use semantic model for module graph by @ematipico in #9211
- fix(css/parser): correctly parse container query scroll-state by @ematipico in #9254
- perf(rowan): text edits by slicing text by @ematipico in #9252
- fix(css/parser): bom parsing by @ematipico in #9259
- refactor(markdown-parser): promote pre-marker indent to explicit CST by @jfmcdowell in #9224
- refactor(markdown-parser): extract magic numbers to named constants by @jfmcdowell in #9228
- fix(analyzer): some rules panicked by @ematipico in #9255
- fix(css/formatter): ratio printing by @ematipico in #9251
- refactor(markdown-parser): replace remaining magic numbers with named constants by @jfmcdowell in #9264
- feat(lint): add nursery rule useNamedCaptureGroup by @ff1451 in #9048
- fix(noVueDuplicateKeys): fix false positives when keys are defined in
watchby @dyc3 in #9266 - refactor(markdown-parser): deduplicate link scan/parse with BumpMode by @jfmcdowell in #9192
- feat(lint): add ||= to ??= detection in useNullishCoalescing by @pkallos in #9257
- fix(lint): noArrayIndexKey should flag index anywhere in template by @LouisLau-art in #8968
- fix(dx): deny
type Options = ()in rules by @dyc3 in #9281 - fix(cli): json reporter escaping by @ematipico in #9256
- fix(noUndeclaredVariables): consult embedded bindings service before flagging false positives by @dyc3 in #9269
- feat(css): add support for
@container scroll-stateat-rule and associated queries by @denbezrukov in #9273 - feat(lint/html): add
useVueScopedStylesby @dyc3 in #9185 - chore(deps): update rust:1.93.1-bookworm docker digest to 7c4ae64 by @renovate[bot] in #9289
- chore(deps): update rust:1.93.1-bullseye docker digest to fae8ebc by @renovate[bot] in #9290
- chore: extra rule source by @Netail in #9294
- fix(module_graph): properly index and resolve barrel exports by @ematipico in #9267
- fix(css): parse scroll-state and general-enclosed queries by @denbezrukov in #9284
- feat(linter): add useUnicodeRegex rule by @xcb3d in #8773
- fix(noUndeclaredVariables): fix false positives for functions and variables defined in vue
<script setup>components by @dyc3 in #9283 - ci: release by @github-actions[bot] in #9188
New Contributors
- @JUSTIVE made their first contribution in #9163
- @chocky335 made their first contribution in #9184
- @pkallos made their first contribution in #8952
- @FrederickStempfle made their first contribution in #9215
- @xcb3d made their first contribution in #8773
Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.4...@biomejs/biome@2.4.5