2.6.7
Patch Changes
-
#12906
b3375d2Thanks @dyc3! - Added the nursery rulenoAsyncPromiseFinally, which reports async functions passed to a promise's.finally()method. If such a function fails, its error replaces the original result or error of the promise.promise.finally(async () => { await cleanup(); });
-
#12894
e24da6fThanks @dyc3! - Added the nursery rulenoDuplicateTypeConstituents, which reports types listed more than once in a union or intersection type, andundefinedin the type of an optional parameter.type T = string | number | string; function f(a?: string | undefined) {}
-
#12899
6c15027Thanks @dyc3! - Added the nursery rulenoExcessiveSelectorComplexity, which limits how many IDs, type selectors, attribute selectors, pseudo-classes, universal selectors, compound selectors, and combinators a CSS selector can contain. It can also disallow chosen combinators, pseudo-classes, pseudo-elements, attributes, and attribute operators. The rule does nothing until an option is set.For example, with
"maxIds": 1, the following selector is reported:#main #sidebar {}
-
#12897
0b8f429Thanks @dyc3! - Added the new nursery rulenoInvalidFetchOptions, which reports abodyin the options offetch()andnew Request()when the method isGETorHEAD. These calls throw aTypeErrorat runtime. When nomethodis given, the request usesGET.await fetch("/", { method: "GET", body: "foo=bar" });
-
#12926
9b6b9f4Thanks @dyc3! - Added the nursery rulenoNewArray, which reportsnew Array()calls with a single argument. Such a call creates an empty array of the given length when the argument is a number, and an array that holds the argument otherwise.const array = new Array(length);
-
#12895
739440fThanks @dyc3! - Added the new nursery rulenoRedundantTypeConstituents, which reports members of union and intersection types that have no effect, such as a literal type next to its primitive type, orneverin a union.type Status = "active" | string;
-
#12810
71ab61bThanks @dyc3! - Added the nursery rulenoSvelteAsyncStore, which disallows passing async functions to thewritable(),readable(), andderived()stores fromsvelte/store.import { writable } from "svelte/store"; const user = writable(null, async (set) => { set(await fetchUser()); });
-
#12917
37d9f41Thanks @dyc3! - Added the new nursery rulenoUnresolvedDefaultImport, which reports default imports from modules that have no default export. The rule is part of theprojectdomain.// foo.js only contains `export function foo() {}` import foo from "./foo.js";
-
#12892
f16842eThanks @dyc3! - Added the nursery rulenoUselessFallbackInSpread, which reports empty object fallbacks when spreading a value into an object. Spreadingnull,undefined, or another falsy value into an object adds no properties, so the fallback has no effect.const object = { ...(options || {}) };
-
#12785
c198be2Thanks @dyc3! - Added the new nursery rulenoUselessParameterPropertyAssignment, which reports constructor assignments such asthis.name = namewhennameis a parameter property. TypeScript already sets the property to the parameter's value, so the assignment does nothing.class User { constructor(public name: string) { this.name = name; } }
-
#12900
a4d1b0fThanks @dyc3! - Added the nursery rulenoUselessSpread, which reports spread syntax that has no effect. For example,[first, ...[second]]can be written as[first, second], andnew Set([...items])can be written asnew Set(items). -
#12902
d7d755bThanks @dyc3! - Added the nursery rulenoVueExposeAfterAwait, which reportsexpose()anddefineExpose()calls that come after anawaitin a Vue component's setup code. These calls run too late, so a parent component might not receive the exposed properties.<script setup> await fetchUser(); defineExpose({ reload }); </script>
-
#12596
d33e56eThanks @dyc3! - Added the nursery ruleuseAtomicUpdates, which reports assignments in async functions and generators that can be based on an outdated value because the function paused at anawaitoryieldafter reading it.let total = 0; async function addToTotal(getAmount) { total += await getAmount(); // reported }
-
#12901
48e3572Thanks @dyc3! - Added the new nursery ruleuseConsistentBooleanName. It requires variables, parameters, and functions that hold or return a boolean to start with a prefix such asisorhas, and reports names with those prefixes that don't hold or return a boolean.const completed = progress === 100; const hasName = "Sindre";
-
#12905
5b00387Thanks @dyc3! - Added the nursery ruleuseConsistentFontWeightNotation, which enforces writing font weights either as numbers or as the keywordsnormalandboldwhere possible. It checks thefont-weightandfontproperties, and its safe fix converts betweennormal/boldand400/700.a { font-weight: bold; }
-
#12922
8d33c85Thanks @dyc3! - Added the nursery ruleuseConsistentTupleLabels, which reports tuple type elements without a label when other elements of the same tuple have one.type Point = [x: number, number];
-
#12925
7252cbdThanks @dyc3! - Added the new nursery ruleuseGlobalRegexInMatchAll, which reports calls tomatchAll()with a regular expression that doesn't have thegflag. These calls throw aTypeErrorat runtime.text.matchAll(/pattern/);
-
#12891
e781bc3Thanks @dyc3! - Added the nursery ruleuseGlobalRegexInReplaceAll, which reports regular expressions without thegflag passed toreplaceAll(). These calls throw aTypeErrorinstead of replacing text.withSpaces.replaceAll(/\s+/, ",");
-
#12896
a968e1aThanks @dyc3! - Added the new nursery ruleuseValidCharacterComparison, which reports comparisons between a single character and a string that has more than one character. Such comparisons are alwaysfalse, or alwaystruewith!==and!=.text.charAt(0) === "ab";
-
#13085
7a795d0Thanks @ematipico! - Fixed withastro/compiler-rs#221 so Astro template expressions containing comment-only JSX expression children, such as<span>{<!-- x -->}</span>, parse without diagnostics. -
#12621
79ce388Thanks @latin-1! - Fixed #12413 and #12414:useSortedPropertiesnow sorts consecutive groups of properties independently, preserving the positions of nested rules, at-rules, and SCSS variable declarations. -
#13065
bd9faaeThanks @ematipico! - Fixed #5848: runninguseSortedKeysoruseSortedSelectionSetas an editor source action no longer corrupts nested objects or selection sets. -
#13056
98f4d53Thanks @ematipico! - Fixed #10607:noUndeclaredDependenciesno longer reports imports resolved through TypeScript'scompilerOptions.pathsmappings. -
#13033
7638393Thanks @GBra-4-669! - Fixed #12980: the CSS parser no longer panics on acomposesdeclaration whose value contains a non-identifier token, such ascomposes: 1px;. It reports a diagnostic instead. -
#12917
37d9f41Thanks @dyc3! - FixednoUnresolvedImports: it now reports default imports from modules that only forward exports withexport * from "...".export *never re-exports a default export, soimport foo from "./barrel.js"fails when./barrel.jscontains onlyexport * from "./foo.js". -
#12596
d33e56eThanks @dyc3! - FixednoUnreachableSuperignoring the default values of constructor parameters. Usingthisin a default value is now reported, because it runs beforesuper(), and callingsuper()in a default value is now recognized.class Child extends Parent { constructor(options = this.defaults()) { // reported super(options); } }
-
#12596
d33e56eThanks @dyc3! - FixednoUselessAssignmentignoring variables that are used in the iterated value of afor...oforfor...inloop, in the default values of a destructuring declaration or of parameters, or in the body of an arrow function written as a single expression. These variables are now checked too.function process(first, second) { let list = first; // reported: this value is never read list = second; for (const item of list) { handle(item); } }
-
#12805
2468384Thanks @vibbix! - Fixed #12332:noUnknownUnitno longer reports hex colors that start with a digit in SCSS custom properties or in unquoted legacy IEfiltervalues. The rule now accepts--accent: #4566a8;instead of reporting the unknown unita8. -
#12549
7fdb28fThanks @pkallos! - Fixed #10464:useNullishCoalescingno longer reports a ternary orifstatement that checks onlynullor onlyundefinedwhen the type can also be the other, because??would change its behavior. -
#12952
d1896a0Thanks @arendjr! - Addedgrit()queries to JavaScript plugins. A rule can now use a GritQL pattern to select the nodes passed torun()instead of listing syntax kinds withast().For example:
export const noConsole = defineRule({ query: grit("`console.log($args)`"), run(element) { if (element.kind !== "JS_CALL_EXPRESSION") return; registerDiagnostic(element, "warning", "Unexpected console.log."); }, });
Usage of Grit patterns can be particularly useful when it would take several checks to verify the shape of a snippet that involves multiple AST nodes.
Grit sequence patterns call
run()for each matched node. Matching on leaf tokens is also supported for patterns, while patterns containing rewrites are rejected. Plugins using GritQL patterns should report diagnostics fromrun()as usual.Plugins using Grit queries can still request the semantic model as well:
export const rule = defineRule({ query: grit("function $fn($args) { $body }", { semantic: true }), run(node, { model }) { // You can use `model` here similar to a query specified using `ast(..., { semantic: true })`. }, });
-
#13022
81d0187Thanks @arendjr! - Fixed an issue where GritQL patterns wouldn't match snippets if they contain a trailing list separator.For example, the pattern
`a, b`wouldn't match the arguments infunction(a, b,), whereas now they do. -
#12999
ace98cfThanks @deepsingh132! - Fixed #12953: the Markdown formatter no longer removes the blank line between a blockquote that ends a list item and the block that follows it, matching Prettier. Removing that line could also move a following paragraph into the blockquote. The same applies to a list item that ends with a hard line break.- a > b + #### Heading -
#13067
45c8c4dThanks @ematipico! - Added the nursery rulenoDisabledAttribute, which warns when buttons and other form controls use the nativedisabledattribute. A disabled control can't be reached with the Tab key, so the rule suggestsaria-disabledorreadonlyinstead.<button disabled>Save</button> <input type="email" disabled />
-
#12923
0668c8fThanks @dyc3! - Added the new nursery rulenoScssNullComparison. It reports comparisons tonullin Sass@ifand@else ifconditions, becausenullalready counts as false in a condition.a { @if $value == null {} }
-
#12955
e1ef913Thanks @ematipico! - Fixed an issue where Biome could silently skip configured plugins. Biome now reports an error when those plugins are unavailable during analysis. -
#12997
419aa5dThanks @Riccardo-bit-cpu! - Fixed #12475:noSwitchDeclarationsno longer reportsvardeclarations insideswitchclauses, matching ESLint'sno-case-declarations. -
#12867
6a25d72Thanks @dyc3! - Added the nursery rulenoUselessQualifier, which reports namespace and enum names that are repeated before a member inside that same namespace or enum. Biome provides a fix that removes the repeated name.namespace Shapes { export type Point = { x: number; y: number }; const origin: Shapes.Point = { x: 0, y: 0 }; }
-
#12050
60f4695Thanks @dor-sr! - Fixed #11933:useUnicodeRegexno longer offers to add theuflag to patterns that become invalid or change meaning in Unicode mode, such as/{/,/\-/or/[\d-z]/. The rule still reports them. -
#13035
478e056Thanks @dyc3! - Fixed #13026: the Markdown formatter no longer indents the rows of a table inside a blockquote when the table follows a paragraph of two or more lines. Previously, every run of the formatter indented the rows further until they were joined onto the header line.> First line of a paragraph, > second line of it. > > | A | B | - > | --- | --- | - > | x | y | + > | --- | --- | + > | x | y |
-
#13066
f6cf28eThanks @arendjr! - Removed thesemantic()query function from the JavaScript plugin API. Pass{ semantic: true }toast()instead to provide the semantic model to a rule.export const rule = defineRule({ query: semantic("JS_REFERENCE_IDENTIFIER"), run(node, { model }) { // Use `model` here. }, });
Becomes:
export const rule = defineRule({ query: ast("JS_REFERENCE_IDENTIFIER", { semantic: true }), run(node, { model }) { // Use `model` here. }, });
This behaviour matches the
grit()query function, which also accepts the{ semantic: true }option. -
#12951
014b976Thanks @ematipico! - Fixed #10782:noUndeclaredClassesno longer appears to hang on projects with long component import chains. -
#13073
827e610Thanks @vibbix! - Fixed #13072: a comment before a SCSS map entry whose value is a parenthesized group no longer indents that group one level too deep. This matches Prettier 3.10 behavior now.$map: ( /* comment */ key: ( - a: 1, - b: 2, - ), + a: 1, + b: 2, + ), ); -
#12928
ae0e186Thanks @dyc3! - ImprovednoUselessStringConcat. The rule now reports literals joined after another value, such asfoo + "a" + "b", and fixes template literals with placeholders, so`Hello, ${name}` + "!"becomes`Hello, ${name}!`.The rule no longer reports strings that would join into text that looks like a placeholder, such as
"$" + "{name}", or into a directive such as"use strict". It also no longer reportsobj.foo * "a" + "b", which its fix used to change toobj.foo * "ab".The fix no longer changes the value of the string in two cases. It used to change
1 + 2 + "b" + "c"to"12bc"instead of1 + 2 + "bc". It used to change"\1" + "2"to"\12", which is a different escape sequence.The fix no longer joins literals that are on different lines when the concatenation ends with two literals on the same line. It also no longer puts a line break from a template literal into a string literal, which made the code invalid.
-
#13048
24734a8Thanks @ematipico! - Fixed #13028: Biome now keeps a paragraph in its outer block quote when a quote-only blank line closes a nested block quote.> > b > -> > c +> c
-
#12967
bd0988eThanks @siketyan! - Fixed #12827:noDuplicateProperties,noDuplicateCustomProperties, andnoMissingVarFunctionnow check declarations at the top level of embedded CSS templates, such asstyled.div`...`. -
#13048
24734a8Thanks @ematipico! - Fixed #13029: the Markdown formatter now normalizes spaces inside inline and reference link text without removing whitespace-only text.-something [ text ]( destination) -something [ ]( destination) +something [ text ](destination) +something [ ](destination)
-
#13021
05a1409Thanks @dyc3! - Fixed #12993: Svelte{@const}tags with TypeScript type annotations, such as{@const doubled: number = item * 2}, now parse and format in components with<script lang="ts">. -
#12968
ec0142bThanks @siketyan! - Fixed #12826: Biome now detects CSS in styled-components templates that use.attrs(), such asstyled.button.attrs({ type: "button" })`...`andstyled(Component).attrs(() => ({}))`...`, so they are formatted and linted likestyled.button`...`. -
#13048
24734a8Thanks @ematipico! - Fixed #13027: the Markdown formatter now preserves spaces around text after a code span that crosses block quote lines.> `a -> b`c`d` +> b` c `d`
-
#13055
78c744aThanks @ematipico! - Fixed #13053: Biome now reports missing CLI paths as file-system errors without theINTERNALtag or advice that the path was ignored by configuration. File-system diagnostics now use specificfs/*categories, with underlying I/O errors categorized asfs/io. -
#12927
c6feec1Thanks @dyc3! - Added the nursery ruleuseCatchErrorName, which requires a specific name for caught errors intry...catchstatements and in the error handlers ofpromise.catch()andpromise.then(). The name defaults toerrorand can be changed with thenameoption.try {} catch (err) {} // `err` should be named `error`
-
#12788
7f971edThanks @dyc3! - ExtendeduseWhileto reportfor (;;)loops and to fix them towhile (true). -
#12967
bd0988eThanks @siketyan! - FixednoMissingVarFunctionso it also checks declarations inside at-rules such as@pageand@font-face. For example,@page { margin: --page-margin; }is now reported when--page-marginis declared in:root. -
#13057
d9267a5Thanks @ematipico! - Fixed #10896 so Svelte<script generics>attributes containing object type constraints parse and format as TypeScript type parameters. -
#13048
24734a8Thanks @ematipico! - Fixed #13038: Biome now aligns wrapped task-list paragraphs with the text following the checkbox.- [ ] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc varius - malesuada eros, faucibus dapibus odio rhoncus in. + malesuada eros, faucibus dapibus odio rhoncus in.
What's Changed
- chore: remove graphite from sponsors by @dyc3 in #12988
- fix(graph): memoize upward traversal by @ematipico in #12951
- fix(plugins): emit error on missing plugin by @ematipico in #12955
- fix(lint/useUnicodeRegex): don't add the u flag to patterns invalid in unicode mode by @dor-sr in #12050
- fix(lint/css): resolve root declarations in embedded snippets by @siketyan in #12967
- feat(embeds/css): parse
styled.a.attrs()as embedded CSS snippets by @siketyan in #12968 - feat: support GritQL queries in JS plugins by @arendjr in #12952
- fix(lint): don't report
varinnoSwitchDeclarationsby @Riccardo-bit-cpu in #12997 - fix(svelte): parse type annotations in const tags by @dyc3 in #13021
- fix(grit): allow matching trailing list separator by @arendjr in #13022
- feat(lint): add NoReactDirectStateMutation by @jelly in #13034
- fix(useWhile): detect and fix infinite for loops by @dyc3 in #12788
- docs: remove duplicated word in HTML formatter debug comment by @ninglinLiu in #13039
- feat(lint): add noSvelteAsyncStore by @dyc3 in #12810
- feat(lint): add noUselessParameterPropertyAssignment by @dyc3 in #12785
- feat(lint): add noUselessQualifier by @dyc3 in #12867
- feat(lint): add useGlobalRegexInReplaceAll by @dyc3 in #12891
- feat(lint): add noUselessFallbackInSpread by @dyc3 in #12892
- feat(lint): add useValidCharacterComparison by @dyc3 in #12896
- feat(lint): add noExcessiveSelectorComplexity by @dyc3 in #12899
- feat(lint): add useGlobalRegexInMatchAll by @dyc3 in #12925
- feat(lint): add noScssNullComparison by @dyc3 in #12923
- feat(lint): add noUnresolvedDefaultImport by @dyc3 in #12917
- feat(lint): add useConsistentTupleLabels by @dyc3 in #12922
- feat(lint): add useConsistentFontWeightNotation by @dyc3 in #12905
- feat(lint): add noAsyncPromiseFinally by @dyc3 in #12906
- feat(lint): add noUselessSpread by @dyc3 in #12900
- feat(lint): add useConsistentBooleanName by @dyc3 in #12901
- feat(lint): add noInvalidFetchOptions by @dyc3 in #12897
- feat(lint): add noVueExposeAfterAwait by @dyc3 in #12902
- feat(lint): add noNewArray by @dyc3 in #12926
- feat(lint): add useCatchErrorName by @dyc3 in #12927
- feat(lint): add noRedundantTypeConstituents by @dyc3 in #12895
- feat(lint): add noDuplicateTypeConstituents by @dyc3 in #12894
- feat(lint): expand noUselessStringConcat by @dyc3 in #12928
- feat(lint): add useAtomicUpdates and some fixes in the control flow graph by @dyc3 in #12596
- fix(css): sort consecutive property groups independently by @latin-1 in #12621
- chore(deps): update rust crate jiff to 0.2.41 by @renovate[bot] in #13040
- chore(deps): update rust crate smallvec to 1.16.5 by @renovate[bot] in #13043
- chore(deps): update rust crate notify to 8.2.2 by @renovate[bot] in #13042
- fix(markdown_formatter): keep blank line after a blockquote ending a list item by @deepsingh132 in #12999
- fix(css_parser): don't panic on non-identifier composes value by @GBra-4-669 in #13033
- feat(rowan): port upstream navigation APIs by @ematipico in #13050
- refactor: adopt Rowan navigation APIs by @ematipico in #13051
- refactor(vue): allow easier lookup of syntax nodes from vue semantic model objects by @dyc3 in #12916
- chore(deps): update rust to v1.99.1 by @renovate[bot] in #13047
- fix(md/fmt): various bugs by @ematipico in #13048
- fix(format/md): keep table rows in blockquotes aligned by @dyc3 in #13035
- fix(cli): os error by @ematipico in #13055
- fix(core): parse and visit generics by @ematipico in #13057
- fix(analyzer): skip subtree for sort rules by @ematipico in #13065
- feat(lint):
noDisabledButtonrule by @ematipico in #13067 - fix(lint/css): add fixed SCSS map comment indentation by @vibbix in #13073
- chore: remove semantic() query function from JS plugin API by @arendjr in #13066
- fix(lint): don't report partial nullish checks in useNullishCoalescing by @pkallos in #12549
- fix(parse/astro): html comments in expressions by @ematipico in #13085
- chore(deps): fix advisories by @dyc3 in #13090
- fix(css_parser): lex digit-led hash names in raw custom property values by @vibbix in #12805
- fix(noUndeclaredDependencies): typescript paths by @ematipico in #13056
- feat(lint): cover all form controls in noDisabledAttribute by @dyc3 in #13096
- ci: release by @github-actions[bot] in #12989
New Contributors
- @dor-sr made their first contribution in #12050
- @Riccardo-bit-cpu made their first contribution in #12997
- @ninglinLiu made their first contribution in #13039
- @deepsingh132 made their first contribution in #12999
- @GBra-4-669 made their first contribution in #13033
Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.6.6...@biomejs/biome@2.6.7