All versions since 2.2.7
2.2.7
Patch Changes
-
#7715
b622425Thanks @Netail! - Added the nursery rulenoEmptySource, disallowing meaningless js, css, json & graphql files to prevent codebase clutter. -
#7714
c7e5a14Thanks @MeGaNeKoS! - Increased the maximum line limit for noExcessiveLinesPerFunction from 255 to 65,535 to better support large JSX/front-end components. -
#5868
2db73aeThanks @bushuai! - Fixed #5856,noRedundantUseStrictnow keeps leading trivia -
#7756
d665c97Thanks @ematipico! - Improved the diagnostic message of the rulenoDuplicateTestHooks.
2.3.0
Minor Changes
-
#7263
a3e3369Thanks @arendjr! - Biome’s resolver now supportsbaseUrlif specified intsconfig.json.Example
Given the following file structure:
tsconfig.json{"compilerOptions": {"baseUrl": "./src"}}src/foo.tsexport function foo() {}In this scenario,
import { foo } from "foo";should work regardless of the location of the file containing theimportstatement.Fixes #6432.
-
#7745
6fcbc07Thanks @dyc3! - Addedignoreoption tonoUnknownAtRules. If an unknown at-rule matches any of the items provided inignore, a diagnostic won’t be emitted. -
#7753
63cb7ffThanks @ematipico! - Enhanced theinitcommand. Theinitcommand now checks if the existing project contains known ignore files and known generated folders.If Biome finds
.gitignoreor.ignorefiles, it will add the following configuration tobiome.json:{"vcs": {"enabled": true,"clientKind": "git","useIgnoreFile": true}}If Biome finds a
dist/folder, it will exclude it automatically using the double-exclude syntax:{"files": {"includes": ["**", "!!**/dist"]}} -
#7548
85d3a3aThanks @siketyan! - The rules in a domain are no longer enabled automatically by the installed dependencies unless the rule is recommended. -
#7723
d3aac63Thanks @ematipico! - Added--css-parse-css-modulesCLI flag to control whether CSS Modules syntax is enabled.You can now enable or disable CSS Modules parsing directly from the command line:
Terminal window biome check --css-parse-css-modules=true file.module.cssbiome format --css-parse-css-modules=true file.module.cssbiome lint --css-parse-css-modules=true file.module.cssbiome ci --css-parse-css-modules=true file.module.css -
#7723
d3aac63Thanks @ematipico! - Added--css-parse-tailwind-directivesCLI flag to control whether Tailwind CSS 4.0 directives and functions are enabled.You can now enable or disable Tailwind CSS 4.0 directive parsing directly from the command line:
Terminal window biome check --css-parse-tailwind-directives=true file.cssbiome format --css-parse-tailwind-directives=true file.cssbiome lint --css-parse-tailwind-directives=true file.cssbiome ci --css-parse-tailwind-directives=true file.css -
#7330
272632fThanks @ematipico! - Updated the formatting of.svelteand.vuefiles. Now the indentation of the JavaScript blocks matches Prettier’s:<script>import Component from "./Component"import Component from "./Component"</script> -
#7333
de0d2d6Thanks @dyc3! - Implemented theindentScriptAndStyleoption for vue and svelte files, with the default set tofalseto match Prettier’svueIndentScriptAndStyleoption. When enabled, this option indents the content within<script>and<style>tags to align with the surrounding HTML structure.It can be enabled with this configuration:
{"html": {"formatter": {"indentScriptAndStyle": true}}}Which will format this code to:
<script>import Component from "./Component.vue";</script> -
#7359
ebbddc4Thanks @arendjr! - Deprecated the optionfiles.experimentalScannerIgnoresin favour of force-ignore syntax infiles.includes.files.includessupports ignoring files by prefixing globs with an exclamation mark (!). With this change, it also supports force-ignoring globs by prefixing them with a double exclamation mark (!!).The effect of force-ignoring is that the scanner will not index files matching the glob, even in project mode, even if those files are imported by other files, and even if they are files that receive special treatment by Biome, such as nested
biome.jsonfiles.Example
Let’s take the following configuration:
{"files": {"includes": ["**","!**/generated","!!**/dist","fixtures/example/dist/*.js"]},"linter": {"domains": {"project": "all"}}}This configuration achieves the following:
- Because the project domain is enabled, all supported files in the project are indexed and processed by the linter, except:
- Files inside a
generatedfolder are not processed by the linter, but they will get indexed if a file outside ageneratedfolder imports them. - Files inside a
distfolder are never indexed nor processed, not even if they are imported for any purpose, except: - When the
distfolder is insidefixtures/example/, its.jsfiles do get both indexed and processed.
In general, we now recommend using the force-ignore syntax for any folders that contain output files, such as
build/anddist/. For such folders, it is highly unlikely that indexing has any useful benefits. For folders containing generated files, you may wish to use the regular ignore syntax so that type information can still be extracted from the files.experimentalScannerIgnoreswill continue to work for now, but you’ll see a deprecation warning if you still use it.Run the
biome migrate --writecommand to automatically update the configuration file. -
#7698
3b6f5e3Thanks @ematipico! - Added a new reporter namedrdjson. This reporter prints diagnostics following the RDJSON format:The following command:
Terminal window biome check --reporter=rdjsonWill emit diagnostics in the following format:
{"source": {"name": "Biome","url": "https://biomejs.dev"},"diagnostics": [{"code": {"url": "https://biomejs.dev/linter/rules/no-unused-imports","value": "lint/correctness/noUnusedImports"},"location": {"path": "index.ts","range": {"end": {"column": 11,"line": 0},"start": {"column": 7,"line": 0}}},"message": "This import is unused."},{"code": {"url": "https://biomejs.dev/linter/rules/no-unused-imports","value": "lint/correctness/noUnusedImports"},"location": {"path": "index.ts","range": {"end": {"column": 10,"line": 1},"start": {"column": 9,"line": 1}}},"message": "Several of these imports are unused."}]} -
#7719
188a767Thanks @cadunass! - TheformatWithErrorsoption can now be set via CLI using the--format-with-errorsflag.This flag was previously only available in the configuration file. It allows formatting to proceed on files with syntax errors, which is useful during development when you want to auto-format code while fixing syntax issues.
Example
Terminal window biome format --format-with-errors=true --write file.js -
#7723
d3aac63Thanks @ematipico! - Added--json-parse-allow-commentsCLI flag to control whether comments are allowed in JSON files.You can now enable or disable comment parsing in JSON files directly from the command line:
Terminal window biome check --json-parse-allow-comments=true file.jsonbiome format --json-parse-allow-comments=true file.jsonbiome lint --json-parse-allow-comments=true file.jsonbiome ci --json-parse-allow-comments=true file.json -
#7723
d3aac63Thanks @ematipico! - Added--json-parse-allow-trailing-commasCLI flag to control whether trailing commas are allowed in JSON files.You can now enable or disable trailing comma parsing in JSON files directly from the command line:
Terminal window biome check --json-parse-allow-trailing-commas=true file.jsonbiome format --json-parse-allow-trailing-commas=true file.jsonbiome lint --json-parse-allow-trailing-commas=true file.jsonbiome ci --json-parse-allow-trailing-commas=true file.json -
#7758
cea002fThanks @ematipico! - Promoted new lint rules:- Promoted
noNonNullAssertedOptionalChainto the suspicious group - Promoted
useReactFunctionComponentsto thestylegroup - Promoted
useImageSizeto thecorrectnessgroup - Promoted
useConsistentTypeDefinitionsto thestylegroup - Promoted
useQwikClasslistto thecorrectnessgroup - Promoted
noSecretsto thesecuritygroup
Removed the lint rule
useAnchorHref, because its use case is covered byuseValidAnchor. - Promoted
-
#6356
296627dThanks @wrick17! - Added the newcheckstylereporter. When--reporter=checkstyleis passed to the CLI, Biome will emit diagnostics for Checkstyle format:<?xml version="1.0" encoding="utf-8"?><checkstyle version="4.3"><file name="index.ts"><error line="1" column="8" severity="warning" message="This import is unused." source="lint/correctness/noUnusedImports" /><error line="2" column="10" severity="warning" message="Several of these imports are unused." source="lint/correctness/noUnusedImports" /><error line="8" column="5" severity="warning" message="This variable f is unused." source="lint/correctness/noUnusedVariables" /><error line="9" column="7" severity="warning" message="This variable f is unused." source="lint/correctness/noUnusedVariables" /><error line="1" column="1" severity="error" message="The imports and exports are not sorted." source="assist/source/organizeImports" /><error line="4" column="3" severity="error" message="Using == may be unsafe if you are relying on type coercion." source="lint/suspicious/noDoubleEquals" /><error line="6" column="1" severity="error" message="This is an unexpected use of the debugger statement." source="lint/suspicious/noDebugger" /><error line="8" column="5" severity="error" message="This variable implicitly has the any type." source="lint/suspicious/noImplicitAnyLet" /><error line="9" column="7" severity="error" message="This variable implicitly has the any type." source="lint/suspicious/noImplicitAnyLet" /><error line="2" column="10" severity="error" message="Shouldn't redeclare 'z'. Consider to delete it or rename it." source="lint/suspicious/noRedeclare" /><error line="9" column="7" severity="error" message="Shouldn't redeclare 'f'. Consider to delete it or rename it." source="lint/suspicious/noRedeclare" /><error line="0" column="0" severity="error" message="Formatter would have printed the following content:" source="format" /></file><file name="main.ts"><error line="1" column="8" severity="warning" message="This import is unused." source="lint/correctness/noUnusedImports" /><error line="2" column="10" severity="warning" message="Several of these imports are unused." source="lint/correctness/noUnusedImports" /><error line="8" column="5" severity="warning" message="This variable f is unused." source="lint/correctness/noUnusedVariables" /><error line="9" column="7" severity="warning" message="This variable f is unused." source="lint/correctness/noUnusedVariables" /><error line="1" column="1" severity="error" message="The imports and exports are not sorted." source="assist/source/organizeImports" /><error line="4" column="3" severity="error" message="Using == may be unsafe if you are relying on type coercion." source="lint/suspicious/noDoubleEquals" /><error line="6" column="1" severity="error" message="This is an unexpected use of the debugger statement." source="lint/suspicious/noDebugger" /><error line="8" column="5" severity="error" message="This variable implicitly has the any type." source="lint/suspicious/noImplicitAnyLet" /><error line="9" column="7" severity="error" message="This variable implicitly has the any type." source="lint/suspicious/noImplicitAnyLet" /><error line="2" column="10" severity="error" message="Shouldn't redeclare 'z'. Consider to delete it or rename it." source="lint/suspicious/noRedeclare" /><error line="9" column="7" severity="error" message="Shouldn't redeclare 'f'. Consider to delete it or rename it." source="lint/suspicious/noRedeclare" /><error line="0" column="0" severity="error" message="Formatter would have printed the following content:" source="format" /></file></checkstyle> -
#7488
b13e524Thanks @kpapa05! - Added “@rbxts/react” as an alias for “react” for handling the reactClassic jsxRuntime. -
#7536
0bccd34Thanks @TheAlexLichter! - Added.oxlintrc.jsonto well-known files. -
#7548
85d3a3aThanks @siketyan! - The following rules are now a part of thereactdomain, and they won’t be enabled automatically unless you enabled the domain, or Biome detectsreactas a dependency of your closestpackage.json:lint/correctness/noChildrenProp(recommended)lint/correctness/noReactPropAssignmentslint/security/noDangerouslySetInnerHtml(recommended)lint/security/noDangerouslySetInnerHtmlWithChildren(recommended)lint/style/useComponentExportOnlyModuleslint/suspicious/noArrayIndexKey(recommended)
-
#7667
480909aThanks @ematipico! - Added the ability to show severityInformationdiagnostics in reporter outputs.If one or more rules are triggered, and they are configured to emit an
Informationdiagnostic, now they’re counted in the final output:Terminal window Checked 1 file in <TIME>. No fixes applied.Found 1 info. -
#7702
28e8860Thanks @ematipico! - Added linting and assist support for.htmlfiles, with addition of two new configurations:html.linter.enabledhtml.assist.enabled
The HTML linter, in this release, only contains the rule
noHeaderScope. More rules will be released in the upcoming releases. -
#7164
f66b0c5Thanks @dyc3! - Added a new CSS parser optiontailwindDirectives. Enabling this option will allow all of Tailwind v4’s syntax additions to be parsed and formatted by Biome.You can enable this by setting
css.parser.tailwindDirectivestotruein your Biome configuration.{"css": {"parser": {"tailwindDirectives": true}}} -
#7669
6ed4d16Thanks @barklund! - React 19.2 support is now supported in Biome:- Treats
useEffectEventlikeuseRefinuseExhaustiveDependencies - Added
<Activity />to known React APIs.
- Treats
-
#7702
28e8860Thanks @ematipico! - Added experimental full support for HTML, Vue, Svelte and Astro files. In this release, the HTML parser has been enhanced, and it’s now able to parse.vue,.svelteand.astrofiles.This means that now Biome is able to lint and format the JavaScript (TypeScript), HTML and CSS code that is contained in these files.
Now that the main architecture is stable and working, in the upcoming patches and minors we will also fix possible inaccuracies and edge cases coming from existing lint rules, such as
noUnusedVariablesinside<script>blocks or frontmatter.The support is considered experimental because there might be cases that aren’t fine-parsed yet, hence causing possible inaccuracies when it comes to formatting and linting.
-
#7599
09445c8Thanks @anaisbetts! - #### lineEnding has a new optionautoThe option
lineEndingnow has a variant calledautoto match the operating system’s expected line-ending style: on Windows, this will be CRLF (\r\n), and on macOS / Linux, this will be LF (\n).This allows for cross-platform projects that use Biome not to have to force one option or the other, which aligns better with Git’s default behavior on these platforms.
Example usage:
{"formatter": {"lineEnding": "auto"}}Terminal window biome format --line-ending auto -
#7392
e4feb8eThanks @ematipico! - Added new capabilities to the CLI arguments--skipand--only, available to thebiome lintcommand.--skipand--onlycan now accept domain names; when provided, Biome will run or skip all the rules that belong to a certain domain.For example, the following command will only run the rules that belong to the next domain:
Terminal window biome lint --only=nextAnother example, the following command will skip the rules that belong to the project domain:
Terminal window biome lint --skip=project -
#7702
28e8860Thanks @ematipico! - Added a new option calledhtml.interpolation. This option enables the parsing of text expressions (or interpolation) in HTML files.The following
file.htmlwill be correctly formatted:file.html <div>Hello {{ name }}!<p>Your balance is: {{ account.balance }}</p><button>{{ isLoading ? "Loading..." : "Submit" }}</button></div>To note that
html.interpolationonly parses text expressions that are delimited by double curly braces ({{ }}). The content of expressions is parsed as normal text.
Patch Changes
-
#7712
fcc9b42Thanks @minht11! - Added new ruleuseVueDefineMacrosOrderwhich allows enforcing specific order for Vue compiler macros.In this example, the rule will suggest moving
definePropsbeforedefineEmits:<script lang="ts" setup>const emit = defineEmits(["update"]);const props = defineProps<{ name: string }>();</script> -
#7698
3b6f5e3Thanks @ematipico! - Fixed an issue where the JUnit reporter returned a zero-based location. Now the location returned is one-based. -
#7819
ef45056Thanks @ematipico! - Fixed #7788. Removes some error logging that were emitted when loading possible configuration files. -
#7593
e51dd55Thanks @arendjr! - Fixed an issue with thefiles.maxSizesetting. Previously the setting would always be looked up in the root settings, even in monorepos where a closerbiome.jsonis available. It now correctly uses the nearest configuration. -
#7825
ad55b35Thanks @Conaclos! - Fixed #7798. useNamingConvention no longer panics when it encounters a name that consists of a single dollar sign$that doesn’t match a custom convention. -
#7764
93be2abThanks @gaauwe! - Fixed #6589: Biome now properly loads extension settings before loading the configuration file when opening a text document in the LSP server.
2.3.1
Patch Changes
-
#7840
72afdfaThanks @ematipico! - Fixed #7838, which caused the new--css-parse-*arguments not being recognised by thecicommand. -
#7789
d5b416eThanks @fronterior! - Fixed the LSP methodworkspace/didChangeWorkspaceFoldersto perform incremental updates instead of replacing the entire folder list. -
#7852
bd254c7Thanks @dyc3! - Fixed #7843: The CSS parser, whentailwindDirectivesis enabled, correctly parses--*: initial;. -
#7872
0fe13feThanks @dyc3! - Fixed #7861: The HTML parser will now accept Svelte attribute shorthand syntax in.sveltefiles. -
#7866
7b2600bThanks @dyc3! - Fixed #7860: The css parser, withtailwindDirectivesenabled, will now accept@pluginoptions. -
#7853
fe90c78Thanks @dyc3! - Fixed #7848: The css parser withtailwindDirectivesenabled will now correctly parse tailwind’s source exclude syntax:@source not "foo.css"; -
#7878
c9f7fe5Thanks @ematipico! - Fixed #7857: Biome now parses<script>tags as TypeScript when analysing.astrofiles. -
#7867
b42b718Thanks @smorimoto! - Fixed incorrect option name in HTML parser error message.The error message for disabled text expressions incorrectly referred to the
html.parser.textExpressionoption, which does not exist. Updated it to reference the correcthtml.parser.interpolationoption.
2.3.2
Patch Changes
-
#7859
c600618Thanks @Netail! - Added the nursery rulenoIncrementDecrement, disallows the usage of the unary operators ++ and —. -
#7901
0d17b05Thanks @ematipico! - Fixed #7837, where Biome couldn’t properly parse text expressions that contained nested curly brackets. This was breaking parsing in Astro and Svelte files. -
#7874
e617d36Thanks @Bertie690! - Fixed #7230:noUselessStringConcatno longer emits false positives for multi-line strings with leading+operators.Previously, the rule did not check for leading newlines on the
+operator, emitting false positives if one occurred at the start of a line.
Notably, formatting withoperatorLinebreak="before"would move the+operators to the start of lines automatically, resulting in spurious errors whenever a multi-line string was used.Now, the rule correctly detects and ignores multi-line concatenations with leading operators as well, working regardless of the setting of
operatorLinebreak.Example
// The following code used to error if the `+` operators were at the start of lines (as opposed to the end).// Now, the rule correctly recognizes this as a stylistic concatenation and ignores it.const reallyLongStringThatShouldNotError ="Lorem ipsum dolor sit amet consectetur adipiscing elit." +"Quisque faucibus ex sapien vitae pellentesque sem placerat." +"In id cursus mi pretium tellus duis convallis." +"Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla"; -
#7786
33ffcd5Thanks @daivinhtran! - Fixed #7601: Properly match Grit plugin’s code snippet with only one child. -
#7901
0d17b05Thanks @ematipico! - Fixed #7837, where Biome Language Server panicked when opening HTML-ish files when the experimental full support is enabled.
2.3.3
Patch Changes
-
#7907
57bd662Thanks @ematipico! - Fixed #7839. Now the Biome parser correctly parses the Astro frontmatter even when a triple fence is inside quotes. -
#7934
a35c496Thanks @alissonlauffer! - Fixed #7919: The HTML parser now correctly handles Unicode BOM (Byte Order Mark) characters at the beginning of HTML files, ensuring proper parsing and tokenization. -
#7869
c80361dThanks @matanshavit! - Fixed #7864: Biome now preserves component tag name casing in Svelte, Astro, and Vue files. -
#7926
69cececThanks @matanshavit! - Added the rulenoParametersOnlyUsedInRecursion.This rule detects function parameters that are exclusively used in recursive calls and can be removed to simplify the function signature since they are effectively unused.
function factorial(n, acc) {if (n === 0) return 1;return factorial(n - 1, acc); // acc is only used here}Fixes #6484.
-
#7774
2509b91Thanks @dibashthapa! - Fixed #7657: Added the new ruleno-unknown-propertyfrom ESLint -
#7918
7165d06Thanks @dyc3! - Fixed #7913: The CSS parser, withtailwindDirectivesenabled, will now correctly handle@slot. -
#7959
ffae203Thanks @siketyan! - Fixed the Biome Language Server so it no longer returns an internal error when the formatter is disabled in the configuration.
2.3.4
Patch Changes
-
#7989
4855c4aThanks @alissonlauffer! - Fixed a regression in Astro frontmatter parsing where comments inside quoted strings were incorrectly detected as actual comments. This caused the parser to prematurely terminate frontmatter parsing when encountering strings likeconst test = "//";. For example, the following Astro frontmatter now parses correctly:---const test = "// not a real comment";--- -
#7968
0b28f5fThanks @denbezrukov! - Refactored formatter to use strictTokenelement for better performance. The newTokenvariant is optimized for static, ASCII-only text (keywords, operators, punctuation) with the following constraints:- ASCII only (no Unicode characters)
- No newlines (
\n,\r) - No tab characters (
\t)
This enables faster printing and fitting logic by using bulk string operations (
push_str,len()) instead of character-by-character iteration with Unicode width calculations. -
#7941
19b8280Thanks @Conaclos! - Fixed #7943. Rules’optionsare now properly merged with the inheritedoptionsfrom a shared configuration.This means that you can now override a specific option from a rule without resetting the other options to their default.
Given the following shared configuration:
{"linter": {"rules": {"style": {"useNamingConvention": {"level": "on","options": {"strictCase": false,"conventions": [{"selector": { "kind": "variable", "scope": "global" },"formats": ["CONSTANT_CASE"]}]}}}}}}And the user configuration that extends this shared configuration:
{"extends": ["shared.json"],"linter": {"rules": {"style": {"useNamingConvention": {"level": "on","options": { "strictCase": true }}}}}}The obtained merged configuration is now as follows:
{"extends": ["shared.json"],"linter": {"rules": {"style": {"useNamingConvention": {"level": "on","options": {"strictCase": true,"conventions": [{"selector": { "kind": "variable", "scope": "global" },"formats": ["CONSTANT_CASE"]}]}}}}}} -
#7969
425963dThanks @ematipico! - Added support for the Svelte syntax{@debug}. The Biome HTML parser is now able to parse and format the blocks:{@debug foo,bar, something}{@debug foo, bar, something} -
#7986
3256f82Thanks @lisiur! - Fixed #7981. Now Biome correctly detects and parseslang='tsx'andlang='jsx'languages when used inside in.vuefiles, when.experimentalFullSupportEnabledis enabled. -
#7921
547c2daThanks @dyc3! - Fixed #7854: The CSS parser, withtailwindDirectivesenabled, will now parse@source inline("underline");. -
#7856
c9e20c3Thanks @Netail! - Added the nursery rulenoContinue. Disallowing the usage of thecontinuestatement, structured control flow statements such asifshould be used instead.Invalid:
let sum = 0,i;for (i = 0; i < 10; i++) {if (i >= 5) {continue;}sum += i;}Valid:
let sum = 0,i;for (i = 0; i < 10; i++) {if (i < 5) {sum += i;}}
2.3.5
Patch Changes
-
#8023
96f3e77Thanks @ematipico! - Added support Svelte syntax{@html}. Biome now is able to parse and format the Svelte syntax{@html}:{@html 'div'}{@html 'div'}The contents of the expressions inside the
{@html <expression>}aren’t formatted yet. -
#8058
5f68bccThanks @ematipico! - Fixed a bug where the Biome Language Server would enable its project file watcher even when no project rules were enabled.Now the watching of nested configuration files and nested ignore files is delegated to the editor, if their LSP spec supports it.
-
#8023
96f3e77Thanks @ematipico! - Added support Svelte syntax{@render}. Biome now is able to parse and format the Svelte syntax{@render}:{@render sum(1, 2) }{@render sum(1, 2)}The contents of the expressions inside the
{@render <expression>}aren’t formatted yet. -
#8006
f0612a5Thanks @Bertie690! - Updated documentation and diagnostic forlint/complexity/noBannedTypes. The rule should have a more detailed description and diagnostic error message. -
#8039
da70d8bThanks @PFiS1737! - Biome now keeps a blank line after the frontmatter section in Astro files. -
#8042
b7efa6fThanks @dyc3! - The CSS Parser, withtailwindDirectivesenabled, will now accept at rules like@mediaand@supportsin@custom-variantshorthand syntax. -
#8064
3ff9d45Thanks @dibashthapa! - Fixed #7967: Fixed the issue with support for advanced SVG props -
#8023
96f3e77Thanks @ematipico! - Added support Svelte syntax{@attach}. Biome now is able to parse and format the Svelte syntax{@attach}:<div {@attach myAttachment }>...</div><div {@attach myAttachment}>...</div>The contents of the expressions inside the
{@attach <expression>}aren’t formatted yet. -
#8001
6e8a50eThanks @ematipico! - Added support Svelte syntax{#key}. Biome now is able to parse and format the Svelte syntax{#key}:{#key expression} <div></div> {/key}{#key expression}<div></div>{/key}The contents of the expressions inside the
{#key <expression>}aren’t formatted yet. -
#8023
96f3e77Thanks @ematipico! - Added support Svelte syntax{@const}. Biome now is able to parse and format the Svelte syntax{@const}:{@const name = value}{@const name = value}The contents of the expressions inside the
{@const <expression>}aren’t formatted yet. -
#8044
8f77d4aThanks @Netail! - Corrected rule source references.biome migrate eslintshould do a bit better detecting rules in your eslint configurations. -
#8065
1a2d1afThanks @Netail! - Added the nursery ruleuseArraySortCompare. Require Array#sort and Array#toSorted calls to always provide a compareFunction.Invalid:
const array = [];array.sort();Valid:
const array = [];array.sort((a, b) => a - b); -
#7673
a3a713dThanks @dyc3! - The HTML parser is now able to parse vue directives. This enables us to write/port Vue lint rules that require inspecting the<template>section. However, this more complex parsing may result in parsing errors where there was none before. For those of you that have opted in to the experimental support (akaexperimentalFullSupportEnabled), we greatly appreciate your help testing this out, and your bug reports. -
#8031
fa6798aThanks @ematipico! - Added support for the Svelte syntax{#if}{/if}. The Biome HTML parser is now able to parse and format the{#if}{/if} blocks:<!-- if / else-if / else -->{#if porridge.temperature > 100}<p>too hot!</p><p>too hot!</p>{:else if 80 > porridge.temperature}<p>too cold!</p><p>too cold!</p>{:else if 100 > porridge.temperature}<p>too too cold!</p><p>too too cold!</p>{:else}<p>just right!</p><p>just right!</p>{/if} -
#8041
beeb7bbThanks @dyc3! - The CSS parser, withtailwindDirectivesenabled, will now accept lists of selectors in@custom-variantshorthand syntax.@custom-variant cell (th:has(&), td:has(&)); -
#8028
c09e45cThanks @fmajestic! - The GitLab reporter now outputs format errors. -
#8037
78011b1Thanks @PFiS1737! -indentScriptAndStyleno longer indents the frontmatter in Astro files. -
#8009
6374b1fThanks @tmcw! - Fixed an edge case in theuseArrowFunctionrule.The rule no longer emits diagnostics for or offers to fix functions that reference the arguments object, because that object is undefined for arrow functions.
Valid example:
// Valid: this function cannot be transformed into an arrow function because// arguments is not defined for arrow functions.const getFirstArg = function () {return arguments[0];};
2.3.6
Patch Changes
-
#8100
82b9a8eThanks @Netail! - Added the nursery ruleuseFind. Enforce the use of Array.prototype.find() over Array.prototype.filter() followed by [0] when looking for a single result.Invalid:
[1, 2, 3].filter((x) => x > 1)[0];[1, 2, 3].filter((x) => x > 1).at(0); -
#8118
dbc7021Thanks @hirokiokada77! - Fixed #8117:useValidLangnow accepts valid BCP 47 language tags with script subtags.Valid:
<html lang="zh-Hans-CN"></html> -
#7672
f1d5725Thanks @Netail! - Added the nursery ruleuseConsistentGraphqlDescriptions, requiring all descriptions to follow the same style (either block or inline) inside GraphQL files.Invalid:
enum EnumValue {"this is a description"DEFAULT}Valid:
enum EnumValue {"""this is a description"""DEFAULT} -
#8026
f102661Thanks @matanshavit! - Fixed #8004:noParametersOnlyUsedInRecursionnow correctly detects recursion by comparing function bindings instead of just names.Previously, the rule incorrectly flagged parameters when a method had the same name as an outer function but called the outer function (not itself):
function notRecursive(arg) {return arg;}const obj = {notRecursive(arg) {return notRecursive(arg); // This calls the outer function, not the method itself},};Biome now properly distinguishes between these cases and will not report false positives.
-
#8097
5fc5416Thanks @dyc3! - Added the nursery rulenoVueVIfWithVFor. This rule disallowsv-forandv-ifon the same element.<!-- Invalid --><div v-for="item in items" v-if="item.isActive">{{ item.name }}</div> -
#8085
7983940Thanks @Netail! - Added the nursery rulenoForIn. Disallow iterating using a for-in loop.Invalid:
for (const i in array) {console.log(i, array[i]);} -
#8086
2b41e82Thanks @matanshavit! - Fixed #8045: ThenoNestedTernaryrule now correctly detects nested ternary expressions even when they are wrapped in parentheses (e.g.foo ? (bar ? 1 : 2) : 3).Previously, the rule would not flag nested ternaries like
foo ? (bar ? 1 : 2) : 3because the parentheses prevented detection. The rule now looks through parentheses to identify nested conditionals.Previously not detected (now flagged):
const result = foo ? (bar ? 1 : 2) : 3;Still valid (non-nested with parentheses):
const result = foo ? bar : baz; -
#8075
e403868Thanks @YTomm! - Fixed #7948: TheuseReadonlyClassPropertiescode fix whencheckAllPropertiesis enabled will no longer insert a newline afterreadonlyand the class property. -
#8102
47d940eThanks @lucasweng! - Fixed #8027.useReactFunctionComponentsno longer reports class components that implementcomponentDidCatchusing class expressions.The rule now correctly recognizes error boundaries defined as class expressions:
const ErrorBoundary = class extends Component {componentDidCatch(error, info) {}render() {return this.props.children;}}; -
#8097
5fc5416Thanks @dyc3! - Added the nursery ruleuseVueHyphenatedAttributes, which encourages using kebab case for attribute names, per the Vue style guide’s recommendations.<!-- Invalid --><MyComponent myProp="value" /><!-- Valid --><MyComponent my-prop="value" /> -
#8108
0f0a658Thanks @Netail! - Added the nursery rulenoSyncScripts. Prevent the usage of synchronous scripts.Invalid:
<script src="https://third-party-script.js" />Valid:
<script src="https://third-party-script.js" async /><script src="https://third-party-script.js" defer /> -
#8098
1fdcaf0Thanks @Jayllyz! - Added documentation URLs to rule descriptions in the JSON schema. -
#8097
5fc5416Thanks @dyc3! - Fixed an issue with the HTML parser where it would treat Vue directives with dynamic arguments as static arguments instead. -
#7684
f4433b3Thanks @vladimir-ivanov! - ChangednoUnusedPrivateClassMembersto align more fully with meaningful reads.This rule now distinguishes more carefully between writes and reads of private class members.
- A meaningful read is any access that affects program behavior.
- For example,
this.#x += 1both reads and writes#x, so it counts as usage. - Pure writes without a read (e.g.
this.#x = 1with no getter) are no longer treated as usage.
This change ensures that private members are only considered “used” when they are actually read in a way that influences execution.
Invalid examples (previously valid)
class UsedMember {set #x(value) {doSomething(value);}foo() {// This assignment does not actually read #x, because there is no getter.// Previously, this was considered a usage, but now it’s correctly flagged.this.#x = 1;}}Valid example (Previously invalid)
class Foo {#usedOnlyInWriteStatement = 5;method() {// This counts as a meaningful read because we both read and write the value.this.#usedOnlyInWriteStatement += 42;}} -
#7684
f4433b3Thanks @vladimir-ivanov! - Improved detection of used private class membersThe analysis for private class members has been improved: now the tool only considers a private member “used” if it is actually referenced in the code.
- Previously, some private members might have been reported as used even if they weren’t actually accessed.
- With this change, only members that are truly read or called in the code are counted as used.
- Members that are never accessed will now be correctly reported as unused.
This makes reports about unused private members more accurate and helps you clean up truly unused code.
Example (previously valid)
type YesNo = "yes" | "no";export class SampleYesNo {private yes: () => void;private no: () => void;private dontKnow: () => void; // <- will now report as unusedon(action: YesNo): void {this[action]();}} -
#7681
b406db6Thanks @kedevked! - Added the new lint rule,useSpread, ported from the ESLint ruleprefer-spread.This rule enforces the use of the spread syntax (
...) overFunction.prototype.apply()when calling variadic functions, as spread syntax is generally more concise and idiomatic in modern JavaScript (ES2015+).The rule provides a safe fix.
Invalid
Math.max.apply(Math, args);foo.apply(undefined, args);obj.method.apply(obj, args);Valid
Math.max(...args);foo(...args);obj.method(...args);// Allowed: cases where the `this` binding is intentionally changedfoo.apply(otherObj, args); -
#7287
aa55c8dThanks @ToBinio! - Fixed #7205: ThenoDuplicateTestHooksrule now treats chained describe variants (e.g., describe.each/for/todo) as proper describe scopes, eliminating false positives.The following code will no longer be a false positive:
describe("foo", () => {describe.for([])("baz", () => {beforeEach(() => {});});describe.todo("qux", () => {beforeEach(() => {});});describe.todo.each([])("baz", () => {beforeEach(() => {});});}); -
#8013
0c0edd4Thanks @Jayllyz! - Added the GraphQL nursery ruleuseUniqueGraphqlOperationName. This rule ensures that all GraphQL operations within a document have unique names.Invalid:
query user {user {id}}query user {user {idemail}}Valid:
query user {user {id}}query userWithEmail {user {idemail}} -
#8084
c2983f9Thanks @dyc3! - Fixed #8080: The HTML parser, when parsing Vue, can now properly handle Vue directives with no argument, modifiers, or initializer (e.g.v-else). It will no longer treat subsequent valid attributes as bogus.<p v-else class="flex">World</p><!-- Fixed: class now gets parsed as it's own attribute --> -
#8104
041196bThanks @Conaclos! - FixednoInvalidUseBeforeDeclaration. The rule no longer reports a use of an ambient variable before its declarations. The rule also completely ignores TypeScript declaration files. The following code is no longer reported as invalid:CONSTANT;declare const CONSTANT: number; -
#8060
ba7b076Thanks @dyc3! - Added the nursery ruleuseVueValidVBind, which enforces the validity ofv-binddirectives in Vue files.Invalid
v-bindusages include:<Foo v-bind /><!-- Missing argument --><Foo v-bind:foo /><!-- Missing value --><Foo v-bind:foo.bar="baz" /><!-- Invalid modifier --> -
#8113
fb8e3e7Thanks @Conaclos! - FixednoInvalidUseBeforeDeclaration. The rule now reports invalid use of classes, enums, and TypeScript’s import-equals before their declarations.The following code is now reported as invalid:
new C();class C {} -
#8077
0170dcbThanks @dyc3! - Added the ruleuseVueValidVElseIfto enforce validv-else-ifdirectives in Vue templates. This rule reports invalidv-else-ifdirectives with missing conditional expressions or when not preceded by av-iforv-else-ifdirective. -
#8077
0170dcbThanks @dyc3! - Added the ruleuseVueValidVElseto enforce validv-elsedirectives in Vue templates. This rule reportsv-elsedirectives that are not preceded by av-iforv-else-ifdirective. -
#8077
0170dcbThanks @dyc3! - Added the ruleuseVueValidVHtmlto enforce valid usage of thev-htmldirective in Vue templates. This rule reportsv-htmldirectives with missing expressions, unexpected arguments, or unexpected modifiers. -
#8077
0170dcbThanks @dyc3! - Added the ruleuseVueValidVIfto enforce validv-ifdirectives in Vue templates. It disallows arguments and modifiers, and ensures a value is provided. -
#8077
0170dcbThanks @dyc3! - Added the ruleuseVueValidVOnto enforce validv-ondirectives in Vue templates. This rule reports invalidv-on/ shorthand@directives with missing event names, invalid modifiers, or missing handler expressions.
2.3.7
Patch Changes
-
#8169
7fdcec8Thanks @arendjr! - Fixed #7999: Correctly placeawaitafter leading comment in auto-fix action fromnoFloatingPromisesrule. -
#8157
12d5b42Thanks @Conaclos! - Fixed #8148.noInvalidUseBeforeDeclarationno longer reports some valid use before declarations.The following code is no longer reported as invalid:
class classA {C = C;}const C = 0; -
#8178
6ba4157Thanks @dyc3! - Fixed #8174, where the HTML parser would parse 2 directives as a single directive because it would not reject whitespace in Vue directives. This would cause the formatter to erroneously merge the 2 directives into one, resulting in broken code.<Component v-else:property="123" /><Component v-else :property="123" /> -
#8088
0eb08e8Thanks @db295! - Fixed #7876: ThenoUnusedImportsrule now ignores imports that are used by @linkcode and @linkplain (previously supported @link and @see).The following code will no longer be a false positive:
import type { a } from "a"/*** {@linkcode a}*/function func() {} -
#8119
8d64655Thanks @ematipico! - Improved the detection of the rulenoUnnecessaryConditions. Now the rule isn’t triggered for variables that are mutated inside a module.This logic deviates from the original rule, hence
noUnnecessaryConditionsis now marked as “inspired”.In the following example,
heystarts asfalse, but then it’s assigned to a string. The rule isn’t triggered inside theifcheck.let hey = false;function test() {hey = "string";}if (hey) {} -
#8149
e0a02bfThanks @Netail! - Fixed #8144: ImprovenoSyncScripts, ignore script tags withtype="module"as these are always non-blocking. -
#8182
e9f068eThanks @hirokiokada77! - Fixed #7877: Range suppressions now handle suppressed categories properly.Valid:
// biome-ignore-start lint: explanationconst foo = 1;// biome-ignore-end lint: explanation -
#8111
bf1a836Thanks @ryan-m-walker! - Added support for parsing and formatting the CSS if function.Example
.basic-style {color: if(style(--scheme: dark): #eeeeee; else: #000000;);} -
#8173
7fc07c1Thanks @ematipico! - Fixed #8138 by reverting an internal refactor that caused a regression to the rulenoUnusedPrivateClassMembers. -
#8119
8d64655Thanks @ematipico! - Improved the type inference engine, by resolving types for variables that are assigned to multiple values. -
#8158
fb1458bThanks @dyc3! - Added theuseVueValidVTextlint rule to enforce validv-textdirectives. The rule reports whenv-texthas an argument, has modifiers, or is missing a value.Invalid:
<div v-text /><!-- missing value --><div v-text:aaa="foo" /><!-- has argument --><div v-text.bbb="foo" /><!-- has modifier --> -
#8158
fb1458bThanks @dyc3! - FixeduseVueValidVHtmlso that it will now flag empty strings, e.g.v-html="" -
#7078
bb7a15cThanks @emilyinure! - Fixed #6675: Now only flags noAccumulatingSpread on Object.assign when a new object is being allocated on each iteration. Before, all cases using Object.assign with reduce parameters were warned despite not making new allocations.The following code will no longer be a false positive:
foo.reduce((acc, bar) => Object.assign(acc, bar), {});The following cases which do make new allocations will continue to warn:
foo.reduce((acc, bar) => Object.assign({}, acc, bar), {}); -
#8175
0c8349eThanks @ryan-m-walker! - Fixed CSS formatting of dimension units to use correct casing forQ,HzandkHz.Before:
.cssUnits {a: 1Q;b: 1Hz;c: 1kHz;}After:
.cssUnits {a: 1Q;b: 1Hz;c: 1kHz;}
2.3.8
Patch Changes
-
#8188
4ca088cThanks @ematipico! - Fixed #7390, where Biome couldn’t apply the correct configuration passed via--config-path.If you have multiple root configuration files, running any command with
--config-pathwill now apply the chosen configuration file. -
#8171
79adaeaThanks @dibashthapa! - Added the new rulenoLeakedRender. This rule helps prevent potential leaks when rendering components that use binary expressions or ternaries.For example, the following code triggers the rule because the component would render
0:const Component = () => {const count = 0;return <div>{count && <span>Count: {count}</span>}</div>;}; -
#8116
b537918Thanks @Netail! - Added the nursery rulenoDuplicatedSpreadProps. Disallow JSX prop spreading the same identifier multiple times.Invalid:
<div {...props} something="else" {...props} /> -
#8256
f1e4696Thanks @cormacrelf! - Fixed a bug where logs were discarded (the kind from--log-level=infoetc.). This is a regression introduced after an internal refactor that wasn’t adequately tested. -
#8226
3f19b52Thanks @dyc3! - Fixed #8222: The HTML parser, with Vue directives enabled, can now parsev-slotshorthand syntax, e.g.<template #foo>. -
#8007
182ecdcThanks @brandonmcconnell! - Added support for dollar-sign-prefixed filenames in theuseFilenamingConventionrule.Biome now allows filenames starting with the dollar-sign (e.g.
$postId.tsx) by default to support naming conventions used by frameworks such as TanStack Start for file-based-routing. -
#8218
91484d1Thanks @hirokiokada77! - Added thenoMultiStrrule, which disallows creating multiline strings by escaping newlines.Invalid:
const foo ="Line 1\n\Line 2";Valid:
const foo = "Line 1\nLine 2";const bar = `Line 1Line 2`; -
#8225
98ca2aeThanks @ongyuxing! - Fixed #7806: Prefer breaking after the assignment operator for conditional types with generic parameters to match Prettier.type True = unknown extends Type<"many","generic","parameters","one","two","three">? true: false;type True =unknown extends Type<"many", "generic", "parameters", "one", "two", "three">? true: false; -
#6765
23f7855Thanks @emilyinure! - Fixed #6569: Allow files to export from themselves withnoImportCycles.This means the following is now allowed:
example.js export function example() {return 1;}// Re-exports all named exports from the current module under a single namespace// and then imports the namespace from the current module.// Allows for encapsulating functions/variables into a namespace instead// of using a static class.export * as Example from "./example.js";import { Example } from "./example.js"; -
#8214
68c052eThanks @hirokiokada77! - Added thenoEqualsToNullrule, which enforces the use of===and!==for comparison withnullinstead of==or!=.Invalid:
foo == null;foo != null;Valid:
foo === null;foo !== null; -
#8219
793bb9aThanks @dyc3! - Fixed #8190: The HTML parser will now parse Vue event handlers that contain:correctly, e.g.@update:modelValue="onUpdate". -
#8259
4a9139bThanks @hirokiokada77! - Fixed #8254: ThenoParameterAssignrule withpropertyAssignment: "deny"was incorrectly reporting an error when a function parameter was used on the right-hand side of an assignment to a local variable’s property.The rule should only flag assignments that modify the parameter binding or its properties (L-value), not the use of its value.
Valid:
(input) => {const local = { property: 0 };local.property = input;}; -
#8201
cd2edd7Thanks @Netail! - Added the nursery rulenoTernary. Disallow ternary operators.Invalid:
const foo = isBar ? baz : qux; -
#8172
de98933Thanks @JeremyMoeglich! - Fixed #8145: handling of large hex literals, which previously caused both false positives and false negatives.This affects
noPrecisionLossandnoConstantMathMinMaxClamp. -
#8210
7b44e9eThanks @Netail! - Corrected rule source reference.biome migrate eslintshould do a bit better detecting rules in your eslint configurations. -
#8213
e430555Thanks @ruidosujeira! - Fixed #8209: Recognized formatting capability when either range or on-type formatting is supported, not only full-file formatting. This ensures editors and the language server correctly detect formatting support in files like JSONC. -
#8202
6f49d95Thanks @hirokiokada77! - Fixed #8079: Properly handlenameandvaluemetavariables forJsxAttributeGritQL queries.The following
biome searchcommand no longer throws an error:biome search 'JsxAttribute($name, $value) as $attr where { $name <: "style" }' -
#8276
f7e836fThanks @hirokiokada77! - Added thenoProtorule, which disallows the use of the__proto__property for getting or setting the prototype of an object.Invalid:
obj.__proto__ = a;const b = obj.__proto__;Valid:
const a = Object.getPrototypeOf(obj);Object.setPrototypeOf(obj, b);
2.3.9
Patch Changes
-
#8232
84c9e08Thanks @ruidosujeira! - Added the nursery rulenoScriptUrl.This rule disallows the use of
javascript:URLs, which are considered a form ofevaland can pose security risks such as XSS vulnerabilities.<a href="javascript:alert('XSS')">Click me</a> -
#8341
343dc4dThanks @arendjr! - Added the nursery ruleuseAwaitThenable, which enforces thatawaitis only used on Promise values.Invalid
await "value";const createValue = () => "value";await createValue();Caution
This is a first iteration of the rule, and does not yet detect generic “thenable” values.
-
#8034
e7e0f6cThanks @Netail! - Added the nursery ruleuseRegexpExec. EnforceRegExp#execoverString#matchif no global flag is provided. -
#8137
d407efbThanks @denbezrukov! - Reduced the internal memory used by the Biome formatter. -
#8281
30b046fThanks @tylersayshi! - Added the ruleuseRequiredScripts, which enforces presence of configurable entries in thescriptssection ofpackage.jsonfiles. -
#8290
d74c8bdThanks @dyc3! - The HTML formatter has been updated to match Prettier 3.7’s behavior for handling<iframe>’sallowattribute.<iframe allow="layout-animations 'none'; unoptimized-images 'none'; oversized-images 'none'; sync-script 'none'; sync-xhr 'none'; unsized-media 'none';"></iframe><iframeallow="layout-animations 'none';unoptimized-images 'none';oversized-images 'none';sync-script 'none';sync-xhr 'none';unsized-media 'none';"></iframe> -
#8302
d1d5014Thanks @mlafeldt! - Fixed #8109: return statements in Astro frontmatter no longer trigger “Illegal return statement” errors when usingexperimentalFullSupportEnabled. -
#8346
f3aee1aThanks @arendjr! - Fixed #8292: Implement tracking of types of TypeScript constructor parameter properties.This resolves certain false negatives in
noFloatingPromisesand other typed rules.Example
class AsyncClass {async returnsPromise() {return "value";}}class ShouldBeReported {constructor(public field: AsyncClass) {}// ^^^^^^^^^^^^----------------- Parameter property declarationasync shouldBeReported() {// `noFloatingPromises` will now report the following usage:this.field.returnsPromise();}} -
#8326
153e3c6Thanks @ematipico! - Improved the rulenoBiomeFirstException. The rule can now inspect if extended configurations already contain the catch-all**insidefiles.includesand, if so, the rule suggests removing**from the user configuration. -
#8433
397547aThanks @dyc3! - Fixed #7920: The CSS parser, with Tailwind directives enabled, will no longer error when you use things likeprefix(tw)in@importat rules. -
#8378
cc2a62eThanks @Bertie690! - Clarify diagnostic message forlint/style/useUnifiedTypeSignaturesThe rule’s diagnostic message now clearly states that multiple similar overload signatures are hard to read & maintain, as opposed to overload signatures in general.
-
#8296
9d3ef10Thanks @dyc3! -biome ragenow shows if you have experimental HTML full support enabled. -
#8414
09acf2aThanks @Bertie690! - Updated the documentation & diagnostic message forlint/nursery/noProto, mentioning the reasons for its longstanding deprecation and why more modern alternatives are preferred.Notably, the rule clearly states that using
__proto__inside object literal definitions is still allowed, being a standard way to set the prototype of a newly created object. -
#8445
c3df0e0Thanks @tt-a1i! - Fix--changedand--stagedflags throwing “No such file or directory” error when a file has been deleted or renamed in the working directory. The CLI now filters out files that no longer exist before processing. -
#8459
b17d12bThanks @ruidosujeira! - Fix #8435: resolved false positive innoUnusedVariablesfor generic type parameters in construct signature type members (new <T>(): T). -
#8439
a78774bThanks @tt-a1i! - Fixed #8011:useConsistentCurlyBracesno longer suggests removing curly braces from JSX expression children containing characters that would cause parsing issues or semantic changes when converted to plain JSX text ({,},<,>,&). -
#8436
a392c06Thanks @ruidosujeira! - Fixed #8429. Formatter, linter, and assist settings now correctly inherit from global configuration when not explicitly specified in overrides.Before this fix, when an override specified only one feature (e.g., only
linter), other features would be incorrectly disabled instead of inheriting from global settings.Example configuration that now works correctly:
{"formatter": { "enabled": true },"overrides": [{"includes": ["*.vue"],"linter": { "enabled": false }}]}After this fix,
.vuefiles will have the linter disabled (as specified in the override) but the formatter enabled (inherited from global settings). -
#8411
9f1b3b0Thanks @rriski! - Properly handlename,type_arguments, andattributesslots forJsxOpeningElementandJsxSelfClosingElementGritQL patterns.The following biome search commands no longer throw errors:
Terminal window biome search 'JsxOpeningElement(name = $elem_name) where { $elem_name <: "div" }'biome search 'JsxSelfClosingElement(name = $elem_name) where { $elem_name <: "div" }' -
#8441
cf37d0dThanks @tt-a1i! - Fixed #6577:noUselessUndefinedno longer reports() => undefinedin arrow function expression bodies. Previously, the rule would flag this pattern and suggest replacing it with() => {}, which conflicts with thenoEmptyBlockStatementsrule. -
#8444
8caa7a0Thanks @tt-a1i! - FixnoUnknownMediaFeatureNamefalse positive forprefers-reduced-transparencymedia feature. The feature name was misspelled asprefers-reduded-transparencyin the keywords list. -
#8443
c3fa5a1Thanks @tt-a1i! - FixuseGenericFontNamesfalse positive when a CSS variable is used as the last value infont-familyorfont. The rule now correctly ignores cases likefont-family: "Noto Serif", var(--serif)andfont: 1em Arial, var(--fallback). -
#8281
30b046fThanks @tylersayshi! - FixednoDuplicateDependenciesincorrectly triggering on files like_package.json. -
#8315
c7915c4Thanks @hirokiokada77! - Fixed #5213: ThenoDoneCallbackrule no longer flags false positives when a method is called on a regular variable bound to identifiers such asbefore,after,beforeEach, andafterEach. -
#8398
204844fThanks @Bertie690! - The default value of theignoreRestSiblingsoption fornoUnusedVariables’ has been reverted to its prior value oftrueafter an internal refactor accidentally changed it.The diagnostic message has also been tweaked for readability.
-
#8242
9694e37Thanks @dyc3! - Fixed bugs in the HTML parser so that it will flag invalid shorthand syntaxes instead of silently accepting them. For example,<Foo : foo="5" />is now invalid because there is a space after the:. -
#8297
efa694cThanks @Yonom! - Added support for negative value utilities inuseSortedClasses. Negative value utilities such as-ml-2or-top-4are now recognized and sorted correctly alongside their positive counterparts.// Now detected as unsorted:<div class="-ml-2 p-4 -mt-1" />// Suggested fix:<div class="-mt-1 -ml-2 p-4" /> -
#8335
3710702Thanks @dibashthapa! - Added the new nursery ruleuseDestructuring. This rule helps to encourage destructuring from arrays and objects.For example, the following code triggers because the variable name
xmatches the propertyfoo.x, making it ideal for object destructuring syntax.var x = foo.x; -
#8383
59b2f9aThanks @ematipico! - Fixed #7927:noExtraNonNullAssertionincorrectly flagged separate non-null assertions on both sides of an assignment.The rule now correctly distinguishes between nested non-null assertions (still flagged) and separate non-null assertions on different sides of an assignment (allowed).
Examples
Valid (now allowed)
arr[0]! ^= arr[1]!;Invalid (still flagged)
arr[0]!! ^= arr[1];arr[0] ^= arr[1]!!; -
#8401
382786bThanks @Bertie690! -useExhaustiveDependenciesnow correctly validates custom hooks whose dependency arrays come before their callbacks.Previously, a logical error caused the rule to be unable to detect dependency arrays placed before hook callbacks, producing spurious errors and blocking further diagnostics.
{"linter": {"rules": {"correctness": {"useExhaustiveDependencies": {"level": "error","options": {"hooks": [{"name": "doSomething","closureIndex": 2,"dependenciesIndex": 0}]}}}}}}function component() {let thing = 5;// The rule will now correctly recognize `thing` as being specified// instead of erroring due to "missing" dependency arraysdoSomething([thing], "blah", () => {console.log(thing);});}The rule documentation & diagnostic messages have also been reworked for improved clarity.
-
#8365
8f36051Thanks @JacquesLeupin! - Fixed #8360: GritQL plugins defined in child configurations withextends: "//"now work correctly. -
#8306
8de2774Thanks @dibashthapa! - Fixed #8288: Fixed the issue with false positive errorsThis new change will ignore attribute and only show diagnostics for JSX Expressions
For example
Valid:
<Something checked={isOpen && items.length} />Invalid:
const Component = () => {return isOpen && items.length;}; -
#8356
f9673fcThanks @ematipico! - Fixed #7917, where Biome removed the styles contained in a<style lang="scss">, whenexperimentalFullSupportEnabledis enabled. -
#8371
d71924eThanks @ematipico! - Fixed #7343, where Biome failed to resolve extended configurations from parent directories using relative paths. -
#8404
6a221f9Thanks @fireairforce! - Fixed #7826, where a class member namedasyncwill not cause the parse error. -
#8249
893e36cThanks @cormacrelf! - Addressed #7538. Reduced the volume of logging from the LSP server.Use
biome cleanto remove large logs. -
#8303
db2c65bThanks @hirokiokada77! - Fixed #8300:noUnusedImportsnow detects JSDoc tags on object properties.import type LinkOnObjectProperty from "mod";const testLinkOnObjectProperty = {/*** {@link LinkOnObjectProperty}*/property: 0,}; -
#8328
9cf2332Thanks @Netail! - Corrected rule source reference.biome migrate eslintshould do a bit better detecting rules in your eslint configurations. -
#8403
c96dcf2Thanks @dyc3! - Fixed #8340:noUnknownPropertywill no longer flag anything in@pluginwhen the parser optiontailwindDirectivesis enabled -
#8284
4976d1bThanks @denbezrukov! - Improved the performance of the Biome Formatter by enabling the internal source maps only when needed. -
#8260
a226b28Thanks @ho991217! - Fixed biome-vscode#817: Biome now updates documents when thetextDocument/didSavenotification is received. -
#8183
b064786Thanks @hornta! - Fixed #8179: TheuseConsistentArrowReturnrule now correctly handles multiline expressions in its autofix when thestyleoption is set to"always".Previously, the autofix would incorrectly place a newline after the
returnkeyword, causing unexpected behavior.Example:
const foo = (l) => l.split("\n");Now correctly autofixes to:
const foo = (l) => {returnl.split('\n');return l.split('\n');} -
#8382
7409cbaThanks @fireairforce! - Fixed #8338: Ignored thenoUnknownTypeSelectorcheck when therootselector is used under View Transition pseudo-elements.Example
::view-transition-old(root),::view-transition-new(root) {z-index: 1;} -
#7513
e039f3bThanks @AsherDe! - Added the nursery rulenoVueSetupPropsReactivityLoss.This new rule disallows usages that cause the reactivity of
propspassed to thesetupfunction to be lost.Invalid code example:
export default {setup({ count }) {// `count` is no longer reactive here.return () => h("div", count);},};
2.3.10
Patch Changes
-
#8417
c3a2557Thanks @taga3s! - Fixed #7809:noRedeclareno longer reports redeclarations forinfertype in conditional types. -
#8477
90e8684Thanks @dyc3! - Fixed #8475: fixed a regression in hownoExtraNonNullAssertionflags extra non-null assertions -
#8479
250b519Thanks @dyc3! - Fixed #8473: The semantic model now indexes typescript constructor method definitions, and no longer panics if you use one (a regression in 2.3.9). -
#8448
2af85c1Thanks @mdevils! - Improved handling ofdefineProps()macro in Vue components. ThenoVueReservedKeysrule now avoids false positives in non-setup scripts. -
#8420
42033b0Thanks @vsn4ik! - Fixed the nursery rulenoLeakedRender.The
biome migrate eslintcommand now correctly detects the rulereact/jsx-no-leaked-renderin your eslint configurations. -
#8426
285d932Thanks @anthonyshew! - Added a Turborepo domain and a new “noUndeclaredEnvVars” rule in it for warning users of unsafe environment variable usage in Turborepos. -
#8410
a21db74Thanks @ematipico! - Fixed #2988 where Biome couldn’t handle properly characters that contain multiple code points when running instdinmode. -
#8372
b352ee4Thanks @Netail! - Added the nursery rulenoAmbiguousAnchorText, which disallows ambiguous anchor descriptions.Invalid
<a>learn more</a>
2.3.11
Patch Changes
-
#8583
83be210Thanks @dyc3! - Added the new nursery ruleuseVueValidTemplateRoot.This rule validates only root-level
<template>elements in Vue single-file components. If the<template>has asrcattribute, it must be empty. Otherwise, it must contain content.Invalid examples:
<template src="./foo.html">content</template><template></template>Valid examples:
<template>content</template><template src="./foo.html"></template> -
#8586
df8fe06Thanks @dyc3! - Added a new nursery ruleuseVueConsistentVBindStyle. Enforces consistentv-bindstyle (:propshorthand vsv-bind:proplonghand). Default prefers shorthand; configurable via rule options. -
#8587
9a8c98dThanks @dyc3! - Added the ruleuseVueVForKey, which enforces that any element usingv-foralso specifies akey.Invalid
<li v-for="item in items">{{ item }}</li>Valid
<li v-for="item in items" :key="item.id">{{ item }}</li> -
#8586
df8fe06Thanks @dyc3! - Added a new nursery ruleuseVueConsistentVOnStyle. Enforces consistentv-onstyle (@eventshorthand vsv-on:eventlonghand). Default prefers shorthand; configurable via rule options. -
#8583
83be210Thanks @dyc3! - Added the new nursery ruleuseVueValidVOnce. Enforces that usages of thev-oncedirective in Vue.js SFC are valid.<!-- Valid --><div v-once /><!-- Invalid --><div v-once:aaa /><div v-once.bbb /><div v-once="ccc" /> -
#8498
d80fa41Thanks @tt-a1i! - Fixed #8494. ExtendednoUndeclaredEnvVarsto support bracket notation (process.env["VAR"],import.meta.env["VAR"]), Bun runtime (Bun.env.VAR,Bun.env["VAR"]), and Deno runtime (Deno.env.get("VAR")). -
#8509
574a909Thanks @ematipico! - Added support for parsing and formatting the Svelte{#await}syntax, whenhtml.experimentalFullSupportEnabledis set totrue.{#await promise then name }{#await promise then name}{:catch name}{:catch name}{/await} -
#8316
d64e92dThanks @washbin! - Added the new nursery rulenoMultiAssign. This rule helps to prevent multiple chained assignments.For example, the following code triggers because there are two assignment expressions in the same statement.
const a = (b = 0); -
#8592
a5f59cdThanks @Netail! - Added the nursery ruleuseUniqueInputFieldNames. Require fields within an input object to be unique.Invalid:
query A($x: Int, $x: Int) {field} -
#8524
17a6156Thanks @JacquesLeupin! - Fixed #8488: Relative plugin paths are now resolved from the configuration file directory, including when configurations are merged (e.g.extends: "//"). -
#8655
3260ec9Thanks @JacquesLeupin! - Fixed #8636: Biome’s CSS formatter now breaks comma-separated declaration values at top-level commas when wrapping. -
#8537
cc3e851Thanks @dibashthapa! - Fixed #8491: Resolved false positive errors for safe boolean expressions. There are still pending fixes. Head to #8491 (comment) for more detailsThis new change will check for safe boolean expressions in variable declarations.
For example,
Valid:
let isOne = 1;let isPositiveNumber = number > 0;return (<div>{" "}{isOne && "One"} {isPositiveNumber && "Is positive"}</div>);Invalid:
let emptyStr = "";let isZero = 0;return (<div>{emptyStr && "Empty String"} {isZero && "Number is zero"}{" "}</div>); -
#8511
16a9036Thanks @ematipico! - Improved the diagnostics of the rulesuseSortedClassesandnoUnnecessaryConditions. The diagnostics now state that these rules are a work in progress and link to the relevant GitHub issue. -
#8521
a704be9Thanks @ToBinio! - Added the nursery ruleuseVueConsistentDefinePropsDeclaration, which enforces consistentdefinePropsdeclaration style.Invalid
<script setup lang="ts">const props = defineProps({kind: { type: String },});</script>Valid
<script setup lang="ts">const props = defineProps<{kind: string;}>();</script> -
#8595
7c85bf0Thanks @dyc3! - Fixed #8584: The HTML formatter will preserve whitespace after some elements and embedded expressions, which more closely aligns with Prettier’s behavior.<h1>Hello, {framework}and Svelte!</h1><h1>Hello, {framework} and Svelte!</h1> -
#8598
5e85d43Thanks @Netail! - Added the nursery ruleuseUniqueFieldDefinitionNames. Require all fields of a type to be unique.Invalid:
type SomeObject {foo: Stringfoo: String} -
#8495
b573d14Thanks @taga3s! - Fixed #8405:noMisusedPromisesnow emits warnings/errors when a function returns union types such asT | Promise<T>which is used in conditionals.const a = (): boolean | Promise<boolean> => Promise.resolve(true);if (a()) {} // Now correctly flagged -
#8632
0be7d12Thanks @Bertie690! - The documentation & rule sources forlint/complexity/noBannedTypeshave been updated to fix a few oversights.In addition to some general typo fixes:
-
The rule now recommends
Record<keyof any, never>instead ofRecord<string, never>(the latter of which incorrectly allows symbol-keyed properties). -
The rule mentions an alternate method to enforce object emptiness involving
unique symbol-based guards used bytype-festand many other packages:declare const mySym: unique symbol;// Since this type's only property is an unexported `unique symbol`, nothing that imports it can specify any properties directly// (as far as excess property checks go)export type EmptyObject = { [mySym]?: never };export type IsEmptyObject<T> = T extends EmptyObject ? true : false;
The rule’s listed sources have been updated as well to reflect the original source rule (
ban-types) having been split into 3 separate rules circa April 2024. -
-
#8580
a3a1ad2Thanks @taga3s! - Added the nursery rulenoBeforeInteractiveScriptOutsideDocumentto the Next.js domain. This rule prevents usage ofnext/script’sbeforeInteractivestrategy outside ofpages/_document.js. -
#8493
5fc24f4Thanks @ematipico! - Added support for parsing and formatting the Svelte{#each}syntax, whenhtml.experimentalFullSupportEnabledis set totrue.{#each items as item }{#each items as item}{/each} -
#8546
0196c0eThanks @Zaczero! - Hardened union static-member type flattening in edge cases (e.g. unions containingunknownor inferred expression types). This keeps inference conservative and avoids unstable type growth innode = node.parent-style loops. -
#8569
1022c76Thanks @ematipico! - Fixed an issue where the Biome HTML parser would emit a parse error when certain keywords are inside the text of HTML tags. -
#8606
f50723bThanks @dyc3! - Fixed #8563: fixed a bounds check on bogus regex literals that caused panics when doing type inference -
#7410
ab9af9aThanks @sgarcialaguna! - Added the new nursery rulenoJsxPropsBind. This rule disallows .bind(), arrow functions, or function expressions in JSX props.Invalid:
<Foo onClick={() => console.log("Hello!")}></Foo> -
#8523
5f22f1cThanks @ematipico! - Improved the diagnostics of nursery rules. Added a message to diagnostics emitted by nursery rules, so that users are aware of nature of nursery rules. -
#8571
03666fdThanks @dyc3! - Improved the performance ofnoRedeclareby eliminating string allocations -
#8591
9dd9ca7Thanks @Netail! - Added the nursery ruleuseUniqueArgumentNames. Enforce unique arguments for GraphQL fields & directives.Invalid:
query {field(arg1: "value", arg1: "value")} -
#8521
a704be9Thanks @ToBinio! - Update useVueDefineMacrosOrder to only run on -
#8344
7b982baThanks @ematipico! - Reduced the system calls when running the CLI. The performances might be noticeable in big projects that have multiple libraries and enable project rules. -
#8588
958e24bThanks @Netail! - Added the nursery ruleuseUniqueVariableNames. Enforce unique variable names for GraphQL operations.Invalid:
query ($x: Int, $x: Int) {field} -
#8529
8794883Thanks @mdevils! - Fixed #8499:useExhaustiveDependenciesproperly handles aliased destructured object keys when usingstableResultconfiguration. -
#8557
4df2f4dThanks @dyc3! - Fixed an issue with the HTML formatter where it wouldn’t add a space before the/>in self closing elements. This brings the HTML formatter more in line with Prettier.<Component/><Component /> -
#8509
574a909Thanks @ematipico! - Added support for parsing and formatting the Svelte{#snippet}syntax, whenhtml.experimentalFullSupportEnabledis set totrue.{#snippet foo() }{#snippet foo()}{/snippe} -
#8248
1231a5cThanks @emilyinure! - Added new nursery rulenoReturnAssign, which disallows assignments inside return statements.Invalid:
function f(a) {return (a = 1);} -
#8531
6b09620Thanks @taga3s! - Fixed #8472: The CSS parser can now accept multiple comma separated parameters in:active-view-transition-type. -
#8615
b9da66dThanks @taga3s! - Removenext/scriptcomponent name check fromnoBeforeInteractiveScriptOutsideDocumentsince it is a default export. -
#8536
efbfbe2Thanks @dyc3! - Fixed #8527: Improved type inference where analyzing code with repeated object property access and assignments (e.g.node = node.parent, a pattern common when traversing trees in a while loop) could hit an internal type limit. Biome now handles these cases without exceeding the type limit. -
#8583
83be210Thanks @dyc3! - Added the new nursery ruleuseVueValidVCloak. Enforces that usages of thev-cloakdirective in Vue.js SFC are valid.<!-- Valid --><div v-cloak /><!-- Invalid --><div v-cloak:aaa /><div v-cloak.bbb /><div v-cloak="ccc" /> -
#8583
83be210Thanks @dyc3! - Added the new nursery ruleuseVueValidVPre. Enforces that usages of thev-predirective in Vue.js SFC are valid.<!-- Valid --><div v-pre /><!-- Invalid --><div v-pre:aaa /><div v-pre.bbb /><div v-pre="ccc" /> -
#8644
a3a27a7Thanks @JacquesLeupin! - Added the nursery ruleuseVueVaporto enforce<script setup vapor>in Vue SFCs. For example<script setup>is invalid. -
#8508
b86842cThanks @tt-a1i! - Fixed #6783: now, when a path is provided via--stdin-file-path, Biome checks whether the file exists on disk. If the path doesn’t exist (virtual path), ignore checks (files.includesand VCS ignore rules) are skipped.
2.3.12
Patch Changes
-
#8653
047576dThanks @dyc3! - Added new nursery rulenoDuplicateAttributesto forbid duplicate attributes in HTML elements. -
#8648
96d09f4Thanks @BaeSeokJae! - Added a new nursery rulenoVueOptionsApi.Biome now reports Vue Options API usage, which is incompatible with Vue 3.6’s Vapor Mode. This rule detects Options API patterns in
<script>blocks,defineComponent(), andcreateApp()calls, helping prepare codebases for Vapor Mode adoption.For example, the following now triggers this rule:
<script>export default {data() {return { count: 0 };},};</script> -
#8832
b08270bThanks @Exudev! - Fixed #8809, #7985, and #8136: thenoSecretsrule no longer reports false positives on common CamelCase identifiers likepaddingBottom,backgroundColor,unhandledRejection,uncaughtException, andIngestGatewayLogGroup.The entropy calculation algorithm now uses “average run length” to distinguish between legitimate CamelCase patterns (which have longer runs of same-case letters) and suspicious alternating case patterns (which have short runs).
-
#8793
c19fb0eThanks @TheBaconWizard! - Properly handleparametersmetavariables forarrow_functionGritQL queries. The followingbiome searchcommand no longer throws an error:Terminal window biome search 'arrow_function(parameters=$parameters, body=$body)' -
#8561
981affbThanks @wataryooou! - FixednoUnusedVariablesto ignore type parameters declared in ambient contexts such asdeclare moduleblocks. -
#8817
652cfbbThanks @dyc3! - Fixed #8765: The HTML parser can now parse directive modifiers with a single colon, e.g.@keydown.:. -
#8704
a1914d4Thanks @Netail! - Added the nursery rulenoRootType. Disallow the usage of specified root types. (e.g.mutationand/orsubscription)Invalid:
{"options": {"disallow": ["mutation"]}}type Mutation {SetMessage(message: String): String} -
#8712
251b47bThanks @Netail! - Renamed the following GraphQL nursery rules to match the Biome standard:useUniqueArgumentNames->noDuplicateArgumentNamesuseUniqueFieldDefinitionNames->noDuplicateFieldDefinitionNamesuseUniqueGraphqlOperationName->noDuplicateGraphqlOperationNameuseUniqueInputFieldNames->noDuplicateInputFieldNamesuseUniqueVariableNames->noDuplicateVariableNames
Run the
biome migrate --writecommand to automatically update the configuration file. -
#7602
957cd8eThanks @kedevked! - Added the nursery lint ruleuseErrorCause.This rule enforces that errors caught in a
catchclause are not rethrown without wrapping them in a newErrorobject and specifying the original error as thecause. This helps preserve the error’s stack trace and context for better debugging.It can be configured with the following option:
requireCatchParameter: (default:true)- When
true, the rule requires thatcatchclauses have a parameter. If athrowstatement appears inside acatchclause without a parameter, it will be flagged.
- When
Invalid examples:
try {foo();} catch {throw new Error("fail");}try {foo();} catch (err) {throw new Error(err.message);}Valid examples:
try {foo();} catch (err) {throw new Error("fail", { cause: err });}try {foo();} catch (error) {throw new Error("Something went wrong", { cause: error });}Valid example when
requireCatchParameterisfalse:Valid:
try {foo();} catch {throw new Error("fail");} -
#8725
95aba98Thanks @dyc3! - Fixed #8715: The CSS parser will now recover slightly better if a semicolon is missing from Tailwind’s@applyat-rule. -
#8616
4ee3bdaThanks @Netail! - Added the nursery ruleuseLoneAnonymousOperation. Disallow anonymous operations when more than one operation specified in document.Invalid:
query {fieldA}query B {fieldB} -
#8624
291c9f2Thanks @taga3s! - Added the nursery ruleuseInlineScriptIdto the Next.js domain. This rule enforcesidattribute onnext/scriptcomponents with inline content ordangerouslySetInnerHTML.The following code is invalid:
import Script from "next/script";export default function Page() {return (<Script>{`console.log('Hello');`}</Script> // must have `id` attribute);} -
#8767
0d15370Thanks @mdevils! - Fixed #3512:useExhaustiveDependenciesnow properly handles nested destructuring patterns from hook results.const [[x, y], setXY] = useState([1, 2]);useEffect(() => {console.log(x, y);}, [x, y]); // x and y are now correctly recognized as unstable -
#8757
17ed9d3Thanks @Netail! - Added the nursery rulenoDivRegex. Disallow equal signs explicitly at the beginning of regular expressions.Invalid:
var f = function () {return /=foo/;}; -
#8836
aab1d17Thanks @dyc3! - Fixed #7858: Biome now parses Astro files with empty frontmatter blocks. -
#8755
3a15c29Thanks @arturalkaim! - Fixed #6670. The$filenamemetavariable can now be used in GritQLwhereclauses to filter matches by filename. -
#8821
63e68a1Thanks @playhardgopro! - Fixed several bugs in Vue conditional rules (useVueValidVIf,useVueValidVElse, anduseVueValidVElseIf) related to whitespace handling, newlines, and self-closing tags. -
#8767
0d15370Thanks @mdevils! - Fixed #3685:useExhaustiveDependenciesnow properly handles transparent expression wrappers like non-null assertions and type assertions in dependency comparisons.useMemo(() => Boolean(myObj!.x), [myObj!.x]); // No longer reports incorrect diagnosticsuseMemo(() => myObj!.x?.y === true, [myObj!.x?.y]); // Now correctly matches dependencies -
#8597
f764007Thanks @Netail! - Added the nursery rulenoDuplicateEnumValueNames. Enforce unique enum value names.Invalid:
enum A {TESTTesT} -
#8679
33dfd7cThanks @ematipico! - Fixed #8678. Now Biome correctly parses components inside Vue, Svelte and Astro files when they have the same name of self-closing elements. -
#8617
31a9bfeThanks @Netail! - Added the nursery ruleuseLoneExecutableDefinition. Require queries, mutations, subscriptions or fragments to be located in separate files.Invalid:
query Foo {id}fragment Bar on Baz {id} -
#8697
8519669Thanks @Faizanq! - Added the nursery lint rulenoExcessiveLinesPerFileto CSS and GraphQL. -
#8711
365f7aaThanks @Netail! - Added new nursery rulenoDuplicateEnumValues, which disallows defining an enum with multiple members initialized to the same value. -
#8767
0d15370Thanks @mdevils! - Fixed #5914:useExhaustiveDependenciesnow properly handles variables declared in the same statement.const varA = Math.random(),varB = useMemo(() => varA, [varA]); // varA is now correctly recognized as needed -
#8767
0d15370Thanks @mdevils! - Fixed #8427:useExhaustiveDependenciesnow properly resolves variable references to detect captured dependencies.const fe = fetchEntity;useEffect(() => {fe(id);}, [id, fe]); // fe is now correctly detected as needed -
#8767
0d15370Thanks @mdevils! - Fixed #8484:useExhaustiveDependenciesnow properly handles member access on stable hook results.const stableObj = useStable();useMemo(() => {return stableObj.stableValue; // stableObj.stableValue is now correctly recognized as stable}, []); -
#8767
0d15370Thanks @mdevils! - Fixed #7982:useExhaustiveDependenciesnow properly handles callback expressions with type assertions.const callback = useCallback((() => {return count * 2;}) as Function,[count], // count is now correctly detected); -
#8766
39eb545Thanks @Netail! - Fixed #8761: Reverted wrapping the URL of rule descriptions with<>, causing broken URLs in VSCode. -
#8767
0d15370Thanks @mdevils! - Fixed #3080:useExhaustiveDependenciesnow properly analyzes captures within referenced functions passed to hooks.function myEffect() {console.log(foo, bar);}useEffect(myEffect, [foo, bar]); // foo and bar are now correctly detected -
#8740
4962ed0Thanks @Netail! - Extra rule source references.biome migrate eslintshould do a bit better detecting rules in your eslint configurations. -
#8776
395746fThanks @codiini! - Fixed #6003:noUselessUndefinedInitializationno longer reports exported variables initialized toundefined. In Svelte 4, this pattern is used to declare optional component props. -
#8767
0d15370Thanks @mdevils! - Fixed #4248:useExhaustiveDependenciesnow correctly handles function props passed as callbacks.const data = React.useMemo(getData, [getData]); // getData is now correctly recognized as needed -
#8819
bc191ffThanks @Netail! - Fixed #6567:noUnknownPropertynow ignores unknown properties in at-rules which support descriptors. -
#8787
adb652fThanks @tuyuritio! - Fixed #8777: Add support for:active-view-transitionpseudo-class. -
#8639
6577e32Thanks @ohnoah! - Added the nursery lint rulenoExcessiveLinesPerFile. Biome now reports files that exceed a configurable line limit.// maxLines: 2const a = 1;const b = 2;const c = 3; -
#8753
71b5c6eThanks @Netail! - Added the nursery rulenoExcessiveClassesPerFile. Enforce a maximum number of classes per file.Invalid:
class Foo {}class Bar {} -
#8754
d6b2bdaThanks @Netail! - Added the nursery rulenoFloatingClasses. Disallownewoperators outside of assignments or comparisons.Invalid:
new Date();
2.3.13
Patch Changes
-
#8815
f924f23Thanks @dyc3! - ImproveduseVueValidVOnto be more closely aligned with the source rule. It will now properly allow modifiers for all possible keyboard events. It should have better performance when there are no violations of the rule as well.Now treated valid:
<div @keydown.arrow-down="handler"></div><div @keydown.a="handler"></div><div @keydown.b="handler"></div><div @keydown.27="foo"></div> -
#8856
85f81f9Thanks @dyc3! - Fixed #8710: Biome now parses Vue dynamic slot shorthand arguments that use template literals in[]. -
#8850
2a190e0Thanks @dyc3! - Fixed #8708: Tailwind@utilitydirectives now parse functional utility names likepx-*when Tailwind directives are enabled. -
#8863
79386e0Thanks @dyc3! - Fixed an issue withbiome migrate eslintwhere it couldn’t detect rules for CSS, GraphQL, and HTML. -
#8771
6f56b6eThanks @lghuahua! - Fix the--reporter=summaryoutput incorrectly merging and displaying wrong issue counts for different rules. Fixes #8730 -
#8714
ac3a71fThanks @Netail! - Added new nursery ruleuse-consistent-enum-value-type. This rule disallows enums from having both number and string members.
2.3.14
Patch Changes
-
#8921
29e2435Thanks @siketyan! - Fixed #8759: TheuseConsistentTypeDefinitionsrule no longer converts empty object type declarations into interfaces, as it will conflict with thenoEmptyInterfacerule and can cause an infinite loop when both rules are enabled. -
#8928
ccaeac4Thanks @taga3s! - Added the nursery ruleuseGlobalThis. This rule enforces usingglobalThisoverwindow,selfandglobal. -
#8602
9a18daaThanks @dyc3! - Added the new nursery rulenoVueArrowFuncInWatch. This rule forbids using arrow functions in watchers in Vue components, because arrow functions do not give access to the component instance (viathis), while regular functions do. -
#8905
9b1eea8Thanks @ryan-m-walker! - Fixed #8428: Improved parsing recovery when encountering qualified rules inside CSS@pageat-rule blocks. -
#8900
f788cffThanks @mdevils! - Fixed #8802:useExhaustiveDependenciesnow correctly suggests dependencies without including callback-scoped variables or method names.When accessing object properties with a callback-scoped variable, only the object path is suggested:
// Now correctly suggests `props.value` instead of `props.value[day]`useMemo(() => {return WeekdayValues.filter((day) => props.value[day]);}, [props.value]);When calling methods on objects, only the object is suggested as a dependency:
// Now correctly suggests `props.data` instead of `props.data.forEach`useMemo(() => {props.data.forEach((item) => console.log(item));}, [props.data]); -
#8913
e1e20eaThanks @dyc3! - Fixed #8363: HTML parser no longer crashes when encountering a<character followed by a digit in text content (e.g.,<12 months). The parser now correctly emits an “Unescaped<bracket character” error instead of treating<12as a tag name and crashing. -
#8910
2fb63a4Thanks @dyc3! - Fixed #8774: Type aliases with generic parameters that haveextendsconstraints now properly indent comments after the equals sign.Previously, comments after the
=in type aliases withextendsconstraints were not indented:type A<B, C extends D> = // Some commentundefined;type A<B, C extends D> =// Some commentundefined; -
#8916
ea4bd04Thanks @ryan-m-walker! - Fixed #4013, where comments in member chains caused unnecessary line breaks.// BeforeaFunction.b().c.d();// AfteraFunction.b().c.d(); -
#8945
fa66fe3Thanks @fireairforce! - Fixed #8354: Don’t remove quotes when type memeber is new.// Input:type X = {"new"(): string;"foo"(): string;};// Format Output:type X = {"new()": string;foo(): string;}; -
#8927
0ef3da5Thanks @littleKitchen! - Fixed #8907:useExhaustiveDependenciesnow correctly recognizes stable hook results (likeuseStatesetters anduseRefvalues) when declared withlet. -
#8931
4561751Thanks @koshin01! - Added the new nursery rulenoRedundantDefaultExport, which flags redundant default exports where the default export references the same identifier as a named export. -
#8900
f788cffThanks @mdevils! - Fixed #8883:useExhaustiveDependenciesno longer produces false positives when props are destructured in the function body of arrow function components without parentheses around the parameter.type Props = { msg: string };// Arrow function without parentheses around `props`const Component: React.FC<Props> = (props) => {const { msg } = props;// Previously, this incorrectly reported `msg` as unnecessaryuseEffect(() => console.log(msg), [msg]);}; -
#8861
3531687Thanks @dyc3! - Added thenoDeprecatedMediaTypeCSS rule to flag deprecated media types liketvandhandheld. -
#8775
7ea71cdThanks @igas! - Fixed thenoUnnecessararyConditionsrule to prevent trigger for optional fallback patterns. -
#8860
95f1eeaThanks @dyc3! - Added the nursery rulenoHexColors, which flags the use of hexadecimal color codes in CSS and suggests using named colors or RGB/RGBA/HSL/HSLA formats instead. -
#8786
d876a38Thanks @Bertie690! - Added the nursery ruleuseConsistentMethodSignatures.
Inspired by the similarly named version fromtypescript-eslint, this rule aims to enforce a consistent style for methods used inside object types and interfaces.Examples
Invalid code with
styleset to"property"(the default):interface Foo {method(a: string): void;}Invalid code with
styleset to"method":type Bar = {prop: (a: string) => void;} -
#8864
5e97119Thanks @dyc3! - Improved the summary provided bybiome migrate eslintto be clearer on why rules were not migrated. Biome now specifies a reason when a rule is not migrated, such as being incompatible with the formatter or not implemented yet. This helps users make more informed decisions when migrating their ESLint configurations to Biome. -
#8924
99b4cd1Thanks @tmohammad78! - Fixed #8920:noUnknownFunctionnow knows aboutsibling-count, andsibling-indexcss functions -
#8900
f788cffThanks @mdevils! - Fixed #8885:useExhaustiveDependenciesno longer incorrectly reports variables as unnecessary dependencies when they are derived from expressions containing post/pre-increment operators (++/--) or compound assignment operators (+=,-=, etc.).let renderCount = 0;export const MyComponent = () => {// `count` is now correctly recognized as a required dependency// because `renderCount++` can produce different values between rendersconst count = renderCount++;useEffect(() => {console.log(count);}, [count]); // no longer reports `count` as unnecessary}; -
#8619
d78e01dThanks @Netail! - Added the nursery ruleuseInputName. Require mutation arguments to be called “input”, and the input type to be called Mutation name + “Input”.Invalid:
type Mutation {SetMessage(message: String): String} -
#8922
871b45eThanks @siketyan! - Fixed #8829: Revamped thenoGlobalDirnameFilenamerule to catch many false negatives that have not been reported.
2.3.15
Patch Changes
-
#9019
043b67cThanks @dyc3! - Added the lint rulenoNestedPromises. This rule detects nested.then()or.catch()calls that could be refactored into flat promise chains.// Invalid: nested promise that can be flatteneddoThing().then(function () {return doOtherThing().then(console.log);});// Valid: flat promise chaindoThing().then(() => doOtherThing()).then(console.log);The rule intelligently allows nesting when the inner callback references variables from the outer scope, as these cases cannot be safely flattened.
-
#9029
6ebf6c6Thanks @ff1451! - Added the nursery rulenoUselessReturn. The rule reports redundantreturn;statements that don’t affect the function’s control flow.// Invalid: return at end of function is redundantfunction foo() {doSomething();return;} -
#9017
8bac2daThanks @mdevils! - Reverted a behavior change inuseExhaustiveDependenciesthat was accidentally included as part of the #8802 fix. The change made method calls on objects (e.g.,props.data.forEach(...)) report only the object (props.data) as a missing dependency instead of the full member expression. This behavior change will be reconsidered separately. -
#9005
c8dbbbeThanks @corvid-agent! - Fixed #8790: ThenoAssignInExpressionsrule no longer reports a false positive when an assignment is used as the expression body of an arrow function (e.g.,const f = b => a += b). -
#8519
ccdc602Thanks @ruidosujeira! - Fixed #8518, where globally excluded files in a monorepo were still being processed when using"extends": "//".When a package-level configuration extends the root configuration with
"extends": "//", glob patterns (such as those infiles.includes) are now correctly resolved relative to the project root directory, instead of the current workspace directory. -
#9033
0628e0aThanks @mdevils! - Fixed #8967. useExhaustiveDependencies no longer reports false positives for variables destructured from a rest pattern. -
#9023
8ef9d1dThanks @siketyan! - Fixed #9020: Whenjavascript.jsxRuntimeis set toreactClassic,noUnusedImportsanduseImportTyperules now allow importing theReactidentifier from a package other thanreact. This aligns the behavior withtsc(--jsx=react), which also allows importingReactfrom any package. -
#8646
16fd71dThanks @siketyan! - Fixed #8605: Text expressions in some template languages ({{ expr }}or{ expr }) at the top level of an HTML document no longer causes panicking. -
#8930
51c158eThanks @ANKANJAGTAP! - Fixed #8917 useExhaustiveDependencies now correctly detects JSX component identifiers as hook dependencies. -
#9009
7d229c7Thanks @Netail! - Fixed typo in noPositiveTabindex’s quick fix text. -
#8758
8c789f1Thanks @Pranav2612000! - Updated the useJsxKeyInIterable rule to not run inside Map constructors -
#8977
bbe0e0cThanks @FrankFMY! - Fixed #4888. noUnusedImports now addsexport {}when removing the last import in a TypeScript file to prevent it from becoming an ambient module. This does not apply to embedded scripts in Vue, Svelte, or Astro files, which are already in a module context. -
#9016
9d4cfa3Thanks @dyc3! - Added eslint migration metadata for the rules@typescript/no-var-requires,@typescript/keyword-spacing,@typescript/func-call-spacing,vue/keyword-spacing,vue/func-call-spacing, andunicorn/empty-brace-spaces, -
#8848
2cba2b3Thanks @LouisLau-art! - Fixed #8845. NowuseGenericFontNamesdoesn’t trigger whenfontis declared inside the@supportsat-rule. -
#8997
a5f3212Thanks @mldangelo! - Fixed #8476. useAwaitThenable no longer reports false positives forawaiton call expressions whose return type cannot be resolved (e.g., cross-module function calls to Node.js builtins or npm packages). -
#8978
cc7a478Thanks @FrankFMY! - Fixed #8645. useAwait no longer reportsasyncgenerator functions that useyield*, sinceyield*in an async generator delegates to anAsyncIterableand requires theasyncmodifier.
2.4.0
Minor Changes
-
#8964
0353fa0Thanks @dyc3! - Addedignoreoption to theuseHookAtTopLevelrule.You can now specify function names that should not be treated as hooks, even if they follow the
use*naming convention.Example configuration:
{"linter": {"rules": {"correctness": {"useHookAtTopLevel": {"options": {"ignore": ["useDebounce", "useCustomUtility"]}}}}}} -
#8769
d0358b0Thanks @rahuld109! - Added the ruleuseAnchorContentfor HTML to enforce that anchor elements have accessible content for screen readers. The rule flags empty anchors, anchors with only whitespace, and anchors where all content is hidden witharia-hidden. Anchors witharia-labelortitleattributes providing a non-empty accessible name are considered valid. -
#8742
6340ce6Thanks @rahuld109! - Added the ruleuseMediaCaptionto the HTML language. Enforces thataudioandvideoelements have atrackelement withkind="captions"for accessibility. Muted videos are allowed without captions. -
#8621
d11130bThanks @Netail! - Added support for multiple reporters, and the ability to save reporters on arbitrary files.Combine two reporters in CI
If you run Biome on GitHub, take advantage of the reporter and still see the errors in console, you can now use both reporters:
Terminal window biome ci --reporter=default --reporter=githubSave reporter output to a file
With the new
--reporter-fileCLI option, it’s now possible to save the output of all reporters to a file. The file is a path, so you can pass a relative or an absolute path:Terminal window biome ci --reporter=rdjson --reporter-file=/etc/tmp/report.jsonbiome ci --reporter=summary --reporter-file=./reports/file.txtYou can combine these two features. For example, have the
defaultreporter written on terminal, and therdjsonreporter written on file:Terminal window biome ci --reporter=default --reporter=rdjson --reporter-file=/etc/tmp/report.jsonThe
--reporterand--reporter-fileflags must appear next to each other, otherwise an error is thrown. -
#8399
ab88099Thanks @ematipico! - The Biome CSS parser is now able to parse Vue SFC syntax such as:slottedand:deep. These pseudo functions are only correctly parsed when the CSS is defined inside.vuecomponents. Otherwise, Biome will a emit a parse error.This capability is only available when
experimentalFullHtmlSupportedEnabledis set totrue. -
#8663
3dfea16Thanks @ematipico! - Added support for Cursor files. When Biome sees a Cursor JSON file, it will parse it with comments enabled and trailing commas enabled:$PROJECT/.cursor/%APPDATA%\Cursor\User\on Windows~/Library/Application Support/Cursor/User/on macOS~/.config/Cursor/User/on Linux
-
#8723
fe2c642Thanks @cbstns! - Added JSON as a target language for GritQL pattern matching. You can now write Grit plugins for JSON files.This enables users to write GritQL patterns that match against JSON files, useful for:
- Searching and transforming JSON configuration files
- Enforcing patterns in
package.jsonand other JSON configs - Writing custom lint rules for JSON using GritQL
Example patterns:
Match all key-value pairs:
language jsonpair(key = $k, value = $v)Match objects with specific structure:
language jsonJsonObjectValue()Supports both native Biome AST names (
JsonMember,JsonObjectValue) and TreeSitter-compatible names (pair,object,array) for compatibility with existing Grit patterns.For more details, see the GritQL documentation.
-
#8814
4d9c676Thanks @Netail! - Addedignoreoption tonoUnknownProperty. If an unknown property name matches any of the items provided inignore, a diagnostic won’t be emitted. -
#8631
4d8f19dThanks @Netail! - Add a new reporter--reporter=sarif, that emits diagnostics using the SARIF format. -
#8270
4f7909dThanks @lucasweng! - Added theuseIframeTitlelint rule for HTML. The rule enforces the usage of thetitleattribute for theiframeelement.Invalid:
<iframe></iframe> <iframe title=""></iframe>Valid:
<iframe title="title"></iframe> -
#8164
1d25856Thanks @ematipico! - Added a new assist actionuseSortedInterfaceMembersthat sorts TypeScript interface members, for readability.It includes an autofix.
Invalid example.
interface MixedMembers {z: string;a: number;(): void;y: boolean;}Valid example (after using the assist).
interface MixedMembers {a: number;y: boolean;z: string;(): void;} -
#8647
4c7c06fThanks @siketyan! - It’s now possible to provide the stacktrace for a fatal error. The stacktrace is only available when the environment variableRUST_BACKTRACE=1is set, either via the CLI or exported$PATH. This is useful when providing detailed information for debugging purposes:Terminal window RUST_BACKTRACE=1 biome lint -
#7961
a04c8dfThanks @siketyan! - The Biome Language Server now reports progress while scanning files and dependencies in the project. -
#8289
a9025d4Thanks @theshadow27! - Fixed #8024. The ruleuseIterableCallbackReturnnow supports acheckForEachoption. When set tofalse, the rule will skip checking forforEach()callbacks for returning values. -
#8690
e06e5d1Thanks @ematipico! - Added the ruleuseValidLangto the HTML language. -
#7847
e90b14fThanks @Jagget! - Added support forjsxFactoryandjsxFragmentFactory.Biome now respectsjsxFactoryandjsxFragmentFactorysettings fromtsconfig.jsonwhen using the classic JSX runtime, preventing false positive noUnusedImports errors for custom JSX libraries like Preact.tsconfig.json {compilerOptions: {jsx: "react",jsxFactory: "h",jsxFragmentFactory: "Fragment",},}Component.jsx import { h, Fragment } from "preact";function App() {return <div>Hello</div>;} -
#8071
7f5bcf4Thanks @ematipico! - Added new CLI options to the commandslsp-proxyandstartthat allow to control the Biome file watcher.--watcher-kindControls how the Biome file watcher should behave. By default, Biome chooses the best watcher strategy for the current OS, however sometimes this could result in some issues, such as folders locked.
The option accepts the current values:
recommended: the default option, which chooses the best watcher for the current platform.polling: uses the polling strategy.none: it doesn’t enable the watcher. When the watcher is disabled, changes to files aren’t recorded anymore by Biome. This might have repercussions on some lint rules that might rely on updated types or updated paths.
The environment variable
BIOME_WATCHER_KINDcan be used as alias.--watcher-polling-intervalThe polling interval in milliseconds. This is only applicable when using the
pollingwatcher. It defaults to2000milliseconds.The environment variable
BIOME_WATCHER_POLLING_INTERVALcan be used as alias. -
#8262
4186b83Thanks @lucasweng! - Added theuseHtmlLanglint rule for HTML. The rule enforces that thehtmlelement has alangattribute.Invalid:
<html></html><html lang></html><html lang=""></html>Valid:
<html lang="en"></html> -
#8376
1a9334cThanks @siketyan! - Added support for formatting and linting embedded GraphQL snippets in JavaScript.For example, the following snippets are now formatted:
import gql from "graphql-tag";const PeopleCountQuery = gql`query PeopleCount {allPeople {totalCount}}`;import { graphql } from "./graphql";const PeopleCountQuery = graphql(`query PeopleCount {allPeople {totalCount}}`);This feature is experimental and must be enabled explicitly in the configuration:
{"javascript": {"experimentalEmbeddedSnippetsEnabled": true}} -
#7799
54682aaThanks @PaulRBerg! - AddedgroupByNestingoption to theuseSortedKeysassist. When enabled, object keys are grouped by their value’s nesting depth before sorting alphabetically.Simple values (primitives, single-line arrays, and single-line objects) are sorted first, followed by nested values (multi-line arrays and multi-line objects).
Example
To enable this option, configure it in your
biome.json:{"linter": {"rules": {"source": {"useSortedKeys": {"options": {"groupByNesting": true}}}}}}With this option, the following unsorted object:
const object = {name: "Sample",details: {description: "nested",},id: 123,};Will be sorted as:
const object = {id: 123,name: "Sample",details: {description: "nested",},}; -
#8641
1dc8dc2Thanks @tt-a1i! - Added thenoAutofocuslint rule for HTML. This rule enforces that theautofocusattribute is not used on elements, as it can cause usability issues for sighted and non-sighted users. The rule allowsautofocusinsidedialogelements or elements with thepopoverattribute, as these are modal contexts where autofocus is expected. -
#8501
8eb3f19Thanks @tt-a1i! - AddednoPositiveTabindexto HTML. This rule prevents the usage of positive integers on thetabindexattribute, which can disrupt natural keyboard navigation order. -
#8661
b36ff03Thanks @tt-a1i! - Added theuseAltTextlint rule for HTML. This rule enforces that elements requiring alternative text (<img>,<area>,<input type="image">,<object>) provide meaningful information for screen reader users viaalt,title(for objects),aria-label, oraria-labelledbyattributes. Elements witharia-hidden="true"are exempt. -
#7749
1c59333Thanks @andogq! - Implements #1984. UpdateduseHookAtTopLevelto better catch invalid hook usage.This rule is now capable of finding invalid hook usage in more locations. A diagnostic will now be generated if:
- A hook is used at the module level (top of the file, outside any function).
- A hook is used within a function or method which is not a hook or component, unless it is a function expression (such as arrow functions commonly used in tests).
Invalid:
// Invalid: hooks cannot be called at the module level.useHook();// Invalid: hooks must be called from another hook or component.function notAHook() {useHook();}Valid:
// Valid: hooks may be called from function expressions, such as in tests.test("my hook", () => {renderHook(() => useHook());renderHook(function () {return useHook();});}); -
#8307
789b0e7Thanks @mehm8128! - Added theuseValidAriaRolelint rule for HTML. The rule enforces that elements with ARIA roles must use a valid, non-abstract ARIA role. -
#8814
4d9c676Thanks @Netail! - Addedignoreoption tonoUnknownFunction. If an unknown function name matches any of the items provided inignore, a diagnostic won’t be emitted. -
#8814
4d9c676Thanks @Netail! - Addedignoreoption tonoUnknownPseudoClass. If an unknown pseudo-class name matches any of the items provided inignore, a diagnostic won’t be emitted. -
#8623
dc1f94eThanks @mldangelo! - Added thenoDuplicateClassesassist action to detect and remove duplicate CSS classes.For JSX files: Supports
class,classNameattributes and utility functions likeclsx,cn,cva.For HTML files: Checks
classattributes. This is the first assist action for HTML.// Before<div class="flex p-4 flex" />;// After<div class="flex p-4" />; -
#8399
ab88099Thanks @ematipico! - Improved the CSS parser for CSS modules. Biome now automatically enables CSS modules parsing for*.module.cssfiles.If your codebase has only
*.module.cssfiles, you can remove the parser feature as follows, because now Biome does it for you:{"css": {"parser": {"cssModules": true}}} -
#8399
ab88099Thanks @ematipico! - Added support for parsing:globaland:localinside.astro,.svelteand.vuefiles, in<style>portion of the file.This capability is only available when
experimentalFullHtmlSupportedEnabledis set totrue. -
#9011
e014336Thanks @ematipico! - Promoted 21 nursery rules to stable groups.Correctness
Promoted the following rules to the
correctnessgroup:noUnresolvedImports. The rule reports imports that cannot be resolved. The default rule severity is set toerror.noVueReservedProps. The rule reports Vue reserved props usage. The default rule severity is set toerror.noVueReservedKeys. The rule reports Vue reserved keys usage. The default rule severity is set toerror.noVueDataObjectDeclaration. The rule reports Vue 2 data declared as an object instead of a function. The default rule severity is set towarn.noNextAsyncClientComponent. The rule reports async Next.js client components. The default rule severity is set towarn.noVueDuplicateKeys. The rule reports duplicate keys in Vue component options. The default rule severity is set toerror.noVueSetupPropsReactivityLoss. The rule reports destructuring of props in Vue 3 setup which causes reactivity loss. The default rule severity is set toerror.useQwikMethodUsage. The rule enforces correct Qwik framework method usage. The default rule severity is set toerror.useQwikValidLexicalScope. The rule enforces valid lexical scope in Qwik framework. The default rule severity is set toerror.
Suspicious
Promoted the following rules to the
suspiciousgroup:noImportCycles. The rule reports circular imports. The default rule severity is set towarn.noDeprecatedImports. The rule reports imports of deprecated symbols. The default rule severity is set towarn.noReactForwardRef. The rule reports usage ofReact.forwardRef. The default rule severity is set towarn.noUnusedExpressions. The rule reports expressions that are never used. The default rule severity is set towarn.noEmptySource. The rule reports empty source files. The default rule severity is set towarn.useDeprecatedDate. The rule enforces use of GraphQL@deprecateddirective with date. The default rule severity is set towarn.noDuplicateDependencies. The rule reports duplicate dependencies in package.json. The default rule severity is set towarn.
Complexity
Promoted the following rules to the
complexitygroup:noUselessUndefined. The rule reports uselessundefinedinitialization and returns. The default rule severity is set toinfo.useMaxParams. The rule enforces a maximum number of function parameters. The default rule severity is set towarn.noUselessCatchBinding. The rule reports useless catch binding parameters. The default rule severity is set toinfo.
Style
Promoted the following rules to the
stylegroup:useConsistentArrowReturn. The rule enforces consistent return in arrow functions. The default rule severity is set toinfo.noJsxLiterals. The rule reports literal strings in JSX. The default rule severity is set toinfo.
-
#8695
d8f0309Thanks @ematipico! - Added support for the top-level suppression commentbiome-ignore-all format: <explanation>.When the comment
biome-ignore-all format: <explanation>is placed at the beginning of the document, Biome won’t format the code.The feature works for all supported languages. In the following JavaScript snippet, the code isn’t formatted and will stay as is.
// biome-ignore-all format: generatedconst a = [];const a = [];const a = []; -
#8255
da85e3cThanks @ryan-m-walker! - Added support for the typedattrfunction. Addresses issue #6183.Example
.btn {width: attr(data-size type(<length> | <percentage>), 0px);} -
#8165
e0b3f62Thanks @lucasweng! - Added thenoAccessKeylint rule for HTML. The rule enforces that theaccesskeyattribute is not used on any HTML element, as it can conflict with keyboard commands used by screen readers and keyboard-only users.Invalid:
<input type="submit" accesskey="s" value="Submit" /><a href="https://webaim.org/" accesskey="w">WebAIM.org</a><button accesskey="n">Next</button>Valid:
<input type="submit" value="Submit" /><a href="https://webaim.org/">WebAIM.org</a><button>Next</button> -
#8278
7207effThanks @ematipico! - Added a feature that allows editors to inject a Biome configuration to the Biome Language Server without affecting the configuration of the project.If you have a Biome extension that is compatible with your preferred LSP-ready editor, you can map
inlineConfig. The configuration will be merged with the configuration of the project (or the default configuration):For example, with the Zed editor, you would have the following configuration, which will format all files using four spaces as indentation style:
.zed/settings.json {lsp: {biome: {settings: {inline_config: {formatter: {indentStyle: "space",indentWidth: 4,},},},},},} -
#8368
8aa5f5bThanks @Bertie690! - Added 2 options fromtypescript-eslint(ignoreDifferentlyNamedParametersandignoreDifferentJsDoc) touseUnifiedTypeSignatures.Each option makes the rule ignore overload signatures whose parameter names or JSDoc comments differ.
Examples
Valid code with
ignoreDifferentlyNamedParametersset totrue:function cook(scoops: IceCreamScoop[]): void;function cook(cakeType: string): void;Valid code with
ignoreDifferentJsDocset totrue:/** Does objs have "cow" inside it? */function hasCow(objs: string[]): boolean;/** @deprecated - convert to array */function hasCow(objs: string): boolean; -
#8562
361350eThanks @dyc3! - Added the rule profiler behind the--profile-rulescli flag. You can now see a report of which lint rules took the longest to execute. -
#8234
e2e6e66Thanks @ongyuxing! - Updated the CSS properties ordering to align withstylelint-config-recess-orderv7.4.0.It adds support for:
- Containment properties
- Font synthesis properties
- Ruby properties
- Color adjustment properties
- View transitions properties
- Shapes properties
- Motion path properties
- etc.
For the complete list of changes, see: https://github.com/stormwarning/stylelint-config-recess-order/compare/v6.0.0…v7.4.0.
-
#8814
4d9c676Thanks @Netail! - Addedignoreoption tonoUnknownPseudoElement. If an unknown pseudo-element name matches any of the items provided inignore, a diagnostic won’t be emitted. -
#8663
3dfea16Thanks @ematipico! - Added the ability to load the configuration from new known paths. Biome now attempts to load the configuration files from the following locations:$XDG_CONFIG_HOMEor$HOME/.config/biomeon Linux/Users/$USER/Library/Application Support/biomeon macOSC:\Users\$USER\AppData\Roaming\biome\configon Windows
The priority how Biome will attempt to load the configuration files is the following:
- project folder (working directory)
- parent folders
- config home
$XDG_CONFIG_HOMEor$HOME/.config/biomeon Linux/Users/$USER/Library/Application Support/biomeon macOSC:\Users\$USER\AppData\Roaming\biome\configon Windows
-
#7973
bc0e8b4Thanks @siketyan! - Added support for formatting and linting embedded CSS snippets in JavaScript.For example, the following snippets are now formatted and linted:
import styled from "styled-components";const Foo = styled.div`display: flex;color: red;`;import styled from "@emotion/styled";const Foo = styled(Box)`display: flex;color: red;`;import { css } from "@emotion/react";const style = css`display: flex;color: red;`;However, snippets with interpolations are not supported yet. For example, the following snippet isn’t formatted:
import styled from "@emotion/styled";const Foo = styled.div<{ color: string }>`display: flex;color: ${(props) => props.color};`;This feature is experimental and must be enabled explicitly in the configuration:
{"javascript": {"experimentalEmbeddedSnippetsEnabled": true}} -
#8381
50c3513Thanks @mehm8128! - Added theuseAriaPropsForRolelint rule for HTML. The rule enforces that elements with ARIA roles must have all required ARIA attributes for that role. -
#7762
5901d79Thanks @dyc3! - Added theextensionMappingsoption touseImportExtensions. This allows users to specify custom file extensions for different module types.For example, if you want to ban all
.tsimports in favor of.jsimports, you can now do so with this option:{"options": {"extensionMappings": {"ts": "js"}}} -
#8532
01bccc8Thanks @jonaylor89! - Added--onlyand--skipoptions tobiome checkandbiome ci, covering both lint diagnostics and assist actions. Biome now lets you run or exclude specific lint rules, assist actions, group or rules and actions, or domains when running these commands.Examples:
Terminal window biome check --only=suspicious/noDebugger src/**/*.jsbiome ci --skip=project src/** -
#8666
7733f90Thanks @ematipico! - Added the rulenoRedundantAltto HTML. The rule enforces that theimgelementaltattribute does not contain the words “image”, “picture”, or “photo”. -
#8287
a248e88Thanks @mehm8128! - Added thenoDistractingElementslint rule for HTML. The rule enforces that no distracting elements like<marquee>or<blink>are used. -
#8564
adcce82Thanks @ematipico! - Added the new linter domaintypes. This is a domain that enables all rules that require the type inference engine.As opposed to the
projectdomain, which only enables rules that require the module graph to function.The following nursery rules have been moved to the
typesdomain:useArraySortCompareuseAwaitThenableuseFinduseRegexpExecnoUnnecessaryConditionsnoMisusedPromisesnoFloatingPromises
-
#8556
47a79f1Thanks @mehm8128! - Added two new behaviors to thenoSvgWithoutTitlerule.- Support for
graphics-documentandgraphics-symbolroles. - Support for multiple role specifications.
- Support for
-
#8663
3dfea16Thanks @ematipico! - Added the ability to load the hidden files.biome.jsonand.biome.jsonc. This is the order how Biome will attempt the configuration file is:biome.jsonbiome.jsonc.biome.json.biome.jsonc
-
#8334
ae8ac8eThanks @ematipico! - Added the formatter optiontrailingNewline.When set to
false, the formatter will remove the trailing newline at the end of formatted files. The default value istrue, which preserves the current behavior of adding a trailing newline.This option is available globally and for each language-specific formatter configuration:
{"formatter": {"trailingNewline": false},"javascript": {"formatter": {"trailingNewline": true}}}The following CLI flags have been added. They accept
trueorfalseas value:--formatter-trailing-newline--javascript-formatter-trailing-newline--json-formatter-trailing-newline--graphql-formatter-trailing-newline--css-formatter-trailing-newline--html-formatter-trailing-newline
-
#8854
1469968Thanks @ematipico! - Formatting is now applied when applying safe/unsafe fixes viabiome check. -
#8642
46f33a7Thanks @ematipico! - Improved the rulenoUnusedVariablesin Svelte files, by correctly detecting variables defined in the JavaScript blocks, and used inside the templates. -
#8839
79b38aaThanks @ryan-m-walker! - Added support for parsing and formatting the CSS@functionat-rule from the CSS Mixins Module Level 1 specification. Addresses issue #8184.@function --transparent(--color <color>, --alpha <number>: 0.5) returns<color> {result: oklch(from var(--color) l c h / var(--alpha));} -
#8412
73f4f53Thanks @mehm8128! - Added thenoSvgWithoutTitlelint rule to HTML. The rule enforces the usage of thetitleelement for thesvgelement. -
#8243
4291ff3Thanks @ashnewmanjones! - Added theuseButtonTypelint rule for HTML. The rule enforces that thetypeattribute is present and valid on all button elements.Invalid:
<button>Do something</button><button type="incorrectType">Do something</button><button type>Do something</button><button type />Valid:
<button type="button">Do something</button><button type="reset">Do something</button><button type="submit" />
Patch Changes
-
#8898
7e48bd4Thanks @ematipico! - Added e18e ESLint plugin as a recognized rule source. Six Biome rules now reference their e18e equivalents:useAtIndex,useExponentiationOperator,noPrototypeBuiltins,useDateNow,useSpread, anduseObjectSpread. -
#8719
a215408Thanks @ematipico! - Added proper parsing and formatting for Svelte directives when thehtml.experimentalFullSupportEnabledis set totrue. -
#8071
7f5bcf4Thanks @ematipico! - Revamped the logging options for all Biome commands. Now the commandsformat,lint,check,ci,search,lsp-proxyandstartaccept the following CLI options.Some options might have been present before, but they were inconsistent. Plus, all new options have an environment variable as aliases.
--log-fileOptional path/file to redirect log messages to. This option is applicable only to the CLI. If omitted, logs are printed to stdout.
Environment variable alias:
BIOME_LOG_FILE--log-prefix-nameAllows changing the prefix applied to the file name of the logs. This option is applicable only to the daemon.
Environment variable alias:
BIOME_LOG_PREFIX_NAME--log-pathAllows changing the folder where logs are stored. This option is applicable only to the daemon.
Environment variable alias:
BIOME_LOG_PATH--log-levelThe level of logging. In order, from the most verbose to the least verbose:
debug,info,warn,errorThe value
nonewon’t show any logging.Environment variable alias:
BIOME_LOG_LEVEL--log-kindWhat the log should look like.
Environment variable alias:
BIOME_LOG_KINDReduce dumping of LSP logs
When you use a Biome editor extension, Biome’s Daemon dumps its logs using the
debuglevel. If you want to reduce the quantity of these logs, you can now customize it:Terminal window BIOME_LOG_LEVEL=info biome lsp-proxy -
#8663
3dfea16Thanks @ematipico! - Fixed #901. Biome now allows trailing commas in inside Zedsettings.jsonand VSCodesettings.json. -
#8669
683f50dThanks @tt-a1i! - Fixed #8628:useComponentExportOnlyModulesnow allows components referenced as object property values in exported expressions. This fixes false positives for TanStack Router patterns.export const Route = createFileRoute('/')({component: HomeComponent,})function HomeComponent() { ... } // no longer reported as "should be exported" -
#9060
0e47f5aThanks @dyc3! - Fixed #9057: Incorrect diagnostic spans for suppression comments and other raw diagnostics in HTML-ish files (Vue, Svelte, Astro). Previously, diagnostics like “unused suppression” pointed to the wrong location in the document due to the diagnostic offset not being applied. -
#9028
5ac2ad6Thanks @LouisLau-art! - Fixed #9024: Biome no longer reports<hr role="presentation">undernoInteractiveElementToNoninteractiveRole. -
#9072
8656fc0Thanks @dyc3! - Fixed #9068: ThenoVueDuplicateKeysrule now correctly handlestoRefs(props)patterns and no longer produces false positives when destructuring props, particularly in<script setup>blocks. -
#9049
c0ab6ddThanks @ematipico! - Fixed #7138. Now the Biome language server correctly handles theconfigurationPathsetting coming from the editor extension. -
#8556
47a79f1Thanks @mehm8128! - Fixed thenoSvgWithoutTitlerule not to recursively traversetitleelements. -
#8894
6bf1b09Thanks @ematipico! - Added proper parsing for spread attributes{...props}in Svelte and Astro files. -
#8833
375792eThanks @dyc3! - Fixed #4927, #6407: The HTML formatter will now correctly break a block-like element if it has more than 2 children, and at least one of them is another block-like element.<div>a<div>b</div> c</div><div>a<div>b</div>c</div> -
#8854
1469968Thanks @ematipico! - Fixed#7912, where Biome incorrectly added a leading newline to the code contained inside the Astro frontmatter. -
#8806
cb112ceThanks @dyc3! - Major Breaking Changes to the HTML formatter onlyThe HTML formatter (which is still experimental) has been completely overhauled from the ground up to more closely resemble Prettier’s formatting. If you have opted in to the HTML formatter, you may see large formatting diffs for your HTML, Vue, Svelte, and Astro files.
This overhaul fixes several issues (#5150, #6625, #8437) around whitespace sensitivity that were causing incorrect formatting in certain scenarios that were difficult or impossible to fully address before.
-
#8700
0f5a05bThanks @ematipico! - Improved the rulesuseConst,noUnusedImports,useImportTypesandnoUnusedVariablesinside Vue, Svelte and Astro files whenexperimentalFullSupportEnabledis set totrue.Now variables and components that are imported or defined inside the files won’t trigger false positives.
Until now, we suggested disabling these rules with an override. Now the rules are more stable; however, you might still experience a few false positives. Those are probably issues caused by our parser.
If you use
experimentalFullSupportEnabled, you can remove the following override:{"overrides": [{"includes": ["**/*.svelte", "**/*.astro", "**/*.vue"],"linter": {"rules": {"style": {"useConst": "off","useImportType": "off"},"correctness": {"noUnusedVariables": "off","noUnusedImports": "off"}}}}]} -
#8485
bf02ba6Thanks @ematipico! - Fixed an issue where some info diagnostics weren’t tracked by the final summary. -
#8846
5701eadThanks @dyc3! - Fixed #8692: Biome now accepts Vue’sv-bind()function in CSS when Vue CSS modules parsing is enabled. -
#9012
18cdd45Thanks @kiroushi! - Fixed plugin diagnostics showing incorrect line numbers in Vue, Astro, and Svelte files. Plugin diagnostics now correctly account for the template/frontmatter offset, pointing to the right location in the<script>block.
2.4.1
Patch Changes
-
#9092
6edd600Thanks @ematipico! - Fixed #9052. This PR reverts changes introduced by https://github.com/biomejs/biome/pull/8519, which caused unwanted changes on how paths are resolved. -
#9091
3bf674dThanks @ematipico! - Fixed #9090, where SCSS files were incorrectly processed by Biome. This was a regressions caused by the latest developments for supporting SCSS out of the box. -
#9100
66931a8Thanks @siketyan! - Fixed #9081: ThenoUnknownPseudoElementrule no longer reports false positives for any known pseudo elements in CSS modules. This was a regression introduced in v2.4.0. -
#9102
d01b903Thanks @ematipico! - Fixed #9095, where Biome didn’t print anything in stdin mode. This was a regression caused by a recent, internal refactor.
2.4.2
Patch Changes
-
#9103
fc9850cThanks @dyc3! - Fixed #9098:useImportTypeno longer incorrectly flags imports used in Svelte control flow blocks ({#if},{#each},{#await},{#key}) as type-only imports. -
#9106
f4b7296Thanks @dyc3! - Updated rule source metadata for rules fromhtml-eslint. -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoConditionalExpect. This rule disallows conditionalexpect()calls inside tests, which can lead to tests that silently pass when assertions never run.// Invalid - conditional expect may not runtest("conditional", async ({ page }) => {if (someCondition) {await expect(page).toHaveTitle("Title");}});// Valid - unconditional expecttest("unconditional", async ({ page }) => {await expect(page).toHaveTitle("Title");}); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightElementHandle. Prefers locators to element handles.const el = await page.$(".btn"); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightEval. Disallowspage.$eval()andpage.$$eval()methods.await page.$eval(".btn", (el) => el.textContent); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightForceOption. Disallows theforceoption on user interactions.await locator.click({ force: true }); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightMissingAwait. Enforces awaiting async Playwright APIs.const el = page.locator(".btn");el.click(); // Missing await -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightNetworkidle. Disallows deprecatednetworkidlewait option.await page.goto(url, { waitUntil: "networkidle" }); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightPagePause. Disallowspage.pause()debugging calls in committed code.await page.pause(); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightUselessAwait. Disallows unnecessaryawaiton synchronous Playwright methods.// Incorrect - locator() is synchronousconst loc = await page.locator(".btn"); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightWaitForNavigation. Prefers modern navigation APIs over deprecatedwaitForNavigation().await page.waitForNavigation(); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightWaitForSelector. Prefers locators over deprecatedwaitForSelector().await page.waitForSelector(".btn"); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery rulenoPlaywrightWaitForTimeout. Disallows hard-coded timeouts withwaitForTimeout().await page.waitForTimeout(5000); -
#8960
4a5ff40Thanks @abossenbroek! - EnhancednoSkippedTeststo detect Playwright patterns (.fixme,test.describe,test.step, bracket notation, bare calls). ConsolidatednoPlaywrightSkippedTestinto this rule. -
#9101
0c0fb6fThanks @siketyan! - Fixed#9080: ThenoUnusedVariablesrule no longer reports a top-levelPropsinterface or type alias as unused in Astro files. -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery ruleuseExpect. This rule ensures that test functions contain at least oneexpect()assertion.// Invalid - test without assertiontest("no assertion", async ({ page }) => {await page.goto("/");});// Valid - test with assertiontest("has assertion", async ({ page }) => {await expect(page).toHaveTitle("Title");}); -
#8960
4a5ff40Thanks @abossenbroek! - Added the nursery ruleusePlaywrightValidDescribeCallback. Validates that describe callback signatures are not async.test.describe("suite", async () => {});
2.4.3
Patch Changes
-
#9120
aa40fc2Thanks @ematipico! - Fixed #9109, where the GitHub reporter wasn’t correctly enabled whenbiome ciruns on GitHub Actions. -
#9128
8ca3f7fThanks @dyc3! - Fixed #9107: The HTML parser can now correctly parse Astro directives (client/set/class/is/server), which fixes the formatting for Astro directives. -
#9124
f5b0e8dThanks @ematipico! - Fixed #8882 and #9108: The Astro frontmatter lexer now correctly identifies the closing---fence when the frontmatter contains multi-line block comments with quote characters, strings that mix quote types (e.g."it's"), or escaped quote characters (e.g."\"). -
#9142
3ca066bThanks @THernandez03! - Fixed #9141: ThenoUnknownAttributerule no longer reportsclosedbyas an unknown attribute on<dialog>elements. -
#9126
792013eThanks @ematipico! - Added missing Mocha globals to theTestdomain:context,run,setup,specify,suite,suiteSetup,suiteTeardown,teardown,xcontext,xdescribe,xit, andxspecify. These are injected by Mocha’s BDD and TDD interfaces and were previously flagged as undeclared variables in projects using Mocha. -
#8855
6918c9eThanks @ruidosujeira! - Fixed #8840. Now the Biome CSS parser correctly parsesnot + scroll-stateinside@containerqueries. -
#9111
4fb55cfThanks @Jayllyz! - Slightly improved performance ofnoIrregularWhitespaceby adding early return optimization and simplifying character detection logic. -
#8975
086a0c5Thanks @FrankFMY! - Fixed #8478:useDestructuringno longer suggests destructuring when the variable has a type annotation, likeconst foo: string = object.foo.
2.4.4 Latest
Patch Changes
-
#9150
6946835Thanks @dyc3! - Fixed #9138: Astro files containing---in HTML content (e.g.,<h1>---Hi</h1>) are now parsed correctly, both when a frontmatter block is present and when there is no frontmatter at all. -
#9150
aa6f837Thanks @dyc3! - Fixed #9138: The HTML parser incorrectly failing to parse bracket characters ([and]) in text content (e.g.<div>[Foo]</div>). -
#9151
c0d4b0cThanks @dyc3! - Fixed parsing of Svelte directive keywords (use,style) when used as plain text content in HTML/Svelte files. Previously,<p>use JavaScript</p>or<p>style it</p>would incorrectly produce a bogus element instead of proper text content. -
#9162
7f1e060Thanks @dyc3! - Fixed #9161: The Vue parser now correctly handles colon attributes likexlink:hrefandxmlns:xlinkby parsing them as single attributes instead of splitting them into separate tokens. -
#9164
458211bThanks @dyc3! - Fixed #9161: ThenoAssignInExpressionsrule no longer flags assignments in Vue v-on directives (e.g.,@click="counter += 1"). Assignments in event handlers are idiomatic Vue patterns and are now skipped by the rule.
Copyright (c) 2023-present Biome Developers and Contributors.