2.6.3
Patch Changes
-
#12275
807e616Thanks @dyc3! - Added the new nursery rulenoArraySortForMinMax, which reports sorting an array only to read its smallest or largest value. UseMath.min()orMath.max()instead.const minimum = array.toSorted((a, b) => a - b)[0];
-
#12432
cf61682Thanks @dyc3! - Added the nursery rulenoBooleanSortComparator, which reports sort comparators that return a boolean instead of a number. For example,array.sort((a, b) => a > b)never puts the first item before the second, so the array isn't sorted correctly. -
#12304
b4654c5Thanks @dyc3! - Added the new nursery rulenoEagerArrayMethodsInLoops, which reports.map()and.filter()calls in the header offor...ofloops. These calls build a new array that is only used by the loop.for (const name of users.map((user) => user.name)) { console.log(name); }
-
#12121
66c3791Thanks @dyc3! - Added the nursery rulenoNewRequire, which disallows callingrequirewithnew, such asnew require("app-header"). -
#12316
34b520dThanks @dyc3! - Added the new nursery rulenoObsoleteAttributes, which disallows obsolete attributes on HTML elements and suggests what to use instead.<table bgcolor="#ffffff" cellpadding="5"></table>
-
#12258
cce2385Thanks @dyc3! - Added the nursery rulenoPathConcat, which disallows building file paths and URLs by joining strings to__dirname,__filename,import.meta.dirname,import.meta.filename, orimport.meta.url.const fullPath = __dirname + "/foo.js"; // reported
-
#12287
e12ad78Thanks @dyc3! - Added the new nursery rulenoPlaywrightNthMethods, which disallows selecting Playwright elements by position withfirst(),last(), andnth(). A test that relies on the position of an element can act on a different element when the page changes.await page.locator("button").first().click();
-
#12343
62ad123Thanks @vibbix! - Added the nursery rulenoSelfNestedLayer, which disallows nesting a cascade layer inside a layer with the same name. Layer names inside an@layerblock are relative to it, so the inner layer below creates the sublayercomponents.componentsinstead of adding tocomponents.@layer components { @layer components { .button { color: red; } } }
-
#12289
bbbd95dThanks @dyc3! - Added the nursery rulenoShortTimeValues, which reports CSS animation and transition times that are shorter than the configuredminimumnumber of milliseconds. The rule does nothing untilminimumis set.For example, the following code is invalid when
minimumis100:a { transition-duration: 80ms; }
-
#12431
f748ec0Thanks @dyc3! - Added the nursery rulenoSvelteInternal, which disallows importing fromsvelte/internaland its submodules. These modules are private to Svelte and can change or disappear in any release.import { get_current_component } from "svelte/internal";
-
#12270
8ae35c4Thanks @dyc3! - Added the nursery rulenoTanstackQueryRestDestructuring, which disallows rest destructuring and object spread on TanStack Query results. Both read every property of the result, so the component updates on every change to the query.import { useQuery } from "@tanstack/react-query"; const { data, ...rest } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
The rule belongs to the new
tanstackQuerydomain. -
#12308
372af2aThanks @dyc3! - Added the new nursery rulenoUnreadableForOfExpression, which reportsfor...ofandfor await...ofloops that go through the result of a complex expression instead of a variable, a property, or a short call.for (const item of getItems(createArgument(seed))) {} // reported
-
#12422
0be8d10Thanks @dyc3! - Added the new nursery rulenoUnsafeReturn, which disallows returning a value typed asanyfrom a function.function parse(text: string) { return JSON.parse(text); // reported }
-
#12311
8434c92Thanks @dyc3! - Added the nursery rulenoUselessSplice, which reportssplice()calls that have a simpler alternative. For example,array.splice(0, 1)can be written asarray.shift(). -
#12293
eaa4a2bThanks @dyc3! - Added the nursery rulenoVueUnusedEmitDeclarations, which reports events that a Vue component declares but never emits.For example, the following component never emits
close:<script setup> const emit = defineEmits(["change", "close"]); emit("change"); </script>
-
#12386
f01ebb0Thanks @dyc3! - Added the nursery rulenoVueVTextVHtmlOnComponent, which disallowsv-textandv-htmlon Vue components. These directives replace everything inside the component's root element instead of filling its slot.<template> <MyComponent v-html="html"></MyComponent> </template>
-
#12385
7bd38b7Thanks @dyc3! - Added the new nursery rulenoVueWatchAfterAwait, which disallows creating watchers after anawaitin a Vue component'ssetup()function. Vue doesn't stop these watchers when the component is removed. A watcher is allowed when the function it returns is stored, so that function can be called later to stop the watcher.<script> import { watch } from "vue"; export default { async setup() { await fetchUser(); watch(source, () => {}); }, }; </script>
-
#12286
50d2a4eThanks @dyc3! - Added the nursery rulenoZeroLengthUnit, which disallows units on zero lengths in CSS. Biome can remove the unit.a { top: 0px; }
-
#12300
ab2eb9eThanks @dyc3! - Added the nursery ruleuseBlockStatementOverIife, which reports functions that are called immediately when a block statement can replace them. Biome can replace these functions with a block statement.Invalid:
(() => { const value = getValue(); run(value); })();
-
#12421
1c2cac0Thanks @dyc3! - Added the nursery ruleuseConsistentLightnessNotation, which enforces writing the lightness oflab(),lch(),oklab(), andoklch()colors as a percentage, or as a number with thenotationoption. For example, with the default options,oklch(0.85 0.17 88)is reported and can be fixed tooklch(85% 0.17 88). -
#12224
fef7ed4Thanks @dyc3! - Added the nursery ruleuseExpectToContain, which reports tests that compare the result ofincludes()to a boolean, and suggests usingtoContain()instead.expect(fruits.includes("apple")).toBe(true);
-
#12299
0d5025dThanks @dyc3! - Added the new nursery ruleuseIteratorZip, which reportsforloops that use an index only to read the same position from several arrays. Such loops can useIterator.zip()instead.// reported for (let index = 0; index < Math.min(names.length, scores.length); index++) { save(names[index], scores[index]); }
-
#12298
a234d2fThanks @dyc3! - Added the nursery ruleuseMathAbs, which reports manual absolute value calculations and range checks that can useMath.abs(). For example,value < 0 ? -value : valuecan be written asMath.abs(value), andvalue > limit || value < -limitcan be written asMath.abs(value) > limit. -
#12499
bd024ccThanks @dyc3! - Added the nursery ruleuseMathTrunc, which requiresMath.trunc()instead of bitwise operations orparseInt(String(x), 10)for removing the decimal part of a number. For example,const result = value | 0;andconst result = ~~value;are now reported. -
#12314
9e875a4Thanks @dyc3! - Added the new nursery ruleusePackageJsonValidCpu, which reports acpufield inpackage.jsonthat isn't an array of known processor types. Thecpufield lists the processor types that the package supports.For example, the rule reports the following
package.jsonfile becausex86isn't a processor type that package managers recognize:{ "name": "my-package", "cpu": ["x86"] } -
#12315
cb30544Thanks @dyc3! - Added the nursery ruleusePackageJsonValidEngines, which reports an invalidenginesfield inpackage.json. The field must be an object, and each of its values must be a non-empty string.For example, the following
enginesfield is reported because the version ofnodeis a number:{ "engines": { "node": 24 } } -
#12400
407604dThanks @dyc3! - Added the nursery ruleuseVueComponentIs, which requires Vue<component>elements to bind theisattribute with:isorv-bind:is. Without it, Vue has no component to render.<template> <component :is="currentView" /> </template>
-
#12337
c371520Thanks @dyc3! - Added the nursery ruleuseVueToggleInsideTransition, which requires the element inside a Vue<Transition>to be shown and hidden withv-iforv-show. Without one of them, the element is always shown and the transition never plays.<template> <Transition> <div>Content</div> </Transition> </template>
-
#12387
64472e9Thanks @dyc3! - Added the nursery ruleuseVueTypedRef, which reportsref()andshallowRef()calls in TypeScript that have no type argument and no initial value other thannullorundefined. Without a type, TypeScript can't tell which values these refs are meant to hold.import { ref } from "vue"; const count = ref();
-
#12423
bf1a55aThanks @dyc3! - Added the nursery ruleuseVueVOnExact, which requires the.exactmodifier on av-onlistener when another listener for the same event on the element needs more modifier keys, such as.ctrl. Without.exact, both listeners run when those keys are held down. The rule accepts the following code:<template> <button @click.exact="select" @click.ctrl="open"></button> </template>
-
#12418
208730eThanks @latin-1! - Fixed #12417:useSortedPropertiescould produce invalid CSS when sorting properties without a final semicolon. Comments attached to reordered properties are preserved. -
#12216
f2a3c71Thanks @dyc3! - Added the new nursery rulenoDanglingUnderscore, which disallows variable names, function names, and property accesses that start or end with an underscore.const _count = 0; // reported user._id; // reported
-
#12536
438997fThanks @vidigoat! - Fixed the formatter removing the parentheses around an instantiation expression before+,-,<,>,>=,>>and>>>. TypeScript readsmake<T> + yasmake < T > +y, andmake<T> >> ydoesn't parse.- x = make<T> + y; + x = (make<T>) + y; - x = make<T> >> y; + x = (make<T>) >> y;
-
#12540
7d3e8a1Thanks @vidigoat! - Fixed the formatter removing the parentheses around an instantiation expression before a non-null assertion or type arguments of a class heritage, which produced code that doesn't parse.- const a = make<T>!; + const a = (make<T>)!; - class D extends B<T><T> {} + class D extends (B<T>)<T> {}
-
#12496
09d89b9Thanks @vidigoat! - Fixed the formatter removing the parentheses around binary, logical, type-cast and instantiation operands of an instantiation expression. The type arguments then applied to the last operand only, and a nested instantiation expression didn't parse.- const x = a + b<T>; + const x = (a + b)<T>; - const y = a as B<T>; + const y = (a as B)<T>; - const z = f<A><B>; + const z = (f<A>)<B>;
-
#12526
dbcdab1Thanks @dyc3! - Fixed #12524: the Markdown formatter no longer removes the blank line between a paragraph and the list that follows it. Removing it could change the document, because an ordered list that doesn't start at1can't interrupt a paragraph and became part of the paragraph text.Steps: 3. three 4. four
-
#12509
470018bThanks @dyc3! - Fixed #12507: the Markdown formatter no longer drops the>markers after an empty quote line whenproseWrapis"always"or"never". Previously, the text after the empty line was moved out of the blockquote.> a > - b + > b
-
#12598
5699601Thanks @vidigoat! - Fixed the formatter removing the parentheses around the callee of anewexpression when it contains a dynamicimport()call, which produced code that doesn't parse.- new import("foo").bar(); + new (import("foo").bar)();
-
#12508
87d9e6bThanks @dyc3! - Fixed #12502:noInvalidGridAreasnow counts the cells in each row ofgrid-template-areasinstead of comparing the length of the row text. Rows such as"a" "bb"are no longer reported, and rows such as"abc" "d e"are now reported. -
#12530
7f467b2Thanks @dyc3! - Fixed #12529:noUselessElseno longer reports anelseclause when theifblock ends with aswitchstatement that has nodefaultclause. If no case matches, such aswitchdoesn't exit, so theelseclause is needed. -
#12511
d4ea663Thanks @dyc3! - Fixed #12505:useDomNodeTextContentno longer reportsinnerTexton values whose type annotation shows they aren't DOM nodes. The following code is now valid:const Link = ({ innerText }: { innerText: string }) => <a>{innerText}</a>;
-
#12588
e262362Thanks @ematipico! - FixednoDescendingSpecificityto compare resolved nested selector targets. Biome no longer reports nested selectors that resolve to different targets, detects equivalent explicit and nested targets, and emits one diagnostic when a parent selector list expands the same nested selector multiple times.For example, the following selectors are no longer reported because their final targets are
.columnandcode, respectively:.card { .column { :root[data-theme="dark"] & {} } code { :root[data-theme="dark"] & {} } }
-
#12534
e59a324Thanks @Netail! - Improved the diagnostics ofnoIdenticalTestTitle. Biome now reports one diagnostic per repeated title, pointing at the first occurrence and at every later occurrence, instead of one diagnostic per duplicate. -
#12528
a3132dcThanks @ff1451! - Fixed #12503:noUnknownPropertynow checks SCSS nested properties by the name Sass emits for them. For example,radiusinborder: { radius: 4px; }is checked asborder-radiusand is no longer reported, whilecolorinfont: { color: red; }is checked asfont-colorand is now reported. -
#12113
ec4eb2dThanks @dyc3! - Added the nursery ruleuseConsistentUnicodeBom, which disallows a leading Unicode byte order mark by default and can require one withbom: "always". The rule supports JavaScript, TypeScript, JSON, CSS, GraphQL, HTML, and Markdown, provides a fix, and preserves theunicode-bomoption during ESLint migration.The following example is invalid by default because it starts with an invisible U+FEFF character:
const value = 1;
-
#12248
afbc81eThanks @dyc3! - Added the nursery ruleuseReactNativeValidPlatformColors, which requiresPlatformColor()andDynamicColorIOS()calls to use values written directly in the call, so React Native can optimize them.import { PlatformColor } from "react-native"; const labelColor = "labelColor"; const color = PlatformColor(labelColor);
-
#12599
b62494aThanks @dyc3! - Fixed #12532: checking the project root no longer appliesfiles.includesexclusions to directories above the project. -
#12578
6162922Thanks @ematipico! - Fixed GraphQL parsing and formatting for executable descriptions and legacy fragment variables. Biome now formats inputs such as"Description" query { field }without panicking and removes insignificant commas consistently. -
#12593
35c69adThanks @dyc3! - Fixed #12555: the default reporter now prints the command summary, the--max-diagnosticswarning, and the skipped-fixes notice to stderr instead of stdout. Diagnostics already go to stderr, so the summary can no longer get mixed into the middle of a diagnostic when a tool reads the two streams separately. -
#12415
9520907Thanks @latin-1! - Fixed #12412:useSortedPropertiesnow sorts properties inside@keyframesanimations in CSS and SCSS.
What's Changed
- docs: changelog fixes due to broken release by @ematipico in #12497
- feat(lint): add useIteratorZip by @dyc3 in #12299
- feat(lint): add noUselessSplice by @dyc3 in #12311
- feat(lint): add noEagerArrayMethodsInLoops by @dyc3 in #12304
- feat(lint): add useVueTypedRef by @dyc3 in #12387
- feat(lint): add noDanglingUnderscore by @dyc3 in #12216
- feat(lint): add useConsistentUnicodeBom (all languages) by @dyc3 in #12113
- fix(format/js): keep parens around looser operands of instantiation expressions by @vidigoat in #12496
- refactor(vue): add Vue Semantic Model by @dyc3 in #12260
- feat(lint): add useMathAbs by @dyc3 in #12298
- feat(lint): add noShortTimeValues by @dyc3 in #12289
- feat(lint): add noPlaywrightNthMethods by @dyc3 in #12287
- feat(lint): add useMathTrunc by @dyc3 in #12499
- feat(lint): add useReactNativeValidPlatformColors by @dyc3 in #12248
- feat(lint): add useExpectToContain by @dyc3 in #12224
- feat(lint): add noTanstackQueryRestDestructuring and add TanstackQuery domain by @dyc3 in #12270
- feat(lint): add noZeroLengthUnit by @dyc3 in #12286
- feat(lint): add noVueUnusedEmitDeclarations by @dyc3 in #12293
- docs(skills): update skills to point agents to new optimized apis by @dyc3 in #12510
- feat(lint): add noPathConcat by @dyc3 in #12258
- feat(lint): add noNewRequire by @dyc3 in #12121
- feat(html_analyze): expose the Vue semantic model to HTML rules by @dyc3 in #12520
- feat(lint): add noBooleanSortComparator by @dyc3 in #12432
- feat(lint): add usePackageJsonValidCpu by @dyc3 in #12314
- feat(lint): add noObsoleteAttributes by @dyc3 in #12316
- feat(lint): add usePackageJsonValidEngines by @dyc3 in #12315
- feat(lint): add noVueVTextVHtmlOnComponent by @dyc3 in #12386
- feat(lint): add useConsistentLightnessNotation by @dyc3 in #12421
- fix(md/fmt): keep blank line between a paragraph and a following list by @dyc3 in #12526
- fix(format/md): keep quote markers after empty quote lines by @dyc3 in #12509
- fix(css): preserve semicolons and line comments when sorting properties by @latin-1 in #12418
- fix(noUselessElse): don't treat switch without default as breaking early by @dyc3 in #12530
- fix(lint): check SCSS nested properties by their emitted name in noUnknownProperty by @ff1451 in #12528
- fix(lint/noInvalidGridAreas): count cells instead of row text length by @dyc3 in #12508
- feat(lint): add noUnreadableForOfExpression by @dyc3 in #12308
- feat: improve noIdenticalTestTitle diagnostics by @Netail in #12534
- feat(lint): add noSelfNestedLayer by @vibbix in #12343
- fix(format/js): keep parens around an instantiation expression before
+,-,<and>by @vidigoat in #12536 - feat(lint): add noUnsafeReturn by @dyc3 in #12422
- fix(css): sort properties inside keyframe steps by @latin-1 in #12415
- fix(format/js): keep parens around an instantiation expression before
!and heritage type arguments by @vidigoat in #12540 - feat(eslint): allow migration of react/self-closing-comp by @jelly in #12539
- chore: update rule metadata by @dyc3 in #12565
- chore: add syntaxfm to sponsors by @ematipico in #12577
- fix(migrate):
useLogicalPropertiesby @jelly in #12538 - refactor(fmt): make embedding generic by @ematipico in #12579
- fix(graphql): parsing and formatting by @ematipico in #12578
- feat: allow migration of react/no-render-return-value by @jelly in #12556
- feat(lint): add useVueToggleInsideTransition by @dyc3 in #12337
- fix(useDomNodeTextContent): look at type annotations to avoid likely false positives by @dyc3 in #12511
- docs(useTailwindSortedClasses): update docs by @dyc3 in #12584
- refactor(fmt): make crate generic by @ematipico in #12585
- fix(cli): print summary and max diagnostics warning to stderr instead of stdout by @dyc3 in #12593
- fix(noDescendingSpecificity): resolve tail selectors by @ematipico in #12588
- perf: refactor a bunch preorder() calls to use preorder_of_kinds() instead by @dyc3 in #12594
- fix(files): stop exclusion checks above the project root by @dyc3 in #12599
- fix(format/js): wrap a new callee containing an import call in parens by @vidigoat in #12598
- feat(lint): add useVueVOnExact by @dyc3 in #12423
- feat(lint): add useBlockStatementOverIife by @dyc3 in #12300
- perf(rowan): refactor grand_parent() to not allocate a red node for parent by @dyc3 in #12618
- feat(lint): add noSvelteInternal by @dyc3 in #12431
- feat(lint): add useVueComponentIs by @dyc3 in #12400
- feat(lint): add noArraySortForMinMax by @dyc3 in #12275
- feat(lint): add noVueWatchAfterAwait by @dyc3 in #12385
- ci: release by @github-actions[bot] in #12500
New Contributors
Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.6.2...@biomejs/biome@2.6.3