All versions since 2.4.14
2.4.14
Patch Changes
-
#9393
491b171Thanks @dyc3! - Added the nursery ruleuseTestHooksOnTopin thetestdomain. The rule flags lifecycle hooks (beforeEach,beforeAll,afterEach,afterAll) that appear after test cases in the same block, enforcing that hooks are defined before any test case. -
#10157
eefc5abThanks @dyc3! - Fixed #7882: The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as<br></br>. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags. -
#10054
0e9f569Thanks @minseong0324! -noMisleadingReturnTypeno longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to: object.A function annotated
: objectreturning an object literal:function f(): object {return { retry: true };} -
#10116
53269ebThanks @jiwon79! - Fixed #6201:noUselessEscapeInRegexno longer flags an escaped backslash followed by-as a useless escape. Patterns like/[\\-]/are now considered valid because the second\is the escaped backslash, not an unnecessary escape of the trailing dash. -
#10092
33d8543Thanks @Conaclos! - Fixed #9097:organizeImportsno longer adds a blank line between a never-matched group and a matched group.Given the following
organizeImportsoptions:{"groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"]}The following code…
// Commentimport "package";import "./file.js";…was organized as:
// Commentimport "package";import "./file.js";A blank line was added even though the group ‘:NODE:’ doesn’t match any imports here.
:BLANK_LINE:between never-matched groups and matched groups are now ignored. The code is now organized as:// Commentimport "package";import "./file.js"; -
#10138
a10b6c1Thanks @dyc3! - Fixed Vuev-forhandling fornoUndeclaredVariablesandnoUnusedVariables. Biome now recognizes variables declared byv-fordirectives and references to iterated values in Vue templates. -
#10115
d428d76Thanks @minseong0324! -noMisleadingReturnTypeno longer reports false positives when a union return type’sbooleanvariant is covered by bothtrueandfalsereturns. -
#9922
7acf1e0Thanks @dyc3! - Added the new nursery rulenoReactStringRefs, which disallows legacy React string refs such asref="hello"andthis.refs.hello.Biome also reports template-literal refs such as
ref={`hello`}, so React code can consistently migrate to callback refs,createRef(), oruseRef(). -
#10010
f3e76abThanks @dyc3! - Fixed a bug in the LSP file watcher registration so Biome now watches.biome.jsonand.biome.jsoncconfiguration files and reloads workspace settings when they change. -
#10176
8a40ef8Thanks @dyc3! - Fixed #10011: ThenoThisInStaticrule no longer reportsthiswhen it is used as the constructor target innew this(...), which is required for inherited static factory methods. -
#10163
6867e96Thanks @jiwon79! - Fixed #9884: TheuseSortedAttributesauto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic. -
#10079
d29dd19Thanks @Damix48! - Fixed false positive innoAssignInExpressionsfor Svelte{@const}blocks. Assignments in{@const name = value}are now correctly recognized as declarations rather than accidental assignments in expressions. -
#10080
5d8fdacThanks @Damix48! - Fixed parsing of closing parentheses in Svelte{#each}block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys.For example, the following snippets are now parsed correctly:
{#each numbers as number, index (number.toString())}<p>{number}</p>{/each}{#each numbers as number (key(number))}<p>{number}</p>{/each} -
#10140
e7024b9Thanks @solithcy! - Fixed #10135: Biome no longer crashes on missing Svelte template expressions.The following code snippet longer panics:
{#if }<p>^ this would previously crash</p>{/if}{@const }<p> ^ this would also crash</p> -
#10111
7818009Thanks @jiwon79! - Fixed #9997:noDuplicateSelectorsno longer reports false positives for selectors inside@scopequeries. Biome now treats@scopeas a separate at-rule context, like@media,@supports,@container, and@starting-style.The following snippet is no longer flagged as a duplicate:
.Example {padding: 0;}@scope (.theme-dark) {.Example {color: white;}} -
#9926
d62b331Thanks @dyc3! - Added the nursery lint ruleuseMathMinMax, which prefersMath.min()andMath.max()over equivalent ternary comparisons.For example, this code:
const min = a < b ? a : b;is much more readable when rewritten as:
const min = Math.min(a, b); -
#10115
d428d76Thanks @minseong0324! -useExhaustiveSwitchCasesnow flags missingtrue/falsecases forbooleandiscriminants, including whenbooleanis a union variant. -
#10125
a55a0b6Thanks @bmish! - Fixed a resolver bug where packages that define a typed entry point throughpackage.json’smainfield but omittypeswere ignored during type-aware resolution. Type-aware rules such asnoFloatingPromisescan now inspect imports from those packages. -
#10117
895e809Thanks @denizdogan! - Added support for thecorner-shapefamily of CSS properties and thesuperellipse()/squircle()value functions, sonoUnknownPropertyandnoUnknownFunctionno longer flag them as unknown.New known properties:
corner-shape,corner-block-end-shape,corner-block-start-shape,corner-bottom-left-shape,corner-bottom-right-shape,corner-bottom-shape,corner-end-end-shape,corner-end-start-shape,corner-inline-end-shape,corner-inline-start-shape,corner-left-shape,corner-right-shape,corner-start-end-shape,corner-start-start-shape,corner-top-left-shape,corner-top-right-shape,corner-top-shape.New known value functions:
superellipse(),squircle(). -
#8620
8df8f73Thanks @dyc3! - Fixed #8062: Added support for parsing Vuev-fordirectives more accurately. -
#10191
aa055cdThanks @guney! - Now the rulenoStaticElementInteractionsdoesn’t trigger custom elements. -
#9757
2c62594Thanks @dyc3! - Fixed #9099: the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user’s intended line breaks for exclusively non-text children.For example, the following Svelte snippet is now preserved instead of being collapsed to
<div>{name}<!-- comment --></div>:<div>{name}<!-- comment --></div>Similarly, HTML elements like
<span>inside a<div>are now preserved when written on their own line:<div><span>text</span></div> -
#10105
e7c1a6dThanks @jiwon79! - Fixed #10039:useReadonlyClassPropertiesnow detects unreassigned private members in class expressions and export default classes, not only in class declarations.The following patterns are now correctly flagged:
const AnonClass = class {#prop = 123;constructor() {console.log(this.#prop);}};export default class {#prop = 123;constructor() {console.log(this.#prop);}} -
#10141
46a77d0Thanks @minseong0324! - ImprovednoUnnecessaryConditionsto detect conditions that are always truthy because they check built-in global class instances such asDate,Map,Set,WeakMap, andError. -
#10178
7b05a89Thanks @dyc3! - Fixed #10177: The HTML parser no longer reports lowercasehtmlordoctypetext as invalid after void elements such as<br>. -
#10155
0d4595dThanks @jiwon79! - Fixed #10045: the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as:not(:where(...)),:is(:where(...)), and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including:nth-child(... of ...),::part(...), and:active-view-transition-type(...). The following snippet is now correctly formatted, matching Prettier.input:not(:where([type="submit"],[type="checkbox"],[type="radio"],[type="button"],[type="reset"])) {inline-size: 100%;} -
#10112
6f0251eThanks @dyc3! - Fixed #10110: Biome’s parser now accepts surrogate code points in JavaScript string\u{...}escapes. -
#10141
46a77d0Thanks @minseong0324! - ImprovednoMisleadingReturnTypeto detectobjectreturn annotations that hide built-in global class instances such asDate,Map,Set,WeakMap, andError. -
#10083
4a664c1Thanks @ematipico! - Added two new options tonoShadow, both defaulting totrueto match typescript-eslint’s behavior.Fixed #9482: Added
ignoreFunctionTypeParameterNameValueShadowoption. When enabled, parameter names inside function type annotations (e.g.(options: unknown) => void) are not flagged as shadowing outer variables.Fixed #7812: Added
ignoreTypeValueShadowoption. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript. -
#9286
52695cfThanks @Hugo-Polloli! - Fixed #6316: Biome now resolves Svelte$storereferences to the underlyingstorebinding in semantic analysis, preventing falsenoUndeclaredVariablesdiagnostics when the store is declared. -
#10188
ae659ddThanks @dyc3! - Added a new nursery rulenoExcessiveNestedCallbacks, which disallows callbacks nested deeper than the configured maximum. -
#9757
2c62594Thanks @dyc3! - Fixed #9450: the HTML formatter now correctly preserves multiline formatting for nested<template>elements (e.g.<template #body>) when the source has children on separate lines. Previously, the children were collapsed onto a single line.<template><UModal><template #body> <p>content</p> </template><template #body><p>content</p></template></UModal></template> -
#10118
c6edcb4Thanks @Netail! - Fixed #10024:biome migrate eslintcorrectly migrateseslintrules that belong to multiple Biome rules.
2.4.15
Patch Changes
-
#9394
ba3480eThanks @dyc3! - Added the nursery ruleuseTestHooksInOrderin thetestdomain. The rule enforces that Jest/Vitest lifecycle hooks (beforeAll,beforeEach,afterEach,afterAll) are declared in the order they execute, making test setup and teardown easier to reason about. -
#10254
e0a54ccThanks @dyc3! - Added a new nursery ruleuseVueNextTickPromise, which enforces Promise syntax when using VuenextTick.For example, the following snippet triggers the rule:
import { nextTick } from "vue";nextTick(() => {updateDom();}); -
#10219
64aee45Thanks @dyc3! - Added a new nursery rulenoVueVOnNumberValues, that disallows deprecated number modifiers on Vuev-ondirectives.For example, the following snippet triggers the rule:
<input @keyup.13="submit" /> -
#10195
7b8d4e1Thanks @dyc3! - Added the new nursery ruleuseVueValidVFor, which validates Vuev-fordirectives and reports invalid aliases, missing component keys, and keys that do not use iteration variables. -
#10238
1110256Thanks @dyc3! - Added the recommended nursery rulenoVueImportCompilerMacros, which disallows importing Vue compiler macros such asdefinePropsfromvuebecause they are automatically available. -
#10201
1a08f89Thanks @realknove! - Fixed #10193:style/useReadonlyClassPropertiesno longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers. -
#9574
3bd2b6aThanks @Conaclos! - Fixed #9530. The diagnostics oforganizeImportsare now more detailed and more precise. They are also better at localizing where the issue is. -
#10205
a704a6cThanks @Conaclos! - Fixed #10185. `organizeImports now errors when it encounters an unknown predefined group.The following configuration is now reported as invalid because
:INEXISTENT:is an unknown predefined group.{"assist": {"actions": {"source": {"organizeImports": { "options": { "groups": [":INEXISTENT:"] } }}}}} -
#10052
b565bedThanks @minseong0324! - ImprovednoMisleadingReturnType: it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g.string | null→string).These functions are now reported because
nullandnumberare included in the return annotations but never returned:function getUser(): string | null {return "hello";} // null is never returnedfunction getCode(): string | number {return "hello";} // number is never returned -
#10213
ac30057Thanks @dyc3! - Fixed #9450: HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line. -
#10275
9ee6c03Thanks @solithcy! - Fixed #10274: Svelte templates with missing expressions no longer parsed asHtmlBogusElement -
#10143
56798a7Thanks @minseong0324! -noMisleadingReturnTypenow detects misleading return type annotations when object literal properties are initialized withas const.This function is now reported because the return annotation widens a property initialized with
as const:function f(): { value: string } {return { value: "text" as const };} -
#10143
56798a7Thanks @minseong0324! -noUselessTypeConversionnow detects redundant conversions on object literal properties initialized withas const.This conversion is now reported because
message.valueis inferred as a string literal:const message = { value: "text" as const };String(message.value); -
#9807
0ae5840Thanks @dyc3! - Added the new nursery ruleuseThisInClassMethods, based on ESLint’sclass-methods-use-this.The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use
this, andbiome migrate eslintpreserves the supportedignoreMethods,ignoreOverrideMethods, andignoreClassesWithImplementsoptions.Invalid:
class Foo {bar() {// does not use `this`, invalidconsole.log("Hello Biome");}} -
#10258
e7b18f7Thanks @ematipico! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated. -
#10273
04e22a1Thanks @dyc3! - Fixed #10271: The HTML parser now correctly parsesofas text content when in text contexts. -
#9838
83f7385Thanks @dyc3! - Added the nursery rulenoBaseToString, which reports stringification sites that fall back to Object’s default"[object Object]"formatting. The rule also supports theignoredTypeNamesoption. -
#10143
56798a7Thanks @minseong0324! -useExhaustiveSwitchCasesnow checks switch statements over object literal properties initialized withas const.This switch is now reported because
status.kindis inferred as the string literal"ready"but no case handles it:const status = { kind: "ready" as const };switch (status.kind) {} -
#10143
56798a7Thanks @minseong0324! -useStringStartsEndsWithnow detects string index comparisons on object literal properties initialized withas const.This comparison is now reported because
message.valueis inferred as a string literal:const message = { value: "hello" as const };message.value[0] === "h";
2.4.16
Patch Changes
-
#10329
ef764d5Thanks @Conaclos! - Fixed an issue where diagnostics showed an incorrect location in Astro files. -
#10363
50aa415Thanks @dyc3! - Fixed HTML formatting for a case where comments could cause the formatter to split up a closing tag, which would cause the resulting HTML to be syntactically invalid.Input:
<span><!-- 1--><span>a</span><!-- 2--><span>b</span><!-- 3--></span>Output:
<span><!-- 1--> <span>a</span<!-- 2--> ><span>b</span><!-- 3--><span>a</span><!-- 2--><span>b</span><!-- 3--></span> -
#10465
0c718daThanks @dfedoryshchev! - Fixed diagnostics emitted by thenoUntrustedLicensesrule. -
#10358
05c2617Thanks @dyc3! - Fixed #10356:biome rage --linternow displays rules enabled through linter domains in the enabled rules list. -
#10300
950247cThanks @dyc3! - Fixed #10265: Svelte function bindings such asbind:value={get, set}are now parsed more precisely, sonoCommaOperatorwon’t emit false positives for that syntax anymore. -
#9786
e71f584Thanks @MeGaNeKoS! - Fixed #8480:useDestructuringnow providesvariableDeclaratorandassignmentExpressionoptions to control which contexts enforce destructuring, matching ESLint’sprefer-destructuringconfiguration. Both default to{array: true, object: true}. The diagnostic for object destructuring in assignment expressions now instructs users to wrap the assignment in parentheses. -
#10425
1948b72Thanks @sjh9714! - Fixed #10244: TheuseOptionalChainrule now detects negated guard inequality chains like!foo || foo.bar !== "x". -
#10442
001f94fThanks @ematipico! - Fixed #10411:noMisusedPromisesno longer causes a stack overflow when a nested function returns an object with shorthand properties that shadow destructured variables from an outer scope. -
#10318
9b1577fThanks @dyc3! - Added support forformatter.trailingCommasin overrides. This option was previously available in the top-level formatter configuration but missing from formatter overrides. -
#10319
2e37709Thanks @dyc3! - Fixed Vue and Svelte formatting for standalone interpolations in inline elements. Biome now preserves existing newlines in cases like:<span> {{ value }} </span><span>{{ value }}</span> -
#10365
0a58eb0Thanks @Netail! - Fixed #10361:noUnusedFunctionParametersnow mentions the parameter name in the diagnostic. -
#10439
df6b867Thanks @denbezrukov! - Fixed CSS and SCSS formatting for comments around declaration colons so comments between property names, colons, and values stay at the same boundary as Prettier..selector {color: /* red, */blue;color: /* red, */ blue;} -
#10344
b30208cThanks @siketyan! - Fixed#10123: Corrected thenoReactNativeDeepImportssource rule to point to the proper upstream rule, so users can migrate from the original rule correctly. -
#10328
b59133fThanks @dyc3! - Fixed #10309: Biome no longer adds newlines to Astro frontmatter when linter or assist--writemode is enabled.
2.5.0 Latest
Minor Changes
-
#9539
f0615fdThanks @ematipico! - Added a new reporter calledconcise. When--reporter=conciseis passed the commandsformat,lint,checkandci, the diagnostics are printed in a compact manner:! index.ts:2:10: lint/correctness/noUnusedImports: Several of these imports are unused.! main.ts:9:7: lint/correctness/noUnusedVariables: This variable f is unused.× index.ts:8:5: lint/suspicious/noImplicitAnyLet: This variable implicitly has the any type.× main.ts:2:10: lint/suspicious/noRedeclare: Shouldn't redeclare 'z'. Consider to delete it or rename it. -
#9495
2056b23Thanks @aviraldua93! - Added theuseKeyWithClickEventsa11y lint rule for HTML files (.html,.vue,.svelte,.astro). This is a port of the existing JSX rule. The rule enforces that elements with anonclickhandler also have at least one keyboard event handler (onkeydown,onkeyup, oronkeypress) to ensure keyboard accessibility.Inherently keyboard-accessible elements (
<a>,<button>,<input>,<select>,<textarea>,<option>) are excluded, as are elements hidden from assistive technologies (aria-hidden) or withrole="presentation"/role="none".<!-- Invalid: no keyboard handler --><div onclick="handleClick()">Click me</div><!-- Valid: has keyboard handler --><div onclick="handleClick()" onkeydown="handleKeyDown()">Click me</div><!-- Valid: inherently keyboard-accessible --><button onclick="handleClick()">Submit</button> -
#9152
9ec8500Thanks @ematipico! - Added new nursery lint rulenoUndeclaredClassesfor HTML, JSX, and SFC files (Vue, Astro, Svelte). The rule detects CSS class names used inclass="..."(orclassName) attributes that are not defined in any<style>block or linked stylesheet reachable from the file.<!-- .typo is used but never defined --><html><head><style>.button {color: blue;}</style></head><body><div class="button typo"></div></body></html> -
#9152
9ec8500Thanks @ematipico! - Added new nursery lint rulenoUnusedClassesfor 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./* styles.css — .ghost is never used in any importing file */.button {color: blue;}.ghost {color: red;}App.jsx import "./styles.css";export default () => <div className="button" />; -
#9546
6567efaThanks @nhedger! - Added abiome upgradecommand for standalone installations. It upgrades Homebrew installs withbrew upgrade biome, updates manually installed binaries from the latest GitHub release, and tells npm users to upgrade with their package manager instead. -
#9716
701767aThanks @faizkhairi! - Added the HTML version of theuseHeadingContentrule. The rule now enforces that heading elements (h1-h6) have content accessible to screen readers in HTML, Vue, Svelte, and Astro files.<!-- Invalid: empty heading --><h1></h1><!-- Invalid: heading hidden from screen readers --><h1 aria-hidden="true">invisible content</h1><!-- Valid: heading with text content --><h1>heading</h1><!-- Valid: heading with accessible name --><h1 aria-label="Screen reader content"></h1> -
#9582
f437ef8Thanks @rahuld109! - Added the HTML version of theuseKeyWithMouseEventsrule. The rule now enforces thatonmouseoveris accompanied byonfocusandonmouseoutis accompanied byonblurin HTML, Vue, Svelte, and Astro files.<!-- Invalid: onmouseover without onfocus --><div onmouseover="handleMouseOver()"></div><!-- Valid: onmouseover paired with onfocus --><div onmouseover="handleMouseOver()" onfocus="handleFocus()"></div> -
#9275
1fdbceeThanks @ff1451! - Added the new assist actionuseSortedTypeFields, which sorts the fields of GraphQL object types, interface types and input object types alphabetically, e.g.name, age, idbecomesage, id, name. -
#10561
78075b7Thanks @Conaclos! - Added a newstyleoption to useExportType, which enforces a style for exporting types. This is the same option as the one provided byuseImportType. -
#8987
d16e32bThanks @DerTimonius! - Ported theuseValidAnchorrule to HTML. This rule enforces that all anchors are valid and that they are navigable elements. -
#9533
4d251d4Thanks @ematipico! - Theinitcommand now prints the Biome logo. -
#10069
0eb9310Thanks @Netail! - Added the HTML lint rulenoStaticElementInteractions, which enforces that static, visible elements (such as<div>) that have click handlers use the valid role attribute.Invalid:
<div onclick="myFunction()"></div> -
#9134
2a43488Thanks @ematipico! - Added the assist actionuseSortedPackageJson.This action organizes package.json fields according to the same conventions as the popular sort-package-json tool.
-
#9309
7daa18bThanks @Bertie690! - TheallowDoubleNegationoption has been added tonoImplicitCoercionsto allow ignoring double negations inside code.With the option enabled, the following example is considered valid and is ignored by the rule:
const truthy = !!value; -
#9700
894f3fbThanks @ematipico! - The Biome Language server now supports the “go-to definition” feature.When the cursor of the mouse is hovering an entity (variable, CSS class, type, etc.), and the command CTRL + click is triggered, the editor jumps to where this entity is defined, if the language server can find it.
Here’s what Biome is able to resolve:
- Variables and types used in JavaScript modules, defined in the same file or imported from another module.
- JSX Components used in JavaScript modules, defined in the same file or imported from another module.
- CSS classes used in JSX and HTML-ish files (Vue, Svelte and Astro), and defined in CSS files.
- Components used in HTML-ish files and defined in other HTML-ish.
- Variables used in HTML-ish files and defined in the same file or imported from another module (JavaScript or HTML-ish).
-
#10070
bae0710Thanks @Conaclos! - Added the:STYLE:group matcher fororganizeImportsthat matches style imports.For example, the following configuration…
{"assist": {"actions": {"source": {"organizeImports": {"level": "on","options": {"groups": ["**", "!:STYLE:"],"sortBareImports": true}}}}}}…places style imports last:
import "./style.css"import A from "./a.js"import "./style.css" -
#9170
e3107deThanks @mdrobny! - AddedbundleDependenciesoption to NoUndeclaredDependencies rule.This rule now supports imports of packages that are defined only in
bundleDependenciesandbundledDependenciesarrays. -
#9547
01f8473Thanks @mujpao! - Added new assist ruleuseSortedAttributesfor HTML, porting the existing JSX rule. This rule enforces sorted HTML attributes.Invalid
<input type="text" id="name" name="name" /> -
#9366
2ca1117Thanks @dyc3! - Added thehtml.parser.vueconfiguration option. When enabled, it adds support for the parsing of Vue in.htmlfiles. Most Vue users don’t need to enable this option since Vue files typically use the.vueextension, but it can be useful for projects that embed Vue syntax in regular HTML files. -
#9073
74b20eeThanks @chocky335! - Added support for applying GritQL plugin rewrites as code actions. GritQL plugins that use the rewrite operator (=>) now produce fixable diagnostics for JavaScript, CSS, and JSON files. By default, plugin rewrites are treated as unsafe fixes and require--write --unsafeto apply. Plugin authors can passfix_kind = "safe"toregister_diagnostic()to mark a fix as safe, allowing it to be applied with just--write.Example plugin (
useConsoleInfo.grit):language js`console.log($msg)` as $call where {register_diagnostic(span = $call, message = "Use console.info instead of console.log.", severity = "warn", fix_kind = "safe"),$call => `console.info($msg)`}Running
biome check --writeapplies safe rewrites. Unsafe rewrites (the default, orfix_kind = "unsafe") still require--write --unsafe. -
#9384
f4c9edcThanks @Conaclos! - Added thesortBareImportsoption toorganizeImports, which allows bare imports to be sorted within other imports when set tofalse.{"assist": {"actions": {"source": {"organizeImports": {"level": "on","options": { "sortBareImports": true }}}}}}import "b";import "a";import "b";import { A } from "a";import "./file";import { Local } from "./file";import "./file"; -
#8731
e7872bfThanks @siketyan! - Added the watch mode (--watch) to the CLI forcheck/format/lintcommands. By enabling this option, Biome will re-run the check automatically when any file in the workspace has changed after the first run. -
#10106
9b35f78Thanks @ematipico! - Biome can now format and lint.svgfiles. -
#9967
e9b6c17Thanks @dyc3! - Added HTML support fornoExcessiveLinesPerFile. Biome now reports HTML files that exceed the configured line limit, including whenskipBlankLinesis enabled. -
#9491
b3eb63cThanks @IxxyDev! - Added the HTML lint rulenoAriaUnsupportedElements. This rule enforces that elements that do not support ARIA roles, states, and properties (meta,html,script,style) do not haveroleoraria-*attributes.<!-- Invalid: meta does not support aria attributes --><meta charset="UTF-8" role="meta" /> -
#9306
afd57a6Thanks @viraxslot! - Added thenoNoninteractiveTabindexlint rule for HTML. This rule enforces thattabindexis not used on non-interactive elements, as it can cause usability issues for keyboard users.<div tabindex="0">Invalid: non-interactive element</div>` -
#9276
6d041d9Thanks @IxxyDev! - Added the HTML lint rulenoRedundantRoles. This rule enforces that explicitroleattributes are not the same as the implicit/default role of an HTML element. It supports HTML, Vue, Svelte, and Astro files.<!-- Invalid: role="button" is redundant on <button> --><button role="button"></button> -
#9813
69aadc2Thanks @ematipico! - Added a new linter configuration calledpreset. With the new option, users can enable different kinds of rules at once.The following presets are available:
"recommended": it enables all Biome-recommended rules, or recommended rules of a group;"all": it enables all Biome rules, or enables all rules of a group;"none": it disables all Biome rules, or disable all rules of a group.
You can enable recommended rules:
{"linter": {"rules": {"preset": "recommended"}}}You can enable all rules at once:
{linter: {rules: {preset: "all", // enables all rules},},}Or enable all rules for a group:
{linter: {rules: {style: {preset: "all", // enables all rules in the style group},},},}This new option, however, doesn’t affect how nursery rules work. Nursery rules must be enabled singularly, due to their nature.
This new option is meant to replace
recommended, so make sure to run themigratecommand. -
#10022
3422d71Thanks @Netail! - Added the HTML lint rulenoNoninteractiveElementToInteractiveRole, which enforces that interactive ARIA roles are not assigned to non-interactive HTML elements.Invalid:
<h1 role="checkbox"></h1> -
#8396
13785fcThanks @apple-yagi! - Biome now supports pnpm catalogs (default and named) when resolving dependencies for linting. This behavior is opt-in and requires settingjavascript.resolver.experimentalPnpmCatalogstotrue. -
#10028
1009414Thanks @Netail! - Added the HTML lint rulenoInteractiveElementToNoninteractiveRole, which enforces that non-interactive ARIA roles are not assigned to interactive HTML elements.Invalid:
<input role="img" /> -
#9853
816302fThanks @Netail! - Added the new assist actionuseSortedSelectionSet, which sorts GraphQL selection sets alphabetically, e.g.name, age, idbecomesage, id, name.Invalid:
query {nameageid} -
#10074
9c7c6ebThanks @georgephillips! - Added akindfield to theImportMatcherused by theorganizeImportsassist action. The new field selects imports by their syntactic kind and currently supportsbare(matching side-effect imports such asimport "polyfill") with optional!negation (!bare). The matcher composes with the existingtypeandsourcefields, so users can express patterns such as “only bare imports that import a CSS file” ({ "kind": "bare", "source": "**/*.css" }).For example, with the following configuration:
{"assist": {"actions": {"source": {"organizeImports": {"level": "on","options": {"sortBareImports": true,"groups": [{ "kind": "!bare" },":BLANK_LINE:",{ "kind": "bare" }]}}}}}}…the following code:
import "./register-my-component";import { render } from "react-dom";import "./polyfill";import { Button } from "@/components/Button";…is organized as:
import { render } from "react-dom";import { Button } from "@/components/Button";import "./polyfill";import "./register-my-component"; -
#9171
ce65710Thanks @chocky335! - Addedincludesoption for plugin file scoping. Plugins can now be configured with glob patterns to restrict which files they run on. Use negated globs for exclusions.{"plugins": ["global-plugin.grit",{"path": "scoped-plugin.grit","includes": ["src/**/*.ts", "!**/*.test.ts"]}]} -
#9617
dcb99efThanks @faizkhairi! - PorteduseAriaActivedescendantWithTabindexa11y rule to HTML. -
#9496
1dfb829Thanks @aviraldua93! - Added HTML support for thenoAriaHiddenOnFocusableaccessibility lint rule, which enforces thataria-hidden="true"is not set on focusable elements. Focusable elements include native interactive elements (<button>,<input>,<select>,<textarea>), elements withhref(<a>,<area>), elements withtabindex >= 0, and editing hosts (contenteditable). Includes an unsafe fix to remove thearia-hiddenattribute.<!-- Invalid: aria-hidden on a focusable element --><button aria-hidden="true">Submit</button><!-- Valid: aria-hidden on a non-focusable element --><div aria-hidden="true">decorative content</div> -
#9792
f516854Thanks @Maximiliano-Zeballos! - Added theuseSemanticElementslint rule for HTML. The rule now detects the use ofroleattributes in HTML elements and suggests using semantic elements instead.For example, the following code is now flagged:
<div role="navigation"></div>The rule suggests using
<nav>instead. -
#9761
cbbb7d5Thanks @Maximiliano-Zeballos! - Ported theuseValidAriaPropslint rule to HTML. This rule checks that allaria-*attributes used in HTML elements are valid ARIA attributes as defined by the WAI-ARIA specification. -
#9928
aa82576Thanks @aviraldua93! - PorteduseValidAriaValuesto HTML. Biome now validates staticaria-*attribute values in HTML elements against WAI-ARIA types, catching invalid values such asaria-hidden="yes". -
#10562
6642895Thanks @ematipico! - Promoted 73 nursery rules to stable groups.Four rules were renamed as part of the promotion:
noFloatingClassesis nownoUnusedInstantiation, because the rule checks any discardednewexpression, not only classes.noMultiStris nownoMultilineString.useFindis nowuseArrayFind.useSpreadis nowuseSpreadOverApply, because the rule enforces spread call arguments overFunction.apply(), not array or object spread.
Correctness
Promoted the following rules to the
correctnessgroup:noBeforeInteractiveScriptOutsideDocumentnoUnusedInstantiationuseInlineScriptId(recommended, Next.js domain)noVueVIfWithVFor(recommended, Vue domain)useVueValidVBind(recommended, Vue domain)useVueValidVElse(recommended, Vue domain)useVueValidVElseIf(recommended, Vue domain)useVueValidVHtml(recommended, Vue domain)useVueValidVIf(recommended, Vue domain)useVueValidVOn(recommended, Vue domain)useVueValidVText(recommended, Vue domain)useVueValidTemplateRoot(recommended, Vue domain)useVueValidVCloak(recommended, Vue domain)useVueValidVOnce(recommended, Vue domain)useVueValidVPre(recommended, Vue domain)useVueVForKey(recommended, Vue domain)noDuplicateAttributes(recommended)noDuplicateArgumentNames(recommended)noDuplicateInputFieldNames(recommended)noDuplicateVariableNames(recommended)noDuplicateEnumValueNames(recommended)useLoneAnonymousOperation(recommended)
Suspicious
Promoted the following rules to the
suspiciousgroup:noShadownoUnnecessaryConditionsnoParametersOnlyUsedInRecursionnoUnknownAttributeuseArraySortComparenoForInnoDuplicatedSpreadPropsnoEqualsToNullnoProto(recommended)noUndeclaredEnvVars(recommended, Turborepo domain)noReturnAssign(default severity:error)noDuplicateEnumValues(recommended)noVueArrowFuncInWatch(recommended, Vue domain)noNestedPromisesnoLeakedRendernoDeprecatedMediaType(recommended)noDuplicateGraphqlOperationNameuseRequiredScripts
Style
Promoted the following rules to the
stylegroup:useVueMultiWordComponentNames(recommended, Vue domain)useVueDefineMacrosOrdernoIncrementDecrementnoContinueuseSpreadOverApplynoTernarynoMultilineStringnoMultiAssignnoExcessiveClassesPerFilenoExcessiveLinesPerFilenoVueOptionsApiuseErrorCauseuseConsistentEnumValueTypeuseConsistentMethodSignaturesuseGlobalThis(default severity:warn)useDestructuringuseVueHyphenatedAttributes(recommended, Vue domain)useVueConsistentVBindStyle(recommended, Vue domain)useVueConsistentVOnStyle(recommended, Vue domain)noHexColorsuseConsistentGraphqlDescriptionsnoRootTypeuseLoneExecutableDefinitionuseInputName
Complexity
Promoted the following rules to the
complexitygroup:useArrayFindnoRedundantDefaultExport(default severity:warn)noUselessReturnnoDivRegex
Performance
Promoted the following rules to the
performancegroup:Security
Promoted the following rules to the
securitygroup:noScriptUrl(recommended)
A11y
Promoted the following rules to the
a11ygroup:noAmbiguousAnchorText(recommended)
-
#10121
450f8e1Thanks @jongwan56! - Biome now applies Git’s local exclude file when VCS ignore files are enabled. Files listed in.git/info/excludeare skipped the same way as files listed in.gitignore, including in linked worktrees. -
#9397
d5913c9Thanks @mvarendorff! - Addedignoreoption to the noUnusedVariables rule. The option allows excluding identifiers by providing a list of ignored names. It also allows excluding kinds of identifiers from this rule entirely, which may be useful when loading classes dynamically.For example, unused classes as well as all unused variables, functions, etc. called “unused” may be ignored entirely with the following configuration:
{"ignore": {"*": ["unused"],"class": ["*"]}} -
#10089
71a21f0Thanks @Netail! - Added the lint rulenoLabelWithoutControlto HTML, which enforces that a label element or component has a text label and an associated input.<label></label> -
#10015
1828261Thanks @Netail! - Added the HTML lint ruleuseAriaPropsSupportedByRole, which enforces that ARIA properties are valid for the roles that are supported by the element.<a href="#" aria-checked></a> -
#10234
1a51569Thanks @ematipico! - Added thedelimiterSpacingformatter option. This option inserts spaces inside delimiters (after the opening delimiter and before the closing delimiter) when the content fits on a single line. Empty delimiters are not affected, and no space is added before the opening delimiter. The specific delimiters affected depend on the language. It can be configured globally viaformatter.delimiterSpacingor per-language viajavascript.formatter.delimiterSpacing,json.formatter.delimiterSpacing, andcss.formatter.delimiterSpacing. Defaults tofalse.callFn(foo)callFn( foo )const arr = [1, 2, 3];const arr = [ 1, 2, 3 ];JavaScript
When enabled, Biome inserts spaces inside parentheses (e.g.,
foo( a, b )), square brackets (e.g.,[ a, b ]), template literal interpolations (e.g.,${ expr }), and the logical NOT operator (e.g.,! x, but in chains only after the last one:!! x). Only applies when the content fits on a single line. Empty delimiters and the space before the opening delimiter are not affected.if (condition) {}if ( condition ) {}`Hello ${name}!``Hello ${ name }!`JSX
When enabled, Biome inserts spaces inside JSX expression braces (e.g.,
attr={ value }) and spread attributes (e.g.,{ ...props }). Only applies when the content fits on a single line. Empty delimiters are not affected.<Foo bar={value} /><Foo bar={ value } />TypeScript
When enabled, Biome inserts spaces inside TypeScript angle brackets (e.g.,
foo< T >()), indexed access types (e.g.,T[ K ]), mapped types, tuple types, type parameters, and index signatures. Only applies when the content fits on a single line. Empty delimiters are not affected.type Result = Map<string, number>;type Result = Map< string, number >;JSON
When enabled, Biome inserts spaces inside square brackets when the content fits on a single line. Empty brackets are not affected.
[1, 2, 3][ 1, 2, 3 ]CSS
When enabled, Biome inserts spaces inside parentheses and square brackets when the content fits on a single line. Empty delimiters are not affected.
rgba(0, 0, 0, 1)rgba( 0, 0, 0, 1 )[data-attr][ data-attr ] -
#10461
6bac1c3Thanks @TXWSLYF! - Implements #9445. Added theallowImplicitoption touseIterableCallbackReturn. When enabled, callbacks can usereturn;to implicitly returnundefined, matching ESLint’sarray-callback-returnrule. -
#9571
5a8eb75Thanks @dyc3! - Added configurable options to theuseNumericSeparatorsrule. Users can now customize the minimum number of digits required before adding separators and the group length for each type of numeric literal (binary,octal,decimal,hexadecimal).{"linter": {"rules": {"style": {"useNumericSeparators": {"level": "error","options": {"decimal": {"minimumDigits": 7,"groupLength": 3},"hexadecimal": {"minimumDigits": 4,"groupLength": 2}}}}}}} -
#10067
6064312Thanks @Netail! - Added the lint ruleuseFocusableInteractiveto HTML, which enforces elements with an interactive role and interaction handler to be focusable.Invalid:
<div role="button"></div> -
#10026
fb42ac4Thanks @Netail! - Added the HTML lint rulenoNoninteractiveElementInteractions, which disallows use event handlers on non-interactive elements.Invalid:
<div onclick="myFunction()">button</div> -
#10000
2093e3eThanks @Netail! - Added the new assist actionuseSortedEnumMembers, which sorts TypeScript & GraphQL enum members.Invalid:
enum Role {SUPER_ADMINADMINUSERGOD} -
#10013
ad01d3dThanks @Netail! - Added the HTML lint ruleuseValidAutocomplete, which enforces using valid values for theautocompleteattribute oninputelements.<input autocomplete="incorrect" />
Patch Changes
-
#10498
995c1ffThanks @citadelgrad! - Added the nursery ruleuseReactFunctionComponentDefinition, which enforces a consistent function type for named React function components.For example, the following snippet triggers the rule by default.
const MyComponent = (props) => {return <div>{props.name}</div>;}; -
#9974
ff635a9Thanks @pkallos! - AddedignoreMixedLogicalExpressionsto useNullishCoalescing, partially addressing #9232. When enabled, Biome ignores||and||=mixed with&&in the same expression tree. -
#10503
c656679Thanks @Mokto! - Added the new nursery ruleuseSvelteRequireEachKey, a Svelte lint rule that reports{#each}blocks with item bindings that are missing a key. -
#10516
0f29b83Thanks @Dotify71! - AddeduseIncludesto the nursery group. This rule flags comparisons ofString.prototype.indexOf()orArray.prototype.indexOf()against-1and suggests replacing them with the clearerincludes()/!includes()form. -
#10487
0c03ee3Thanks @Mokto! - Fixed a Svelte parser error that incorrectly required a binding variable after{:then}and{:catch}. Biome now correctly accepts{:then}and{:catch}without a binding, as well as the{#await expr then}and{#await expr catch}shorthand forms. -
#10566
a4a294cThanks @dyc3! - FixeduseVueHyphenatedAttributes: The rule now only reports diagnostics in Vue files and ignores SVG elements. -
#10565
72ccf3bThanks @dyc3! - FixeduseVueConsistentVBindStyle: The rule no longer reports argument-lessv-binddirectives because they cannot be converted to shorthand syntax. -
#10591
6e8557bThanks @xsourabhsharma! - Fixed #10563: Biome now parses comma-separated CSS Modulescomposesvalues, such ascomposes: classA from "./a.css", classB from "./b.css";. -
#10603
174b21bThanks @denbezrukov! - Fixed CSS formatting forgrid-template-areasdeclarations with comments before multiline values. Biome now keeps grid area rows aligned instead of adding an extra declaration-boundary indent..grid {grid-template-areas:/* row */"header header""footer footer";"header header""footer footer";} -
#10542
c3f07f7Thanks @dyc3! - Fixed #10513: Biome no longer rejects literal\usequences in quoted HTML attribute values. -
#10108
24e51d6Thanks @IxxyDev! - Fixed #6611:noUnnecessaryConditionsnow uses type information to detect more redundant conditions, including?.,??,||,&&, comparisons againstnull/undefinedon non-nullish operands, andcaseclauses that can never match theswitchvalue. -
#10568
eb1ed0eThanks @harsha-cpp! - Fixed #10564:useAriaPropsForRoleno longer reports false positives for Vue v-bind shorthand bindings (:aria-checked,:aria-level, etc.). -
#10570
2ceb4feThanks @Conaclos! - ImprovednoTsIgnore. The rule now reports more precisely the range of the@ts-ignorecomment. -
#10520
b55d10fThanks @dyc3! - Fixed #10519: Vuev-onevent handlers with multiple inline statements are now parsed consistently with Vue. -
#10204
ebbf0bdThanks @ematipico! - Improved the performance of the Biome linter. The improvements are more visible in bigger projects that have more than ~1k files. Early tests showed that in a code base with ~2k files, Biome took less than 26% of time to finish the command. -
#10546
e39bb2cThanks @tim-we! - Fixed#10536: noUnknownFunction no longer flagged CSScontrast-color()as unknown.contrast-color()is Baseline 2026. -
#8012
2be0264Thanks @denbezrukov! - Improved the performance of the formatter in some cases. The formatter is now up to ~20% faster at formatting files. -
#10467
9a5855eThanks @Netail! - Added a new nursery rulenoRestrictedDependencies, which flags imports andpackage.jsondependency entries that have better alternatives in e18e’s module replacement data.For example, the package
globbyis reported because there’s a better alternative:import glob from "globby";{"dependencies": {"globby": "x.x.x"}} -
#10470
84b43c5Thanks @ShaharAviram1! - Fixed #10447: now the rulenoProcessEnvdetects the use ofenvwhen it’s imported fromprocessandnode:process. -
#10556
7ff6b16Thanks @ematipico! - Fixed #10492: Biome no longer crashes with a stack overflow on certain code when a type-aware rule such asnoFloatingPromises,noMisusedPromises, ornoUnnecessaryConditionsis enabled. For example, the following code used to crash Biome:function f(visitor) {let ctrl = visitor();for (const x of [0]) ctrl = ctrl();} -
#10532
1da3c75Thanks @denbezrukov! - CSS declarations with comments before:or after!importantnow preserve spaces before:and;..selector {padding/* name */: 1px;color: red !important /* note */;padding/* name */ : 1px;color: red !important /* note */ ;} -
#10491
a1b5834Thanks @Mokto! - Fixed the Svelte parser rejecting{#each}blocks where the binding uses object destructuring with property renaming, e.g.{#each items as { id, component: Filter }}. Biome now correctly parses and formats these rename bindings. -
#10490
99bc7dfThanks @Mokto! - Fixed the CSS parser rejecting comma-separated selector lists inside:global()and:local()pseudo-class functions. Biome now correctly parses:global(.foo, .bar). -
#10543
c394faeThanks @mangod12! - Fixed #10477: The RDJSON reporter now emits code replacement text for fix suggestions instead of the human-readable fix description. -
#10530
e8e1e6aThanks @Conaclos! - Fixed #10493:useImportTypenow correctly separates types from a default named import when all imports are types and thestyleoption is set toseparatedType. -
#10555
263c7ccThanks @Mokto! - Improved Svelte lint rule accuracy for quoted attribute values containing{expression}interpolations.noRedundantAltno longer emits false positives when the alt text contains an interpolation, e.g.alt="image of {person}".useButtonTypeno longer emits false positives for dynamic button types written astype="{dynamicType}".noScriptUrlno longer emits false positives for dynamic hrefs such ashref="{url}".
-
#10489
96ef9a4Thanks @Mokto! - Fixed Svelte{#each}parser incorrectly rejecting TypeScriptas consttype assertions in the iterable expression. Biome now correctly parses{#each arr as const as item}. -
#10539
935c59aThanks @dyc3! - Improved how diagnostics print long lines of code, for example minified files where the entire source code is printed in one line.
Copyright (c) 2023-present Biome Developers and Contributors.