github biomejs/biome @biomejs/biome@2.6.8
Biome CLI v2.6.8

39 minutes ago

2.6.8

Patch Changes

  • #13080 a68137d Thanks @dyc3! - Added the nursery rule noBufferConstructor, which disallows the deprecated Node.js Buffer() and new Buffer() constructors. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead.

    new Buffer(5);
  • #12966 82651f5 Thanks @dyc3! - Added the nursery rule noConfusingArraySplice, which reports splice() and toSpliced() calls that replace a single element or insert at index -1.

    array.splice(index, 1, element); // use `array[index] = element` instead
  • #12924 0a9d204 Thanks @dyc3! - Added the nursery rule noDynamicRequire, which disallows require() calls whose module name is built at runtime. When the checkDynamicImports option is enabled, the rule also checks import() calls.

    require("./locales/" + language);
  • #12907 6f2635a Thanks @dyc3! - Added the nursery rule noLateCurrentTargetAccess, which reports reads of event.currentTarget that run after the browser has finished handling the event, when currentTarget is null.

    element.addEventListener("click", async (event) => {
      await save();
      event.currentTarget.disabled = false;
    });
  • #12904 04f30c4 Thanks @dyc3! - Added the nursery rule noMisusedSpread, which uses type information to report spreads that produce unexpected results: strings spread into arrays or arguments, and promises, functions, maps, arrays, iterables, class instances, and classes spread into objects or JSX attributes.

    declare function getUser(): Promise<{ name: string }>;
    const user = { ...getUser() };
  • #12893 5d7ca32 Thanks @dyc3! - Added the nursery rule noTripleSlashReference, which reports /// <reference path="..." /> comments and /// <reference types="..." /> comments for packages that the file also imports. The lib, path, and types options control which kinds of references are allowed.

    /// <reference path="./globals.d.ts" />
  • #12561 746c421 Thanks @dyc3! - Added the nursery rule noVueAsyncComputed, which reports asynchronous code in Vue computed properties, such as async functions, await, promises, setTimeout(), and nextTick().

    <script>
    export default {
      computed: {
        async user() {
          return fetchUser(this.userId);
        },
      },
    };
    </script>
  • #12964 149d729 Thanks @dyc3! - Added the nursery rule noVueDefineModelDefault, which disallows the default option in Vue's defineModel(). When a parent component passes undefined with v-model, the child component uses the default value while the parent keeps undefined, so the two components show different values.

    <script setup>
    const model = defineModel({ type: String, default: "" });
    </script>
  • #13060 67bc9d5 Thanks @dyc3! - Added the nursery rule noVueDeprecatedFilter, which reports the filter syntax that Vue 3 removed.

    For example, the following template uses the currency filter:

    <template>
      <p>{{ price | currency }}</p>
    </template>
  • #12545 0bbe4f1 Thanks @dyc3! - Added the new nursery rule noVueDeprecatedVIs, which reports the deprecated Vue v-is directive. Use the is attribute with a vue: prefix instead.

    <template>
      <div v-is="'MyComponent'"></div>
    </template>
  • #12580 3fdc987 Thanks @dyc3! - Added the nursery rule noVueExportInScriptSetup, which disallows export in Vue <script setup> blocks. Vue fails to compile a component when its <script setup> block exports a value. TypeScript type exports are allowed.

    <script setup>
    export const message = "Hello";
    </script>
  • #13063 d4e90c8 Thanks @dyc3! - Added the nursery rule noYamlEmptyMapKeys, which reports YAML map entries whose key is missing, or has only a tag or an anchor. The rule is recommended.

    : value
  • #13061 97aa183 Thanks @dyc3! - Added the nursery rule noYamlEmptyMapValues, which reports keys in YAML maps that have no value.

    name:
  • #13062 6aad75f Thanks @dyc3! - Added the new nursery rule noYamlEmptySequenceEntries, which reports empty items in YAML lists.

    fruits:
      - apple
      -
      - banana
  • #13082 c1c8c85 Thanks @dyc3! - Added the nursery rule useCalledWith, which reports toHaveBeenCalled(), toBeCalled(), and toHaveBeenCalledOnce() assertions, because they don't check the arguments that the function was called with. The rule belongs to the test domain.

    expect(sendEmail).toHaveBeenCalled();
  • #13075 acfeaf9 Thanks @dyc3! - Added the nursery rule useExpectToHaveBeenCalled, which reports tests that compare the number of calls of a mock function to zero, and suggests using toHaveBeenCalled() instead.

    expect(sendEmail).toHaveBeenCalledTimes(0);
  • #13076 cf5b1a6 Thanks @dyc3! - Added the nursery rule useExpectToHaveBeenCalledTimes, which reports tests that check the length of mock.calls with toHaveLength(), and suggests using toHaveBeenCalledTimes() instead.

    expect(onSave.mock.calls).toHaveLength(1);
  • #13020 5d28641 Thanks @dyc3! - Added the new nursery rule usePackageJsonValidLicense, which reports a license field in package.json that isn't a valid license. The rule accepts SPDX license identifiers and expressions, UNLICENSED, and references to a license file such as SEE LICENSE IN LICENSE.md.

    For example, the rule reports the following package.json file because GPL3 isn't an SPDX license identifier:

    {
      "name": "my-package",
      "license": "GPL3"
    }
  • #13079 058d7a1 Thanks @dyc3! - Added the nursery rule useSpyOn, which reports properties that are overwritten with jest.fn() or vi.fn(). Overwriting a property loses its original value, while jest.spyOn() and vi.spyOn() keep it so it can be restored after the test.

    Date.now = jest.fn(() => 10);
  • #13081 be58f67 Thanks @dyc3! - Added the nursery rule useTopLevelRequire, which reports require() calls that aren't at the top level of the module, such as calls inside functions, blocks, or try statements.

    function readFile(filename, callback) {
        const fs = require("fs");
        fs.readFile(filename, callback);
    }
  • #13054 4d81f0d Thanks @dyc3! - Added the nursery rule useValidNamespaceImports, which reports names read from a namespace import that the imported module doesn't export. It also reports assignments to members of a namespace import, and namespace imports of modules that have no exports.

    import * as utils from "./utils.js";
    
    utils.subtract(2, 1); // `./utils.js` doesn't export `subtract`
  • #13058 ae251e4 Thanks @dyc3! - Added the new nursery rule useVueConsistentVOnHandlerStyle, which enforces one style of event handler in Vue v-on directives. By default, it prefers the name of a method, and an inline function where a method name can't be used.

    <template>
      <button @click="save()">Save</button>
    </template>
  • #12965 c33c03d Thanks @dyc3! - Added the nursery rule useVueRegisteredComponentNameCasing, which requires the names of components registered in the components option of a Vue component to use one casing style. By default, names must be in PascalCase. The casing option switches the rule to camelCase or kebab-case.

    <script>
    export default {
      components: {
        "todo-item": TodoItem,
      },
    };
    </script>
  • #12145 596a2b1 Thanks @ematipico! - Added type narrowing for unwritten local let/const variables and parameters after typeof, equality, nullish, and truthiness checks. Type-aware rules now use these refinements in branches, short-circuit expressions, and after early returns, including noUnnecessaryConditions and noFloatingPromises. Types such as {} no longer imply that a value is always truthy.

  • #12935 e506ff1 Thanks @dyc3! - Improved the performance of the rules noRedeclare and noUnsafeDeclarationMerging. biome lint with Biome's default rules is now about 3% to 5% faster on large projects, and up to 11% faster on some TypeScript projects.

  • #13181 e1556ae Thanks @dyc3! - Fixed the HTML formatter printing a comment twice when it ends the line of an element's opening tag. For example, <div><!-- comment --> followed by <i>x</i></div> on the next line is now formatted as:

    - <div><!-- comment -->
    + <div>
      	<!-- comment -->
      	<i>x</i>
      </div>
  • #13130 1b350ed Thanks @dyc3! - Fixed #13107: the unsafe fix of noDistractingElements now removes the whole element, including its closing tag and children, instead of only the opening tag. The fix is no longer offered when removing the element would produce invalid code, such as const Ticker = () => <marquee>News</marquee>;.

  • #13054 4d81f0d Thanks @dyc3! - Fixed noUnresolvedImports reporting names that a module re-exports from a CommonJS module or from a file that isn't JavaScript, such as export { foo } from "./legacy.cjs". The rule now also reports default imports from a module that only re-exports another module with export * from, because export * from doesn't forward the default export.

  • #12602 d5da394 Thanks @dyc3! - Fixed #12600: biome lint --suppress now adds suppression comments for diagnostics emitted by plugins, such as // biome-ignore lint/plugin/noFoo: ignored using `--suppress` .

  • #13097 3be9e3d Thanks @ashokram-si! - Fixed #13064: The noUnknownTypeSelector rule now correctly accepts the valid <selectedcontent> HTML element used in customizable select controls.

  • #13181 e1556ae Thanks @dyc3! - Fixed #13167: The HTML formatter no longer deletes comments that follow a Svelte block delimiter on the same line, such as {#if}, {:else}, or {#each}. For example, {#if a}<!-- comment --><i>x</i>{/if} is now formatted as:

      {#if a}
    - 	<i>x</i>
    + 	<!-- comment --><i>x</i>
      {/if}
  • #12845 e3ab04d Thanks @dyc3! - Fixed the location of Tailwind CSS diagnostics reported on unquoted object keys. In clsx({ shadow: active }), diagnostics now highlight shadow instead of starting one character later at hadow:.

  • #13098 d3be626 Thanks @ashokram-si! - Fixed #13084: The useThisInClassMethods rule now correctly recognizes this when used inside parameter default values for methods, setters, and class fields.

  • #13131 a788cac Thanks @dyc3! - Fixed #13129: the fix of useArrowFunction no longer produces invalid code when the function is in the initializer of a for statement and returns an in expression. The arrow function body is now wrapped in parentheses.

    // Before
    for (let has = function (k) { return k in cache; }; ;) {}
    // After the fix
    for (let has = (k) => (k in cache); ;) {}
  • #12840 8908627 Thanks @dyc3! - Fixed #12796: useMathMinMax no longer reports comparisons with a bigint written as an expression, such as -1n or 2n ** 62n - 1n, or with a const variable initialized with one. Its unsafe fix turned these comparisons into Math.min() or Math.max() calls, which throw a TypeError when given a bigint.

    const MAX = 2n ** 62n - 1n;
    const clamp = (x) => (x > MAX ? MAX : x);
  • #13152 61924f6 Thanks @dyc3! - Fixed noVueWatchAfterAwait, noVueLifecycleAfterAwait and noVueRestrictedCallAfterAwait, which now also check the setup() function passed as the first argument of defineComponent(). The following code is now reported:

    import { defineComponent, onMounted } from "vue";
    
    defineComponent(async (props) => {
      await load();
      onMounted(() => {});
    }, { props: ["id"] });

    When defineComponent() receives both a function and an options object, these rules now ignore the setup option, because Vue runs the function instead.

  • #13152 61924f6 Thanks @dyc3! - noVueDuplicateKeys now checks the properties returned by a setup() method of an options object, so return { foo } conflicts with a prop, data property, method or computed property named foo.

  • #13152 61924f6 Thanks @dyc3! - The Vue emit rules now read events declared with a function type, as in defineEmits<(e: "change", value: string) => void>(), and event names written as template literals without substitutions, as in emit(`change`). noVueUndeclaredEmits, noVueUnusedEmitDeclarations, useVueSingleEventPayload and useVueEmitValidator previously skipped events declared in these forms.

    noVueShadowNativeEvents now checks this.$emit() only where this is the component, and no longer reports $emit() called through a variable that holds this, as in const vm = this; vm.$emit("click").

  • #12947 a54965d Thanks @machadinhos! - Added the nursery rule noDrizzleDbObjectInsideTransaction, which reports a Drizzle ORM instance used inside its own transaction callback instead of the transaction object.

    await db.transaction(async (tx) => {
      await db.insert(users).values({ name: "John" });
    });
  • #13123 e7c8297 Thanks @ematipico! - Fixed #12176: type-aware rules now select the matching overload of a method declared several times in an interface or object type. For example, useAwaitThenable no longer reports await app.listen({ port: 0 }) on a Fastify server, and still reports await app.listen({ port: 0 }, callback).

  • #12059 87784c7 Thanks @dyc3! - Fixed noUnsafePlusOperands treating the negation of a bigint value as a number. Code such as -value + 1n, where value is declared as bigint, is no longer reported for mixing number and bigint.

  • #13151 be372b5 Thanks @dyc3! - Fixed Vue lint rules such as useVueVModel and useVueVOnExact treating MathML elements like <math> and <mi> as components. Biome now recognizes the MathML Core elements as native elements, and in Vue, Svelte, and Astro files it treats known hyphenated elements such as <annotation-xml> and the SVG <font-face> as native elements instead of components.

  • #12059 87784c7 Thanks @dyc3! - Type inference now evaluates conditional types such as T extends U ? X : Y, including infer and distribution over unions, instead of treating them as a union of both branches. This also applies to built-in types such as Exclude, Extract, ReturnType, Parameters, and Awaited, which improves the accuracy of type-aware rules such as noFloatingPromises.

    type Unwrap<T> = T extends Promise<infer U> ? U : T;
    // Previously inferred as `unknown | Promise<number>`, now as `number`.
    type Value = Unwrap<Promise<number>>;
  • #12602 d5da394 Thanks @dyc3! - Biome now reports an error when a GritQL plugin file name contains invalid characters that could conflict with Biome suppressions.

  • #12838 81d8d28 Thanks @dyc3! - Added the nursery rule noTailwindRestrictedClasses for JavaScript and HTML. It reports the Tailwind CSS classes and variants listed in its options with a custom message, and can replace them with a configured class or variant.

    {
      "linter": {
        "rules": {
          "nursery": {
            "noTailwindRestrictedClasses": {
              "level": "error",
              "options": {
                "classes": {
                  "bg-green-500": { "message": "Use the success color.", "use": "bg-success" },
                  "float-*": "Use flexbox or grid for layout."
                }
              }
            }
          }
        }
      }
    }
    <div className="hover:bg-green-500 float-left" />; // both classes are reported
  • #12932 68e6887 Thanks @dyc3! - Improved the performance of linting files that have no suppression comments by up to 61%.

  • #13136 dcb1eab Thanks @dyc3! - Improved the performance of linting JavaScript and HTML files when Tailwind rules are enabled.

  • #13094 ae66383 Thanks @dyc3! - Fixed #12994: the HTML formatter no longer moves a word onto its own line when it follows an inline element or {expression} that starts a line. Formatting such text is now stable after one pass.

     <span>
     	Showing the first {shown} of
    -	{total}
    -	references
    +	{total} references
     </span>
  • #13162 854ff15 Thanks @Punisheroot! - Fixed #13125: noUselessThisAlias no longer reports aliases used in instance and static class field initializers, where replacing the alias with this changes which object is accessed.

  • #12059 87784c7 Thanks @dyc3! - Fixed type inference for the intersection of a primitive type and one of its literal types, such as string & "a", which Biome inferred as never instead of "a". Type-aware rules such as useExhaustiveSwitchCases and noFloatingPromises now see the literal, so the following switch is reported for missing the "a" case.

    type Kind = ("a" & string) | "b";
    
    function handle(kind: Kind) {
      switch (kind) {
        case "b":
          break;
      }
    }
  • #12551 ca039a1 Thanks @pkallos! - Fixed #9842: useNullishCoalescing no longer skips || and ||= inside a call to a locally declared Boolean when ignoreBooleanCoercion is enabled.

What's Changed

  • fix(lint/js): count this in parameter defaults in useThisInClassMethods by @ashokram-si in #13098
  • chore(deps): update dependency @types/node to v24.19.2 by @renovate[bot] in #13046
  • fix(lint): check Boolean is global in useNullishCoalescing by @pkallos in #12551
  • chore: delete weird files by @ematipico in #13117
  • feat(type_inference): support conditional types and infer bindings by @dyc3 in #12059
  • docs(lint/css): skip Sass-evaluated math functions in useBaseline by @vibbix in #12974
  • feat(types): add flow-sensitive narrowing foundations by @ematipico in #12145
  • feat(types): narrow explicit local predicate calls by @ematipico in #12146
  • feat(types): narrow after standalone assertion calls by @ematipico in #12147
  • feat(lint): add noVueDeprecatedVIs by @dyc3 in #12545
  • feat(lint): add noTailwindRestrictedClasses by @dyc3 in #12838
  • feat(lint): add noTripleSlashReference by @dyc3 in #12893
  • feat(lint): add noMisusedSpread by @dyc3 in #12904
  • feat(lint): add noLateCurrentTargetAccess by @dyc3 in #12907
  • feat(lint): add noDynamicRequire by @dyc3 in #12924
  • feat(lint): add noVueDefineModelDefault by @dyc3 in #12964
  • feat(lint): add noConfusingArraySplice by @dyc3 in #12966
  • feat(lint): add useVueRegisteredComponentNameCasing by @dyc3 in #12965
  • feat(lint): add usePackageJsonValidLicense by @dyc3 in #13020
  • fix(inference): overload in local inference by @ematipico in #13123
  • docs: typo in static value doc comments by @ninglinLiu in #13132
  • chore(deps): update to rust 1.100, add minimum release age config by @dyc3 in #13124
  • fix(noDistractingElements): remove the whole element in the unsafe fix by @dyc3 in #13130
  • fix(useArrowFunction): parenthesize in bodies in for initializers by @dyc3 in #13131
  • fix(useMathMinMax): trace bindings a little further to figure out if the arguments are bigints by @dyc3 in #12840
  • perf(inference): queries and namespace by @ematipico in #13126
  • chore: update rule metadata by @dyc3 in #13134
  • perf(package): sublinear SPDX licence lookup by @dyc3 in #13138
  • perf(lint): implement visited_kinds() for tailwind class string query, simplify it by @dyc3 in #13136
  • perf(html): add token set for mathml elements by @dyc3 in #13151
  • refactor(lint): make old vue rules use the new vue semantic model by @dyc3 in #13152
  • feat(lint): add noDrizzleDbObjectInsideTransaction by @machadinhos in #12947
  • fix(format/html): keep words after inline elements on the same line by @dyc3 in #13094
  • fix(lint/css): recognize the selectedcontent element in noUnknownTypeSelector by @ashokram-si in #13097
  • fix(analyze): emit suppression actions for plugin diagnostics by @dyc3 in #12602
  • feat(lint): add useVueConsistentVOnHandlerStyle by @dyc3 in #13058
  • feat(lint): add noVueDeprecatedFilter by @dyc3 in #13060
  • feat(lint): add noYamlEmptyMapValues by @dyc3 in #13061
  • feat(lint): add noYamlEmptyMapKeys by @dyc3 in #13063
  • feat(lint): add noYamlEmptySequenceEntries by @dyc3 in #13062
  • feat(lint): add useExpectToHaveBeenCalled by @dyc3 in #13075
  • feat(lint): add useExpectToHaveBeenCalledTimes by @dyc3 in #13076
  • feat(lint): add useSpyOn by @dyc3 in #13079
  • feat(lint): add noBufferConstructor by @dyc3 in #13080
  • feat(lint): add useTopLevelRequire by @dyc3 in #13081
  • feat(lint): add useCalledWith by @dyc3 in #13082
  • feat(lint): add noVueExportInScriptSetup by @dyc3 in #12580
  • feat(lint): add useValidNamespaceImports by @dyc3 in #13054
  • feat(lint): add noVueAsyncComputed by @dyc3 in #12561
  • fix(tailwind): locate classes in unquoted object keys correctly by @dyc3 in #12845
  • chore(deps): ignore js-sys crate in renovate config by @dyc3 in #13182
  • fix(format/html/svelte): keep comments after block delimiters and opening tags by @dyc3 in #13181
  • fix(lint): preserve this aliases in class field initializers by @Punisheroot in #13162
  • perf(lint): locate binding nodes near the query node in noRedeclare by @dyc3 in #12935
  • perf(analyze): skip the suppression token pass in files without suppression comments by @dyc3 in #12932
  • fix(format/html): print comment before suppressed first child once by @dyc3 in #13189
  • docs(skills): improve comments writing by @ematipico in #13197
  • docs(skill): improve writing style by @ematipico in #13198
  • ci: release by @github-actions[bot] in #13104

New Contributors

Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.6.7...@biomejs/biome@2.6.8

Don't miss a new biome release

NewReleases is sending notifications on new releases.