2.6.5
Patch Changes
-
#12755
bbc4887Thanks @dyc3! - Added the new nursery rulenoArrayForEach, which reportsforEach()calls that can be written asfor...ofloops. Values known not to be arrays, such as aMapor aSet, are ignored.array.forEach((element) => { bar(element); });
-
#12777
ba692e4Thanks @dyc3! - Added the new nursery rulenoAwaitInPromiseMethods, which reportsawaitinside the array passed toPromise.all(),Promise.allSettled(),Promise.any(), orPromise.race(). Theawaitpauses the code before the method is called, so the promises no longer run at the same time.Promise.all([await promise, anotherPromise]);
-
#12765
af84fb4Thanks @dyc3! - Added the new nursery rulenoChainedComparison, which reports comparisons chained likea < b < cora === b === c. JavaScript comparesawithbfirst, and then compares the resultingtrueorfalsewithc, so3 > 2 > 1isfalse.if (a < b < c) {}
-
#12547
0a2073dThanks @dyc3! - Added the nursery rulenoDynamicDelete, which disallows usingdeletewith a property name that is computed at runtime. Fixed property names written as string or number literals are allowed.delete container[name];
-
#12481
ed7adc2Thanks @dyc3! - Added the nursery rulenoLateEventControl, which reports calls topreventDefault(),stopPropagation(), andstopImmediatePropagation()that run after the browser has finished handling the event, where they have no effect.element.addEventListener("click", async (event) => { await save(); event.preventDefault(); });
-
#12795
179666dThanks @dyc3! - Added the nursery rulenoMapSpread, which disallows spreading objects or arrays in the values returned bymap()andflatMap()callbacks. Each spread copies a whole object or array for every item, which is slow for large arrays. Its unsafe fix replaces an object that starts with a spread withObject.assign().const users = getUsers(); const rows = users.map((user) => ({ ...user, role: getRole(user) }));
-
#12793
d9a99fdThanks @dyc3! - Added the nursery rulenoMismatchedMapKey, which reportsget()andset()calls that use a different key than thehas()check before them. Checking one key and then using another is usually a copy-paste mistake.if (map.has(key)) { map.get(otherKey); // reported }
-
#12342
1db7c0dThanks @vibbix! - Added the nursery rulenoMissingScssInterpolation, which disallows Sass variables and function calls in custom property values without#{}interpolation. Sass copies these values into the CSS unchanged, so the browser receives$gapormath.div(8px, 2)instead of their results. Its unsafe fix wraps variables in#{}.:root { --gap: $gap; --half: math.div(8px, 2); }
-
#12792
de86b37Thanks @dyc3! - Added the nursery rulenoMissingThrow, which reports errors that are created withnewbut never thrown. Its unsafe fix adds the missingthrowkeyword.function check(value) { if (!value) { new Error("Missing value"); } }
-
#12790
c23e4c3Thanks @dyc3! - Added the new nursery rulenoObjectLiteralComparison, which reports comparisons with an empty object{}or an empty array[]. These comparisons never check whether a value is empty, because objects and arrays are compared by reference.if (value === {}) {}
-
#12450
793f07dThanks @dyc3! - Added the new nursery rulenoPlaywrightUnsafeReferences, which reports functions passed topage.evaluate()orpage.addInitScript()that use variables declared outside of them. Playwright runs these functions in the browser page, where those variables don't exist.const x = 7; await page.evaluate(() => x * 2); // reported: `x` must be passed as an argument
-
#12388
a0160a4Thanks @vibbix! - Added the nursery rulenoPseudoElementInFunctionalPseudoClass, which disallows pseudo-elements inside:is(),:where(),:not()and:has(). Browsers drop these selectors, so the styles never apply to the pseudo-element..card:is(::before, ::after) { content: ""; }
-
#12779
bc1befbThanks @dyc3! - Added the new nursery rulenoSinglePromiseInPromiseMethods, which reports an array with a single element passed toPromise.all(),Promise.any(), orPromise.race(). The rule offers a fix that awaits the value directly or usesPromise.resolve().const result = await Promise.all([promise]);
-
#12241
d96de1dThanks @dyc3! - Added the nursery rulenoSvelteBindValueOnCheckableInputs, which reportsbind:valueon checkbox and radio inputs in Svelte files. Users change whether these inputs are checked, not theirvalue, sobind:valuedoes not track their choice.<input type="checkbox" bind:value={accepted} />
-
#12764
e166d08Thanks @dyc3! - Added the new nursery rulenoSyncMethods, which reports calls to functions whose names end withSync, such asfs.readFileSync(). These calls block the program until they finish. TheallowAtRootLeveloption allows them outside of functions, and theignoreoption allows specific function names.const contents = fs.readFileSync("data.txt");
-
#12515
c0a4174Thanks @dyc3! - Added the nursery rulenoTanstackQueryVoidQueryFn, which disallows TanStack Query functions that don't return any data. TanStack Query doesn't acceptundefinedas the data of a query, so the query fails with an error.import { useQuery } from "@tanstack/react-query"; useQuery({ queryKey: ["todos"], queryFn: async () => { await fetch("/api/todos"); }, });
The rule belongs to the
tanstackQueryandtypesdomains. -
#12482
1e6e407Thanks @dyc3! - Added the nursery rulenoUnnecessaryStringTrim, which reportstrim()calls beforestartsWith()orendsWith()when only one side of the string matters. UsetrimStart()ortrimEnd()instead.value.trim().startsWith("-");
-
#12772
a108773Thanks @dyc3! - Added the nursery rulenoUselessAwait, which reportsawaiton values that are never promises, such as literals, arrays, and the results of comparisons.await [fetchUser(), fetchPosts()];
-
#12783
d0931b0Thanks @dyc3! - Added the new nursery rulenoUselessLengthCheck, which reports array length checks that don't change the result: a check that the array is empty next toevery(), a check that it isn't empty next tosome(), or a check that it isn't empty around afor...ofloop over the same array.if (array.length > 0 && array.some(Boolean)) {}
-
#12488
93e0e73Thanks @dyc3! - Added the new nursery rulenoUselessTypeAssertion, which reports type assertions that don't change the type of an expression, such as a non-null assertion on a value that can't benullorundefined.function double(value: number): number { return value! * 2; }
-
#12632
0e197b4Thanks @dyc3! - Added the nursery rulenoVueChildContent, which disallows content inside elements that usev-htmlorv-text. These directives replace the content of their element, so Vue discards anything written there.<template> <div v-html="html">Loading...</div> </template>
-
#12616
cb7b888Thanks @dyc3! - Added the new nursery rulenoVueDeprecatedConfigKeyCodes, which reports uses ofVue.config.keyCodes. Vue 3 removed this option, so custom key names defined with it no longer work.Vue.config.keyCodes = { f1: 112 };
-
#12568
59f3a42Thanks @dyc3! - Added the nursery rulenoVueDeprecatedDestroyedLifecycle, which reports thebeforeDestroyanddestroyedlifecycle hooks in Vue components. Vue 3 renamed them tobeforeUnmountandunmounted, and no longer calls hooks with the old names.<script> export default { destroyed() {}, }; </script>
-
#12654
bcb1e0fThanks @dyc3! - Added the nursery rulenoVueDeprecatedEventsApi, which reports calls to the$on,$off, and$onceinstance methods in Vue components. Vue 3 removed these methods, so calling them throws an error.<script> export default { mounted() { this.$on("start", handler); // reported }, }; </script>
-
#12590
b9872efThanks @dyc3! - Added the nursery rulenoVueDeprecatedFunctionalTemplate, which reports thefunctionalattribute on the<template>of a Vue component. Vue 3 no longer supports this attribute.<template functional> <div>{{ props.message }}</div> </template>
-
#12552
b71b705Thanks @dyc3! - Added the nursery rulenoVueDeprecatedHtmlElementIs, which disallows theisattribute on HTML elements in Vue templates. Vue 3 no longer renders a component in place of these elements, unless the value starts withvue:.<template> <tr is="my-row"></tr> </template>
-
#12553
4a613e1Thanks @dyc3! - Added the nursery rulenoVueDeprecatedInlineTemplate, which disallows theinline-templateattribute on Vue components. Vue 3 removed this feature, so the content between the component's tags is no longer used as its template.<template> <my-component inline-template> <div>{{ message }}</div> </my-component> </template>
-
#12617
0e9ca5bThanks @dyc3! - Added the nursery rulenoVueDeprecatedModelDefinition, which reports themodeloption in Vue components. Vue 3 ignores this option, sov-modelon the component always uses themodelValueprop and theupdate:modelValueevent.<script> export default { model: { prop: "checked", event: "change", }, }; </script>
-
#12604
e998921Thanks @dyc3! - Added the nursery rulenoVueDeprecatedPropsDefaultThis, which reportsthisinside the function that computes the default value of a Vue prop. Vue doesn't give this function access to the component, sothisdoesn't point to it. Read other props from the function's first argument instead.<script> export default { props: { size: Number, sizes: { type: Array, default() { return [this.size]; }, }, }, }; </script>
-
#12633
f65fe1eThanks @dyc3! - Added the nursery rulenoVueDeprecatedSlotAttribute, which reports theslotattribute in Vue templates. Vue 3 no longer uses this attribute to fill named slots, so usev-slot(or#) on a<template>element instead.<template> <MyComponent> <template slot="header">Title</template> </MyComponent> </template>
-
#12589
8ccb19aThanks @dyc3! - Added the new nursery rulenoVueDeprecatedVBindSync, which reports the.syncmodifier on Vuev-binddirectives. Vue 3 removed this modifier, so the rule suggestsv-modelwith the same argument instead.<MyComponent :title.sync="pageTitle" />
-
#12609
e1e102bThanks @dyc3! - Added the new nursery rulenoVueDeprecatedVOnNativeModifier, which disallows the.nativemodifier on Vue'sv-ondirective. Vue 3 removed this modifier.<MyComponent @click.native="onClick" />
-
#12667
de354e7Thanks @dyc3! - Added the new nursery rulenoVueExcessiveProps, which reports Vue components that declare more props than themaxPropsoption allows. The default limit is10.<!-- With "maxProps": 2 --> <script setup lang="ts"> defineProps<{ title: string; subtitle: string; icon: string }>(); // reported </script>
-
#12666
c3dc557Thanks @dyc3! - Added the nursery rulenoVueLoneTemplate, which reports<template>elements inside a Vue template that don't usev-if,v-else-if,v-else,v-for, orv-slot. Vue renders these as regular HTML<template>elements, so their content isn't shown.<template> <template> <p>Hello</p> </template> </template>
-
#12533
4b1089dThanks @dyc3! - Added the new nursery rulenoVueMixin, which reports themixinsoption in Vue components. In Vue 3, composables are the recommended way to share logic between components. The rule is recommended and part of thevuedomain.<script> export default { mixins: [counterMixin], }; </script>
-
#12658
807e358Thanks @dyc3! - Added the new nursery rulenoVueMultipleObjectsInClass, which reports:classarrays in Vue templates that contain more than one object. Merge the conditional classes into a single object instead.<template> <div :class="[{ active: isActive }, { disabled: isDisabled }]" /> </template>
-
#12564
78c1dd5Thanks @dyc3! - Added the nursery rulenoVueRefObjectReactivityLoss, which reports reads of a Vue ref's value that run only once, in the same function that creates the ref. Such a read copies the current value, and the copy doesn't update when the ref changes.import { ref } from "vue"; const count = ref(0); const doubled = count.value * 2;
-
#12517
5044c56Thanks @dyc3! - Added the nursery rulenoVueRestrictedCallAfterAwait, which reports calls to configured functions that come after anawaitin a Vue component'ssetup()function.For example, with
{ "functions": [{ "module": "vue-i18n", "path": "useI18n" }] }, the following call is reported:<script> import { useI18n } from "vue-i18n"; export default { async setup() { await fetchUser(); const { t } = useI18n(); return { t }; }, }; </script>
-
#12558
e898da4Thanks @dyc3! - Added the nursery rulenoVueRestrictedVOn, which reportsv-onevent listeners that are disallowed through thelistenersoption. An entry can match an event name, a set of modifiers, and an element. For example, with{ "listeners": [{ "event": "click", "element": "MyButton" }] },<MyButton @click="onClick" />is now reported. -
#12573
65c6b0bThanks @dyc3! - Added the new nursery rulenoVueTemplateKey, which disallows thekeyattribute on<template>elements in Vue files. Akeyon a<template>that also usesv-foris still allowed.<template> <template :key="item.id"><div /></template> </template>
-
#12629
2a34da1Thanks @dyc3! - Added the new nursery rulenoVueTemplateShadow, which disallowsv-forandv-slotvariables that hide a variable with the same name from an outer scope of a Vue template.<template> <div v-for="item in groups"> <span v-for="item in item.children">{{ item }}</span> </div> </template>
-
#12610
40de561Thanks @dyc3! - Added the new nursery rulenoVueTextareaMustache, which disallows{{ }}text interpolation inside a Vue<textarea>. Vue doesn't support it there; usev-modelinstead.<template> <textarea>{{ message }}</textarea> </template>
-
#12665
7742209Thanks @dyc3! - Added the new nursery rulenoVueThisInBeforeRouteEnter, which reportsthisin thebeforeRouteEnternavigation guard of a Vue component. Vue Router calls this guard before it creates the component, sothisisundefinedthere.<script> export default { beforeRouteEnter(to, from, next) { this.loadUser(to.params.id); // reported next(); }, }; </script>
-
#12620
70d7173Thanks @dyc3! - Added the nursery rulenoVueThisInTemplate, which reportsthisin Vue templates. Templates can read the properties of the component directly, sothis.textcan be written astext:<template> <p>{{ this.text }}</p> </template>
-
#12601
1d4ed92Thanks @dyc3! - Added the new nursery rulenoVueUndeclaredEmits, which reports events that a Vue component emits without declaring them in theemitsoption or indefineEmits().<script setup> const emit = defineEmits(["change"]); emit("close"); // reported: "close" is not declared </script>
-
#12583
4e870a8Thanks @dyc3! - Added the nursery rulenoVueUndeclaredProperties, which reports names that a Vue component uses but doesn't declare, in its template, inthis.name, and inprops.name.<script setup> const count = 0; </script> <template> <!-- `cnt` isn't declared --> <p>{{ cnt }}</p> </template>
-
#12657
b45fe79Thanks @dyc3! - Added the new nursery rulenoVueUndeclaredSlots, which reports<slot>elements in Vue components written in TypeScript when the slot isn't declared withdefineSlots()or with theslotsoption.<script setup lang="ts"> defineSlots<{ default(props: { msg: string }): any; }>(); </script> <template> <slot name="footer" /> <!-- reported --> </template>
-
#12789
041c800Thanks @dyc3! - Added the new nursery rulenoVueUselessTemplateAttributes, which reports attributes and directives that have no effect on a<template>element withv-if,v-else-if,v-else,v-for, orv-slotin Vue files. Vue renders only the content of such an element, so it ignores the other attributes.<template> <template v-if="visible" class="heading">Title</template> </template>
-
#12592
36531ccThanks @dyc3! - Added the nursery rulenoVueUselessVBind, which reportsv-binddirectives whose value is a fixed string. A plain attribute does the same thing.<template> <div :id="'foo'" /> <!-- reported, use id="foo" instead --> </template>
-
#12522
59838bbThanks @dyc3! - Added the nursery rulenoVueVForTemplateKeyOnChild, which reports akeyplaced on a child element of a<template v-for>instead of on the<template>tag.<template> <template v-for="todo in todos"> <TodoItem :key="todo.id" /> </template> </template>
-
#12516
2d9e57eThanks @dyc3! - Added the nursery ruleuseAccessorPairs. The rule reports setters that have no matching getter in object literals, classes, and property descriptors.const user = { set name(value) { this._name = value; }, };
-
#12756
1c6e3efThanks @dyc3! - Added the new nursery ruleuseObjectFromEntries, which reports code that builds an object from a list of key-value pairs withreduce(), afor...ofloop, or_.fromPairs()instead ofObject.fromEntries(). Thefunctionsoption adds other helper functions to report.const object = pairs.reduce((object, [key, value]) => ({ ...object, [key]: value }), {});
-
#12778
5432756Thanks @dyc3! - Added the new nursery ruleuseSetSize, which reports code that copies aSetinto an array only to read the array'slength, and suggests reading thesizeproperty of theSetinstead.const uniqueCount = [...new Set(userIds)].length;
-
#12302
b0d3390Thanks @dyc3! - Added the nursery ruleuseSvelteStoreInitialValue, which requireswritable(),readable(), andderived()stores fromsvelte/storeto be created with an initial value.import { writable } from "svelte/store"; export const count = writable();
-
#12290
c973fedThanks @dyc3! - Added the nursery ruleuseTailwindVariablesShorthandfor JavaScript and HTML. It reports Tailwind CSS classes that read a CSS variable with[var()], and fixes them to the shorthand that Tailwind CSS v4 added.<div className="bg-[var(--brand)]" />; // use `bg-(--brand)`
-
#12518
e9d9616Thanks @dyc3! - Added the nursery ruleuseTanstackQueryStableQueryClient, which reports a TanStack QueryQueryClientcreated inside a React component or custom hook. Such a client is created again on every render, and its cache starts empty each time.import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; function App() { const queryClient = new QueryClient(); return <QueryClientProvider client={queryClient}><Home /></QueryClientProvider>; }
-
#12650
0ddd08fThanks @dyc3! - Added the nursery ruleuseVueBlockOrder, which enforces the order of the top-level blocks in Vue components. By default,<script>and<template>blocks come first, in any order, followed by<style>blocks. The order can be changed with theorderoption.<style></style> <script></script>
-
#12715
7863f32Thanks @dyc3! - Added the nursery ruleuseVueBooleanPropTypeFirst, which requiresBooleanto come first in the list of types of a Vue prop. WhenStringcomes beforeBoolean, a prop written in a template without a value is set to an empty string instead oftrue.<script setup> defineProps({ disabled: [String, Boolean], }); </script>
-
#12563
91ac4cbThanks @dyc3! - Added the nursery ruleuseVueComputedPropertyReturn, which requires the getters of Vue computed properties to return a value on every path.<script setup> import { computed, ref } from "vue"; const count = ref(0); const double = computed(() => { count.value * 2; // reported: the getter never returns a value }); </script>
-
#12716
ae535eaThanks @dyc3! - Added the new nursery ruleuseVueConsistentBooleanPropStyle, which enforces a consistent style for Vue component props set totrue. By default, it requires the shorthand form; thestyleoption can require the longhand form instead.<template> <MyComponent :disabled="true" /> </template>
-
#12675
2a16d59Thanks @dyc3! - Added the new nursery ruleuseVueConsistentDefineEmitsDeclaration, which enforces one declaration style fordefineEmitsin<script setup lang="ts">. By default, events must be declared with a type. Thestyleoption can instead require each event to be a property of that type, such aschange: [id: number], or require an argument, such asdefineEmits(["change"]).<script setup lang="ts"> const emit = defineEmits(["change", "update"]); </script>
-
#12612
ab53e4fThanks @dyc3! - Added the nursery ruleuseVueConsistentPropNameCasing, which requires prop names in Vue components to use one casing style. By default, prop names must be in camelCase. Thecasingoption switches the rule to snake_case.<script setup> defineProps({ greeting_text: String, }); </script>
-
#12608
0928a75Thanks @dyc3! - Added the nursery ruleuseVueConsistentVForDelimiter, which requires the same word,inorof, between the item and the list in every Vuev-fordirective. The default isin, and thedelimiteroption switches it toof.<!-- reported by default --> <div v-for="item of items"></div>
-
#12611
d2df495Thanks @dyc3! - Added the nursery ruleuseVueConsistentVSlotStyle, which enforces one style for Vue slots:#name,v-slot:name, orv-slotfor the default slot. By default, it expectsv-sloton a component and#on<template>elements.<template> <MyComponent> <template v-slot:header>Title</template> </MyComponent> </template>
-
#12780
69467e0Thanks @dyc3! - Added the nursery ruleuseVueDefaultExport, which reports a<script>block of a Vue component that has no default export, when the file has no<script setup>block.<script> const foo = "foo"; </script>
-
#12655
8a576b4Thanks @dyc3! - Added the nursery ruleuseVueDefaultProp, which reports optional props of Vue components that have no default value. Props that only acceptBooleanare not reported.For example, the following component doesn't say what
sizeis when a parent component leaves it out:<script setup> defineProps({ size: Number, }); </script>
-
#12676
530000aThanks @dyc3! - Added the nursery ruleuseVueEmitValidator, which requires a validator function for each event declared in theemitsoption or indefineEmits().<script setup> // Reported: the event "change" has no validator function. defineEmits(["change"]); </script>
-
#12605
093c7caThanks @dyc3! - Added the new nursery ruleuseVueEmitsValidatorReturn, which reports Vue event validators that never return a true value. Vue prints a warning in development mode each time such an event is emitted.<script setup> defineEmits({ submit(payload) { payload.email.includes("@"); }, }); </script>
-
#12668
1690307Thanks @dyc3! - Added the new nursery ruleuseVueMacroVariableName, which requires specific variable names for the results ofdefineProps(),defineEmits(),defineSlots(),useSlots()anduseAttrs()in Vue<script setup>blocks. The names can be changed with the rule's options.<script setup> const propsDefined = defineProps({ msg: String }); // reported, should be `props` </script>
-
#12773
8f28e3fThanks @dyc3! - Added the nursery ruleuseVueOneComponentPerFile, which reports files that define more than one Vue component. The rule counts<script setup>blocks,export default { ... }in.vuefiles, anddefineComponent()andcreateApp()calls that define a component in place with an options object or a setup function. It doesn't report the main component of a.vuefile.<script setup> import { defineComponent, h } from "vue"; const Badge = defineComponent({ render: () => h("span", "New"), }); </script>
-
#12571
a357b2fThanks @dyc3! - Added the new nursery ruleuseVuePropTypeConstructor, which reports Vue prop types that aren't constructors, such as a type name written as a string.<script> export default { props: { size: 'Number', // reported, use `Number` instead }, }; </script>
-
#12566
e69572bThanks @dyc3! - Added the nursery ruleuseVueRenderReturn, which requires therenderfunction of a Vue component to return a value on every path.The following example is invalid because the
renderfunction returns nothing whenthis.visibleisfalse:<script> import { h } from "vue"; export default { render() { if (this.visible) { return h("div", "hello"); } }, }; </script>
-
#12619
3703a36Thanks @dyc3! - Added the nursery ruleuseVueSeparateStaticClass, which reports class names in a Vue:classbinding that always apply, such asheaderin<div :class="['header', theme]">. These classes belong in the plainclassattribute. -
#12677
f6b7f15Thanks @dyc3! - Added the nursery ruleuseVueSingleEventPayload, which reports Vue component events that are emitted or declared with more than one value. A listener written inline in a template, such as@change="onChange($event)", only receives the first value.<script setup> const emit = defineEmits(["change"]); emit("change", value, extra); </script>
-
#12646
3d92356Thanks @dyc3! - Added the new nursery ruleuseVueSlotNameCasing, which enforces a consistent casing for the names of<slot>elements in Vue templates. Slot names must be in camelCase by default. Thecasingoption can require kebab-case or a single lowercase word instead.<template> <slot name="foo-bar" /> </template>
-
#12572
cb16268Thanks @dyc3! - Added the nursery ruleuseVueSlotsAsFunctions, which reports slots inthis.$slotsthat are used as their content instead of being called. In Vue 3, each slot is a function that returns its content.export default { render() { return this.$slots.default.filter(isVisible); // reported }, };
-
#12659
e7691f7Thanks @Object,! - Added the new nursery ruleuseVueTypedObjectProps, which reports Vue props declared withObjectorArraywithout a TypeScript type in TypeScript files and Vue files with<script lang="ts">.<script setup lang="ts"> defineProps({ // reported items: Array as PropType<string[]>, }); </script>
-
#12574
bb8ca38Thanks @dyc3! - Added the nursery ruleuseVueValidAttributeName, which reports invalid attribute names in Vue templates, including names bound withv-bind. Attributes on components aren't checked.<template> <p 0abc :-def="value"></p> </template>
-
#12582
f6ac8ebThanks @dyc3! - Added the nursery ruleuseVueValidDefaultProp, which requires the default value of a Vue prop to match the type of the prop. Default objects and arrays must also be returned from a function, so that each component instance gets its own copy.<script> export default { props: { count: { type: Number, default: "zero" }, // reported items: { type: Array, default: [] }, // reported }, }; </script>
-
#12613
071324dThanks @dyc3! - Added the nursery ruleuseVueValidDefineOptions, which reports invalid calls to Vue'sdefineOptions()macro in<script setup>. It reports a call that is repeated, that has no options or has type arguments, that declaresprops,emits,expose, orslots, or that uses variables declared in<script setup>.<script setup> const options = { name: "Foo" }; defineOptions(options); </script>
-
#12557
f1eb303Thanks @dyc3! - Added the new nursery ruleuseVueValidNextTick, which reports VuenextTickcalls that don't wait for Vue to update the page. The rule is recommended and part of the Vue domain.import { nextTick } from "vue"; nextTick(); // reported: the Promise is ignored nextTick.then(callback); // reported: `nextTick` isn't called
-
#12674
361c9f2Thanks @dyc3! - Fixed #12672: Astro and Svelte formatting now preserves comments and whitespace inside preformatted elements such as<pre>and<textarea>.-<pre><code>Hello</code></pre> +<pre> + <!-- hello --> + <code>Hello</code> +</pre>
-
#12746
2ebd7b6Thanks @ematipico! - Improved #2730: Biome now reports the active analyzer rule and source range when a rule panics, and suggests disabling the rule as a workaround. -
#12758
1df6d85Thanks @dyc3! - Fixed #12739, #12741, and #12742: the Markdown formatter now adds a blank line between a top-level paragraph and a header, fenced code block, list, or blockquote that directly follows it, matching Prettier.Some text: + - bullet 1 - bullet 2 -
#12806
03261deThanks @Jayllyz! - Added the nursery ruleuseTanstackQueryInfiniteQueryPropertyOrder, which enforces the orderqueryFn,getPreviousPageParam,getNextPageParamin the options of TanStack Query infinite queries. TanStack Query infers types from this order.import { useInfiniteQuery } from "@tanstack/react-query"; useInfiniteQuery({ getNextPageParam: (lastPage) => lastPage.nextId, queryFn: ({ pageParam }) => fetchProjects(pageParam), });
-
#12762
69187a9Thanks @dyc3! - Fixed #12738: the Markdown formatter now collapses consecutive blank lines between blocks into a single blank line.Some paragraph. - - ## Next section
-
#12708
e87ec37Thanks @nhedger! - Fixed.editorconfigsection globs that skipped the character following a bracket expression. For example,[{[ab],c}.json]now matchesa.json,b.json, andc.json. -
#11623
37440f9Thanks @Bsibz! - Fixed #11548: ThetypeMemberselector ofuseNamingConventionno longer applies to TypeScript type parameters. -
#12106
ff1d8b8Thanks @dyc3! - Added the nursery rulenoExcessiveNestedBlocks, which reports blocks nested deeper than the configured maximum (4 by default). It checksif,switch,try, and loop statements in JavaScript, and nested rules and at-rules in CSS. -
#12747
397b0ebThanks @ematipico! - Fixed #8094: Biome's language server now skips unchanged dynamic capability registrations, preventing duplicate watched-file notifications in affected editors. -
#12708
e87ec37Thanks @nhedger! - Fixed #12683:.editorconfigsection globs with nested braces, such as[{*.{js,json},biome.jsonc}], are now supported instead of being ignored. -
#12910
6f8313dThanks @dyc3! - Fixed a slowdown inbiome lint,biome checkandbiome formatthat grew with the number of files: looking up an open file took longer after every file Biome had already processed. Large projects are processed faster again. -
#12787
53c3a49Thanks @dyc3! - Fixed the GritQL formatter treating a single line break between list items as a blank line. Formatting a broken list no longer adds blank lines between its items, and blank lines from the source are still kept.$x <: [ - `1`, - - `2`, + `1`, `2`, `3` ]
-
#12864
c2c2590Thanks @nhedger! - Fixed #12862: Biome now applies the options under the top-levelgritconfiguration key. Previously, options such asgrit.formatter.lineWidthandgrit.formatter.enabledwere ignored, and Grit files were formatted with the globalformattersettings. -
#12543
0ec0a72Thanks @dyc3! - FixednoVueUndeclaredDirectivesnot reporting undeclared custom directives in components that export their options withexport { options as default }.<script> const options = {}; export { options as default }; </script> <template> <div v-highlight></div> </template>
-
#12745
86be8b8Thanks @vidigoat! - Fixed the formatter removing the parentheses that end an optional chain when a non-null assertion, type arguments or more parentheses follow them. The output either short-circuited the rest of the chain, as ina?.b!.cfor(a?.b)!.c, or didn't parse, as withnew a?.b!(), a template tag or an assignment target.- a?.b!.c; + (a?.b)!.c; - new a?.b!(); + new (a?.b)!(); - a?.b`template`; + (a?.b)`template`;
-
#12821
44626baThanks @Suto-Michimasa! - Fixed #12820:usePlaywrightValidDescribeCallbackno longer reports an anonymoustest.describe(callback)as a missing callback.test.describe(() => { test.use({ colorScheme: "dark" }); });
-
#12819
b620cbcThanks @Suto-Michimasa! - Fixed #12766:usePlaywrightValidDescribeCallbackno longer reportstest.describe(title, details, callback). The rule now validates the last argument as the callback, as the original ESLint rule does.test.describe("suite", { tag: "@smoke" }, () => {});
-
#12898
291f034Thanks @dyc3! - Fixed #12882: the Tailwind class parser no longer reports a parse error for unknown utilities with a dashed name and an arbitrary value or a CSS variable, such asfoo-bar-[1px]orfoo-bar-(--my-var).useTailwindSortedClassessorts these classes first, like other unknown classes. -
#12639
bd19436Thanks @dyc3! - Fixed #12623: the safe fix ofuseConsistentTestItno longer leaves an unused import when applied to every call in a file. When all calls to an imported test function are renamed, the import is now replaced with an alias, such astest as it, instead of keeping the original specifier. When the original specifier is kept, the alias is now added astest, test as itinstead oftest , test as it. -
#12870
378798fThanks @dyc3! - Improved the performance of grit plugins that use regexes. -
#12769
6d23980Thanks @ematipico! - Fixed #12757: the Markdown formatter no longer turns an indented paragraph line that starts with-,1.,#, or>into a list, heading, or blockquote. Such a line now joins the previous line, matching Prettier.-- Item - - Nested item +- Item - Nested item continuation line
-
#12737
162ed76Thanks @xgbtxy! - Fixed #12726:useMathMinMaxnow recognizes directly listed nonnumeric elements in array reductions, such as["foo", "bar"].reduce((a, b) => a > b ? a : b). This also covers Date values and local constant arrays used only by reductions, including parentheses and TypeScript assertions. Spread elements and other unclassified inputs retain their existing behavior. -
#12782
44d6768Thanks @dyc3! - Added the new nursery rulenoInvalidRemoveEventListener, which reports calls toremoveEventListener()that pass an inline function or the result of.bind(). These create a new function, so the listener that was added is never removed.window.removeEventListener("click", listener.bind(window));
-
#12858
b312e95Thanks @dyc3! - Fixed #12851: a plugin that throws or fails to run now reports an error diagnostic instead of an info diagnostic, sobiome lintandbiome checkexit with a non-zero code. -
#12813
a55d360Thanks @dyc3! - Improved the performance of JavaScript plugins that readnode.kindortoken.kind. -
#12913
4ada6fcThanks @dyc3! - Fixed #12909: Biome no longer crashes with an access violation when formatting, linting or checking files on Windows ARM64. -
#12443
cccbc03Thanks @dyc3! - Fixed the code fixes ofnoMisusedPromises,noFloatingPromises, andnoVueDataObjectDeclarationduplicating comments attached to the wrapped expression. For example, thenoFloatingPromisesfix for an array of promises preceded by a comment no longer copies that comment intoPromise.all(...). -
#12769
6d23980Thanks @ematipico! - Fixed #12768: the Markdown formatter no longer splits a blockquote in two when an empty>line separates its list items.> - one > - two - +> > - three
-
#12769
6d23980Thanks @ematipico! - Fixed #12767: the Markdown formatter no longer moves a list item out of a blockquote when the item follows a nested list item. The formatter also keeps the>of a line that directly follows a list inside a blockquote and starts a nested blockquote, a heading, or a different list.> - one > - nested - - two +> - two
-
#12769
6d23980Thanks @ematipico! - Fixed #12703: the Markdown formatter no longer indents the empty>line between a list and a paragraph in a blockquote. Formatting again no longer moves the paragraph out of the quote.> - item one > continued. - > +> > Paragraph line one > line two.
-
#12465
5127af1Thanks @Th3S4mur41! - ExpandeduseLogicalPropertiesto report multi-value physical shorthands and logical longhand pairs that can be combined. Dynamic shorthands such aspadding: var(--spacing) 2pxare also reported without an automatic fix because the variable may supply multiple values.
-
#12860
31f1820Thanks @vibbix! - Fixed the SCSS formatter joining comma-separated multi-value declarations onto one line. SCSS now prints them one value per line, as the CSS formatter and Prettier do..a { - transition: opacity 1s, color 2s; + transition: + opacity 1s, + color 2s; } -
#12868
ac70a85Thanks @dyc3! - Addednode.descendants(kinds)andnode.walk(kinds, enter, exit)to JavaScript plugins. They find the nodes inside a node whose kind is in a set created withnodeKinds(), and are much faster than visiting every node withnode.children().const CALLS = nodeKinds("JS_CALL_EXPRESSION"); for (const call of root.descendants(CALLS)) { registerDiagnostic(call, "information", "Found a call."); }
-
#12786
126c172Thanks @dyc3! - Added theallowBlackAndWhiteoption tonoTailwindRawColors. It defaults totrue. When set tofalse, the rule also reports classes that useblackorwhite, such asbg-whiteandtext-black/50, and suggests similar colors from your theme whentailwind.stylesheetis set.{ "options": { "allowBlackAndWhite": false } } -
#12754
a00eb5aThanks @dyc3! - Fixed #12724: whenproseWrapis"always"or"never", the Markdown formatter now wraps the text inside emphasis, strong emphasis, and strikethrough like the surrounding prose, instead of keeping their source line breaks and forcing line breaks around them. Text inside block quotes keeps its current formatting. With alineWidthof 50:- Some words before the strong text, - **stop and tell - them** - after the strong text. + Some words before the strong text, **stop and tell + them** after the strong text.
-
#12708
e87ec37Thanks @nhedger! - Fixed.editorconfigsection globs with unbalanced braces. As in the EditorConfig reference implementation, all braces in such a glob are now matched literally, so[{a,b}}.json]only matches a file named{a,b}}.json.
What's Changed
- feat(lint): add useVueConsistentDefineEmitsDeclaration by @dyc3 in #12675
- feat(lint): add tests for logical shorthands and longhands by @Th3S4mur41 in #12465
- refactor: use our parser for rule docs by @ematipico in #12744
- feat(deserialize): yaml by @ematipico in #12064
- feat(analyzer): panic handler by @ematipico in #12746
- fix(deps): bump libz-sys to 1.1.31 (RUSTSEC-2026-0418) by @nhedger in #12750
- fix(lint): skip nonnumeric reductions in useMathMinMax by @xgbtxy in #12737
- fix(format/md): fix various missing empty lines bugs by @dyc3 in #12758
- fix(format/js): keep the parens that end an optional chain before
!, type arguments or more parens by @vidigoat in #12745 - fix(lsp): dynamic capability registration by @ematipico in #12747
- fix(editorconfig): support nested brace alternates in section globs by @nhedger in #12708
- fix(format/md): collapse consecutive blank lines between blocks by @dyc3 in #12762
- fix(md/fmt): quote blocks and lists by @ematipico in #12769
- chore: fix formatting in some of our readmes by @dyc3 in #12774
- feat(lint): add useVueValidNextTick by @dyc3 in #12557
- feat(lint): add noPseudoElementInFunctionalPseudoClass by @vibbix in #12388
- feat(lint): add noMissingScssInterpolation by @vibbix in #12342
- chore: add oxlint rule source by @dyc3 in #12784
- feat(lint): add useTailwindVariablesShorthand by @dyc3 in #12290
- feat(lint): add noVueVForTemplateKeyOnChild by @dyc3 in #12522
- feat(lint): add noVueLoneTemplate by @dyc3 in #12666
- feat(lint): add noVueDeprecatedSlotScope by @dyc3 in #12634
- feat(lint): add useVueRenderReturn by @dyc3 in #12566
- fix(js/useNamingconvention): prevent typeMember from matching type parameters by @Bsibz in #11623
- feat(rules_check): build vue semantic models and use them by @dyc3 in #12535
- feat(lint): add useVueValidDefineOptions by @dyc3 in #12613
- feat(lint): add useVueSlotNameCasing by @dyc3 in #12646
- feat(lint): add noVueMixin by @dyc3 in #12533
- feat(lint): add noVueUndeclaredEmits by @dyc3 in #12601
- feat(lint): add noVueDeprecatedPropsDefaultThis by @dyc3 in #12604
- feat(lint): add noVueRestrictedCallAfterAwait by @dyc3 in #12517
- feat(lint): add noVueDeprecatedModelDefinition by @dyc3 in #12617
- refactor(noVueUndeclaredDirectives): use vue semantic model by @dyc3 in #12543
- feat(lint): add noVueDeprecatedConfigKeyCodes by @dyc3 in #12616
- perf(plugins/js): strings emitted by the
.kindproperty are now static by @dyc3 in #12813 - chore: correct wording in changelog by @dyc3 in #12839
- feat(lint): add useAccessorPairs by @dyc3 in #12516
- feat(lint): add noDynamicDelete by @dyc3 in #12547
- feat(lint): add noUselessTypeAssertion by @dyc3 in #12488
- feat(lint): add noTanstackQueryVoidQueryFn by @dyc3 in #12515
- feat(lint): add useTanstackQueryStableQueryClient by @dyc3 in #12518
- feat(lint): add noVueRefObjectReactivityLoss by @dyc3 in #12564
- feat(lint): add useVueComputedPropertyReturn by @dyc3 in #12563
- feat(lint): add noVueRestrictedVOn by @dyc3 in #12558
- feat(lint): add noVueDeprecatedInlineTemplate by @dyc3 in #12553
- feat(lint): add noVueDeprecatedHtmlElementIs by @dyc3 in #12552
- feat(lint): add noVueDeprecatedDestroyedLifecycle by @dyc3 in #12568
- feat(lint): add useVuePropTypeConstructor by @dyc3 in #12571
- chore: fix changeset attribution by @dyc3 in #12816
- feat(lint): add noVueMultipleObjectsInClass by @dyc3 in #12658
- feat(lint): add noVueThisInBeforeRouteEnter by @dyc3 in #12665
- feat(lint): add noVueUndeclaredSlots by @dyc3 in #12657
- feat(lint): add useVueDefaultProp by @dyc3 in #12655
- feat(lint/js): add useTanstackQueryInfiniteQueryPropertyOrder by @Jayllyz in #12806
- fix(lint): accept anonymous describe in usePlaywrightValidDescribeCallback by @Suto-Michimasa in #12821
- fix(format/html): preserve comments in
<pre>in astro and svelte files by @dyc3 in #12674 - fix(useConsistentTestIt): don't leave an unused import after the safe fix by @dyc3 in #12639
- feat(noTailwindRawColors): add allowBlackAndWhite option by @dyc3 in #12786
- chore: update rule metadata by @dyc3 in #12847
- feat(lint): add useSetSize by @dyc3 in #12778
- fix(lint): keep comments once when code fixes wrap a node by @dyc3 in #12443
- feat(lint): add noVueDeprecatedVBindSync by @dyc3 in #12589
- feat(lint): add noVueDeprecatedVOnNativeModifier by @dyc3 in #12609
- feat(lint): add noVueDeprecatedFunctionalTemplate by @dyc3 in #12590
- feat(lint): add noVueUselessVBind by @dyc3 in #12592
- feat(lint): add noVueTemplateKey by @dyc3 in #12573
- feat(lint): add noVueDeprecatedEventsApi by @dyc3 in #12654
- feat(lint): add noVueExcessiveProps by @dyc3 in #12667
- feat(lint): add useVueTypedObjectProps by @dyc3 in #12659
- feat(lint): add noVueDeprecatedSlotAttribute by @dyc3 in #12633
- feat(lint): add useVueValidAttributeName by @dyc3 in #12574
- feat(lint): add useVueBlockOrder by @dyc3 in #12650
- feat(lint): add noVueChildContent by @dyc3 in #12632
- feat(lint): add useVueValidDefaultProp by @dyc3 in #12582
- feat(lint): add noVueUndeclaredProperties by @dyc3 in #12583
- feat(lint): add noVueTemplateShadow by @dyc3 in #12629
- feat(lint): add useVueEmitsValidatorReturn by @dyc3 in #12605
- feat(lint): add noVueThisInTemplate by @dyc3 in #12620
- feat(lint): add useVueConsistentVForDelimiter by @dyc3 in #12608
- feat(lint): add useVueSlotsAsFunctions by @dyc3 in #12572
- feat(lint): add useVueEmitValidator by @dyc3 in #12676
- feat(lint): add useVueSingleEventPayload by @dyc3 in #12677
- feat(lint): add useVueBooleanPropTypeFirst by @dyc3 in #12715
- refactor(cli): read environment variables through an injectable source by @ematipico in #12427
- feat(plugins/js): add tokenKinds and nodeKinds APIs by @dyc3 in #12812
- fix(grit/fmt): don't treat a single line break in lists as a blank line by @dyc3 in #12787
- fix(plugins/js): report plugin failures as errors by @dyc3 in #12858
- fix(markdown_formatter): wrap emphasis content with surrounding prose by @dyc3 in #12754
- fix(lint): accept details argument in usePlaywrightValidDescribeCallback by @Suto-Michimasa in #12819
- fix(lint): multi-value declarations for SCSS don't match prettier by @vibbix in #12860
- feat(lint): add useVueConsistentPropNameCasing by @dyc3 in #12612
- feat(lint): add useVueConsistentVSlotStyle by @dyc3 in #12611
- feat(lint): add useVueSeparateStaticClass by @dyc3 in #12619
- feat(lint): add useVueMacroVariableName by @dyc3 in #12668
- feat(lint): add noUnnecessaryStringTrim by @dyc3 in #12482
- feat(lint): add useVueTrueAttributeShorthand by @dyc3 in #12716
- feat(lint): add noUselessLengthCheck by @dyc3 in #12783
- feat(lint): add useVueDefaultExport by @dyc3 in #12780
- feat(lint): add noVueTextareaMustache by @dyc3 in #12610
- feat(lint): add useObjectFromEntries by @dyc3 in #12756
- feat(lint): add noArrayForEach by @dyc3 in #12755
- feat(lint): add noSyncMethods by @dyc3 in #12764
- feat(lint): add noSinglePromiseInPromiseMethods by @dyc3 in #12779
- feat(lint): add noAwaitInPromiseMethods by @dyc3 in #12777
- feat(lint): add noInvalidRemoveEventListener by @dyc3 in #12782
- feat(lint): add noChainedComparison by @dyc3 in #12765
- feat(lint): add noLateEventControl by @dyc3 in #12481
- feat(lint/js): add noExcessiveNestedBlocks by @dyc3 in #12106
- feat(lint): add noMissingThrow by @dyc3 in #12792
- feat(lint): add noPlaywrightUnsafeReferences by @dyc3 in #12450
- feat(lint): add noUselessAwait by @dyc3 in #12772
- feat(lint): add noObjectLiteralComparison by @dyc3 in #12790
- feat(lint): add useSvelteStoreInitialValue by @dyc3 in #12302
- feat(lint): add noMapSpread by @dyc3 in #12795
- feat(lint): add noMismatchedMapKey by @dyc3 in #12793
- feat(lint): add noVueUselessTemplateAttributes by @dyc3 in #12789
- feat(lint): add useVueOneComponentPerFile by @dyc3 in #12773
- feat(lint): add noSvelteBindValueOnCheckableInputs by @dyc3 in #12241
- chore: update rule metadata by @dyc3 in #12875
- fix(service): apply the top-level grit configuration by @nhedger in #12864
- perf(grit): bump grit-pattern-matcher and grit-util to 0.5.2 by @dyc3 in #12870
- feat(plugins/js): add optimized traversal APIs by @dyc3 in #12868
- fix(parse/tailwind): handle long dashed base names when aribtrary values are involved by @dyc3 in #12898
- perf(analyze): make a disabled rule timer free by @dyc3 in #12911
- chore(deps): pin mimalloc again, add the bad versions to cargo deny by @dyc3 in #12913
- feat(plugins/js): add union to node and token kind sets by @dyc3 in #12914
- perf(service): finish resizes of the file view maps in the writer that starts them by @dyc3 in #12910
- chore: increase size of release builders by @dyc3 in #12919
- ci: release by @github-actions[bot] in #12918
New Contributors
- @xgbtxy made their first contribution in #12737
- @Bsibz made their first contribution in #11623
- @Suto-Michimasa made their first contribution in #12821
Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.6.4...@biomejs/biome@2.6.5