2.4.14
Patch Changes
-
#9393
491b171Thanks @dyc3! - Added the nursery ruleuseTestHooksOnTopin thetestdomain. The rule flags lifecycle hooks (beforeEach,beforeAll,afterEach,afterAll) that appear after test cases in the same block, enforcing that hooks are defined before any test case. -
#10157
eefc5abThanks @dyc3! - Fixed #7882: The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as<br></br>. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags. -
#10054
0e9f569Thanks @minseong0324! -noMisleadingReturnTypeno longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to: object.A function annotated
: objectreturning an object literal:function f(): object { return { retry: true }; }
-
#10116
53269ebThanks @jiwon79! - Fixed #6201:noUselessEscapeInRegexno longer flags an escaped backslash followed by-as a useless escape. Patterns like/[\\-]/are now considered valid because the second\is the escaped backslash, not an unnecessary escape of the trailing dash. -
#10092
33d8543Thanks @Conaclos! - Fixed #9097:organizeImportsno longer adds a blank line between a never-matched group and a matched group.Given the following
organizeImportsoptions:{ "groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"] }The following code...
// Comment import "package"; import "./file.js";
...was organized as:
+ // Comment import "package"; + import "./file.js";
A blank line was added even though the group ':NODE:' doesn't match any imports here.
:BLANK_LINE:between never-matched groups and matched groups are now ignored.
The code is now organized as:// Comment import "package"; + import "./file.js"; -
#10138
a10b6c1Thanks @dyc3! - Fixed Vuev-forhandling fornoUndeclaredVariablesandnoUnusedVariables. Biome now recognizes variables declared byv-fordirectives and references to iterated values in Vue templates. -
#10115
d428d76Thanks @minseong0324! -noMisleadingReturnTypeno longer reports false positives when a union return type'sbooleanvariant is covered by bothtrueandfalsereturns. -
#9922
7acf1e0Thanks @dyc3! - Added the new nursery rulenoReactStringRefs, which disallows legacy React string refs such asref="hello"andthis.refs.hello.Biome also reports template-literal refs such as
ref={`hello`}, so React code can consistently migrate to callback refs,createRef(), oruseRef(). -
#10010
f3e76abThanks @dyc3! - Fixed a bug in the LSP file watcher registration so Biome now watches.biome.jsonand.biome.jsoncconfiguration files and reloads workspace settings when they change. -
#10176
8a40ef8Thanks @dyc3! - Fixed #10011: ThenoThisInStaticrule no longer reportsthiswhen it is used as the constructor target innew this(...), which is required for inherited static factory methods. -
#10163
6867e96Thanks @jiwon79! - Fixed #9884: TheuseSortedAttributesauto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic. -
#10079
d29dd19Thanks @Damix48! - Fixed false positive innoAssignInExpressionsfor Svelte{@const}blocks. Assignments in{@const name = value}are now correctly recognized as declarations rather than accidental assignments in expressions. -
#10080
5d8fdacThanks @Damix48! - Fixed parsing of closing parentheses in Svelte{#each}block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys.For example, the following snippets are now parsed correctly:
{#each numbers as number, index (number.toString())} <p>{number}</p> {/each} {#each numbers as number (key(number))} <p>{number}</p> {/each} -
#10140
e7024b9Thanks @solithcy! - Fixed #10135: Biome no longer crashes on missing Svelte template expressions.The following code snippet longer panics:
{#if } <p>^ this would previously crash</p> {/if} {@const } <p> ^ this would also crash</p> -
#10111
7818009Thanks @jiwon79! - Fixed #9997:noDuplicateSelectorsno longer reports false positives for selectors inside@scopequeries. Biome now treats@scopeas a separate at-rule context, like@media,@supports,@container, and@starting-style.The following snippet is no longer flagged as a duplicate:
.Example { padding: 0; } @scope (.theme-dark) { .Example { color: white; } }
-
#9926
d62b331Thanks @dyc3! - Added the nursery lint ruleuseMathMinMax, which prefersMath.min()andMath.max()over equivalent ternary comparisons.For example, this code:
const min = a < b ? a : b;
is much more readable when rewritten as:
const min = Math.min(a, b);
-
#10115
d428d76Thanks @minseong0324! -useExhaustiveSwitchCasesnow flags missingtrue/falsecases forbooleandiscriminants, including whenbooleanis a union variant. -
#10125
a55a0b6Thanks @bmish! - Fixed a resolver bug where packages that define a typed entry point throughpackage.json'smainfield but omittypeswere ignored during type-aware resolution. Type-aware rules such asnoFloatingPromisescan now inspect imports from those packages. -
#10117
895e809Thanks @denizdogan! - Added support for thecorner-shapefamily of CSS properties and thesuperellipse()/squircle()value functions, sonoUnknownPropertyandnoUnknownFunctionno longer flag them as unknown.New known properties:
corner-shape,corner-block-end-shape,corner-block-start-shape,corner-bottom-left-shape,corner-bottom-right-shape,corner-bottom-shape,corner-end-end-shape,corner-end-start-shape,corner-inline-end-shape,corner-inline-start-shape,corner-left-shape,corner-right-shape,corner-start-end-shape,corner-start-start-shape,corner-top-left-shape,corner-top-right-shape,corner-top-shape.New known value functions:
superellipse(),squircle(). -
#8620
8df8f73Thanks @dyc3! - Fixed #8062: Added support for parsing Vuev-fordirectives more accurately. -
#10191
aa055cdThanks @guney! - Now the rulenoStaticElementInteractionsdoesn't trigger custom elements. -
#9757
2c62594Thanks @dyc3! - Fixed #9099: the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children.For example, the following Svelte snippet is now preserved instead of being collapsed to
<div>{name}<!-- comment --></div>:<div> {name}<!-- comment --> </div>
Similarly, HTML elements like
<span>inside a<div>are now preserved when written on their own line:<div> <span>text</span> </div>
-
#10105
e7c1a6dThanks @jiwon79! - Fixed #10039:useReadonlyClassPropertiesnow detects unreassigned private members in class expressions and export default classes, not only in class declarations.The following patterns are now correctly flagged:
const AnonClass = class { #prop = 123; constructor() { console.log(this.#prop); } }; export default class { #prop = 123; constructor() { console.log(this.#prop); } }
-
#10141
46a77d0Thanks @minseong0324! - ImprovednoUnnecessaryConditionsto detect conditions that are always truthy because they check built-in global class instances such asDate,Map,Set,WeakMap, andError. -
#10178
7b05a89Thanks @dyc3! - Fixed #10177: The HTML parser no longer reports lowercasehtmlordoctypetext as invalid after void elements such as<br>. -
#10155
0d4595dThanks @jiwon79! - Fixed #10045: the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as:not(:where(...)),:is(:where(...)), and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including:nth-child(... of ...),::part(...), and:active-view-transition-type(...).
The following snippet is now correctly formatted, matching Prettier.input:not( :where( [type="submit"], [type="checkbox"], [type="radio"], [type="button"], [type="reset"] ) ) { inline-size: 100%; }
-
#10112
6f0251eThanks @dyc3! - Fixed #10110: Biome's parser now accepts surrogate code points in JavaScript string\u{...}escapes. -
#10141
46a77d0Thanks @minseong0324! - ImprovednoMisleadingReturnTypeto detectobjectreturn annotations that hide built-in global class instances such asDate,Map,Set,WeakMap, andError. -
#10083
4a664c1Thanks @ematipico! - Added two new options tonoShadow, both defaulting totrueto match typescript-eslint's behavior.Fixed #9482: Added
ignoreFunctionTypeParameterNameValueShadowoption. When enabled, parameter names inside function type annotations (e.g.(options: unknown) => void) are not flagged as shadowing outer variables.Fixed #7812: Added
ignoreTypeValueShadowoption. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript. -
#9286
52695cfThanks @Hugo-Polloli! - Fixed #6316: Biome now resolves Svelte$storereferences to the underlyingstorebinding in semantic analysis, preventing falsenoUndeclaredVariablesdiagnostics when the store is declared. -
#10188
ae659ddThanks @dyc3! - Added a new nursery rulenoExcessiveNestedCallbacks, which disallows callbacks nested deeper than the configured maximum. -
#9757
2c62594Thanks @dyc3! - Fixed #9450: the HTML formatter now correctly preserves multiline formatting for nested<template>elements (e.g.<template #body>) when the source has children on separate lines. Previously, the children were collapsed onto a single line.<template> <UModal> - <template #body> <p>content</p> </template> + <template #body> + <p>content</p> + </template> </UModal> </template>
-
#10118
c6edcb4Thanks @Netail! - Fixed #10024:biome migrate eslintcorrectly migrateseslintrules that belong to multiple Biome rules.
What's Changed
- chore(docs): minor updates for contributing and skills by @dyc3 in #10098
- fix(semantic): resolve Svelte $store references in semantic model by @Hugo-Polloli in #9286
- fix(format/html): preserve block indentation if already present in some cases by @dyc3 in #9757
- fix(md/formatter): nested italic by @tidefield in #10078
- fix(deps): update @biomejs packages by @renovate[bot] in #10061
- fix(analyzer): useReadonlyClassProperties detects non-declaration class forms by @jiwon79 in #10105
- fix(noShadow): make sure it doesn't shadow types by @ematipico in #10083
- chore: prepare goverance for contractors by @ematipico in #10087
- feat(analyze/html): add some utilities to speed up lookups of multiple attributes by @dyc3 in #10109
- fix(lint): resolve false positive in noAssignInExpressions for Svelte {@const} blocks by @Damix48 in #10079
- fix(analyzer): noDuplicateSelectors false positives with scope at-rule by @jiwon79 in #10111
- fix(parser): correctly consume closing parenthesis in Svelte each key expression by @Damix48 in #10080
- feat(lint/js): add
useTestHooksOnTopby @dyc3 in #9393 - fix(deps): update dependency prettier to v3.8.3 by @renovate[bot] in #10062
- fix(parse/js): lex surrogate codepoints in string literal escapes by @dyc3 in #10112
- fix(analyzer): noUselessEscapeInRegex no longer flags
\\-as useless by @jiwon79 in #10116 - feat(css): support corner-shape, superellipse, and squircle by @denizdogan in #10117
- fix(lsp): inform clients that .biome.json(c) should also be watched by @dyc3 in #10010
- chore(deps): update rust crate jiff to 0.2.24 by @renovate[bot] in #10128
- chore(deps): update dependency tombi to v0.9.22 by @renovate[bot] in #10127
- fix(resolver): resolve typed package main entries by @bmish in #10125
- chore(deps): update dependency @changesets/cli to v2.31.0 by @renovate[bot] in #10132
- chore(deps): update dependency dprint to v0.54.0 by @renovate[bot] in #10133
- fix(deps): update @biomejs packages by @renovate[bot] in #10130
- chore(deps): update rust crate libc to 0.2.186 by @renovate[bot] in #10129
- chore(deps): update rust crate mimalloc to 0.1.50 by @renovate[bot] in #10060
- feat(parse/html/vue): parse v-for better by @dyc3 in #8620
- feat(parse/html/vue): nested destructuring in v-for by @dyc3 in #10136
- fix(noCommaOperator): remove vue v-for hack by @dyc3 in #10137
- fix(10024): eslint generation by @Netail in #10118
- feat(markdown_formatter): enable formatter ir debugger by @tidefield in #10144
- fix(lint): detect misleading object returns for built-in class instances by @minseong0324 in #10141
- fix: svelte missing expression crash by @solithcy in #10140
- fix(md/fmt/parser): bom, quotes, trimming by @ematipico in #10040
- fix(vue): recognize embedded bindings in v-for directives by @dyc3 in #10138
- feat(css_formatter): improve SCSS include argument formatting by @denbezrukov in #10147
- feat(css_formatter): align SCSS map closing comments by @denbezrukov in #10149
- fix(organizeImports): doesn't add a blank line between a never-matched group and a matched group by @Conaclos in #10092
- fix(parser/md): handle vertical tab by @ematipico in #10146
- fix(lint): noMisleadingReturnType false positive on union with exhausted boolean by @minseong0324 in #10115
- feat(css_formatter): include SCSS comments by @denbezrukov in #10150
- refactor(css_formatter): clarify SCSS include closing comments by @denbezrukov in #10153
- fix(format/css): align selector list indentation with Prettier by @jiwon79 in #10155
- fix(lint): noMisleadingReturnType false negative on object keyword by @minseong0324 in #10054
- feat(css_formatter): improve handling of SCSS trailing separator comm… by @denbezrukov in #10154
- feat(css_formatter): improve handling of SCSS list trailing separator comments by @denbezrukov in #10156
- feat(css_formatter): improve handling of SCSS expression item line comments by @denbezrukov in #10158
- feat(css_formatter): improve handling of SCSS
@at-rootselector comments and formatting by @denbezrukov in #10160 - feat(lint/js): add
noReactStringRefsby @dyc3 in #9922 - feat(lint/js): add
useMathMinMaxby @dyc3 in #9926 - feat(css_formatter): improve handling of SCSS
@if-elsecomments and formatting by @denbezrukov in #10162 - feat(css_formatter): improve handling of SCSS
@whilerule formatting by @denbezrukov in #10164 - feat(css_formatter): improve handling of SCSS
@forrule formatting by @denbezrukov in #10165 - feat(css_formatter): improve handling of SCSS parenthesized binary expressions formatting by @denbezrukov in #10167
- fix(assist): useSortedAttributes no longer corrupts nested JSX attributes by @jiwon79 in #10163
- feat(css_formatter): improve handling of SCSS
@eachrule formatting by @denbezrukov in #10169 - fix(markdown_parser): blockquote list splitting and tightness by @jfmcdowell in #9990
- chore(markdown_parser): remove unused lexer contexts by @jfmcdowell in #10173
- fix(parse/html): relex keywords as text in text contexts by @dyc3 in #10178
- feat(css_formatter): improve handling of SCSS list with trailing separator by @denbezrukov in #10172
- fix(noThisInStatic): don't report
new this()by @dyc3 in #10176 - feat(css): support SCSS interpolated values by @denbezrukov in #10171
- feat(css_formatter): improve handling of SCSS
@useand@forwardrule formatting by @denbezrukov in #10180 - fix(markdown_parser): stop nested lazy lists from swallowing fences by @jfmcdowell in #10170
- feat(css): add support for SCSS media query interpolation by @denbezrukov in #10181
- feat(css_formatter): improve handling of spacing for SCSS unary expressions and functions by @denbezrukov in #10182
- feat(lint/js): add
noExcessiveNestedCallbacksby @dyc3 in #10188 - fix(markdown_parser): keep lazy link references as text by @jfmcdowell in #10189
- fix(lint/a11y/noStaticElementInteractions): exclude custom elements by @guney in #10191
- fix(parse/html): improve the diagnostics when void elements have a closing tag by @dyc3 in #10157
- ci: release by @github-actions[bot] in #10100
New Contributors
- @Hugo-Polloli made their first contribution in #9286
- @Damix48 made their first contribution in #10079
- @denizdogan made their first contribution in #10117
- @solithcy made their first contribution in #10140
- @guney made their first contribution in #10191
Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14