Перейти до вмісту

Журнал змін

2.4.0 Latest

Minor Changes

  • #8964 0353fa0 Thanks @dyc3! - Added ignore option to the useHookAtTopLevel rule.

    You can now specify function names that should not be treated as hooks, even if they follow the use* naming convention.

    Example configuration:

    {
    "linter": {
    "rules": {
    "correctness": {
    "useHookAtTopLevel": {
    "options": {
    "ignore": ["useDebounce", "useCustomUtility"]
    }
    }
    }
    }
    }
    }
  • #8769 d0358b0 Thanks @rahuld109! - Added the rule useAnchorContent for HTML to enforce that anchor elements have accessible content for screen readers. The rule flags empty anchors, anchors with only whitespace, and anchors where all content is hidden with aria-hidden. Anchors with aria-label or title attributes providing a non-empty accessible name are considered valid.

  • #8742 6340ce6 Thanks @rahuld109! - Added the rule useMediaCaption to the HTML language. Enforces that audio and video elements have a track element with kind="captions" for accessibility. Muted videos are allowed without captions.

  • #8621 d11130b Thanks @Netail! - Added support for multiple reporters, and the ability to save reporters on arbitrary files.

    Combine two reporters in CI

    If you run Biome on GitHub, take advantage of the reporter and still see the errors in console, you can now use both reporters:

    Terminal window
    biome ci --reporter=default --reporter=github

    Save reporter output to a file

    With the new --reporter-file CLI option, it’s now possible to save the output of all reporters to a file. The file is a path, so you can pass a relative or an absolute path:

    Terminal window
    biome ci --reporter=rdjson --reporter-file=/etc/tmp/report.json
    biome ci --reporter=summary --reporter-file=./reports/file.txt

    You can combine these two features. For example, have the default reporter written on terminal, and the rdjson reporter written on file:

    Terminal window
    biome ci --reporter=default --reporter=rdjson --reporter-file=/etc/tmp/report.json

    The --reporter and --reporter-file flags must appear next to each other, otherwise an error is thrown.

  • #8399 ab88099 Thanks @ematipico! - The Biome CSS parser is now able to parse Vue SFC syntax such as :slotted and :deep. These pseudo functions are only correctly parsed when the CSS is defined inside .vue components. Otherwise, Biome will a emit a parse error.

    This capability is only available when experimentalFullHtmlSupportedEnabled is set to true.

  • #8663 3dfea16 Thanks @ematipico! - Added support for Cursor files. When Biome sees a Cursor JSON file, it will parse it with comments enabled and trailing commas enabled:

    • $PROJECT/.cursor/
    • %APPDATA%\Cursor\User\ on Windows
    • ~/Library/Application Support/Cursor/User/ on macOS
    • ~/.config/Cursor/User/ on Linux
  • #8723 fe2c642 Thanks @cbstns! - Added JSON as a target language for GritQL pattern matching. You can now write Grit plugins for JSON files.

    This enables users to write GritQL patterns that match against JSON files, useful for:

    • Searching and transforming JSON configuration files
    • Enforcing patterns in package.json and other JSON configs
    • Writing custom lint rules for JSON using GritQL

    Example patterns:

    Match all key-value pairs:

    language json
    pair(key = $k, value = $v)

    Match objects with specific structure:

    language json
    JsonObjectValue()

    Supports both native Biome AST names (JsonMember, JsonObjectValue) and TreeSitter-compatible names (pair, object, array) for compatibility with existing Grit patterns.

    For more details, see the GritQL documentation.

  • #8814 4d9c676 Thanks @Netail! - Added ignore option to noUnknownProperty. If an unknown property name matches any of the items provided in ignore, a diagnostic won’t be emitted.

  • #8631 4d8f19d Thanks @Netail! - Add a new reporter --reporter=sarif, that emits diagnostics using the SARIF format.

  • #8270 4f7909d Thanks @lucasweng! - Added the useIframeTitle lint rule for HTML. The rule enforces the usage of the title attribute for the iframe element.

    Invalid:

    <iframe></iframe> <iframe title=""></iframe>

    Valid:

    <iframe title="title"></iframe>
  • #8164 1d25856 Thanks @ematipico! - Added a new assist action useSortedInterfaceMembers that sorts TypeScript interface members, for readability.

    It includes an autofix.

    Invalid example.

    interface MixedMembers {
    z: string;
    a: number;
    (): void;
    y: boolean;
    }

    Valid example (after using the assist).

    interface MixedMembers {
    a: number;
    y: boolean;
    z: string;
    (): void;
    }
  • #8647 4c7c06f Thanks @siketyan! - It’s now possible to provide the stacktrace for a fatal error. The stacktrace is only available when the environment variable RUST_BACKTRACE=1 is set, either via the CLI or exported $PATH. This is useful when providing detailed information for debugging purposes:

    Terminal window
    RUST_BACKTRACE=1 biome lint
  • #7961 a04c8df Thanks @siketyan! - The Biome Language Server now reports progress while scanning files and dependencies in the project.

  • #8289 a9025d4 Thanks @theshadow27! - Fixed #8024. The rule useIterableCallbackReturn now supports a checkForEach option. When set to false, the rule will skip checking for forEach() callbacks for returning values.

  • #8690 e06e5d1 Thanks @ematipico! - Added the rule useValidLang to the HTML language.

  • #7847 e90b14f Thanks @Jagget! - Added support for jsxFactory and jsxFragmentFactory.Biome now respects jsxFactory and jsxFragmentFactory settings from tsconfig.json when using the classic JSX runtime, preventing false positive noUnusedImports errors for custom JSX libraries like Preact.

    tsconfig.json
    {
    compilerOptions: {
    jsx: "react",
    jsxFactory: "h",
    jsxFragmentFactory: "Fragment",
    },
    }
    Component.jsx
    import { h, Fragment } from "preact";
    function App() {
    return <div>Hello</div>;
    }
  • #8071 7f5bcf4 Thanks @ematipico! - Added new CLI options to the commands lsp-proxy and start that allow to control the Biome file watcher.

    --watcher-kind

    Controls how the Biome file watcher should behave. By default, Biome chooses the best watcher strategy for the current OS, however sometimes this could result in some issues, such as folders locked.

    The option accepts the current values:

    • recommended: the default option, which chooses the best watcher for the current platform.
    • polling: uses the polling strategy.
    • none: it doesn’t enable the watcher. When the watcher is disabled, changes to files aren’t recorded anymore by Biome. This might have repercussions on some lint rules that might rely on updated types or updated paths.

    The environment variable BIOME_WATCHER_KIND can be used as alias.

    --watcher-polling-interval

    The polling interval in milliseconds. This is only applicable when using the polling watcher. It defaults to 2000 milliseconds.

    The environment variable BIOME_WATCHER_POLLING_INTERVAL can be used as alias.

  • #8262 4186b83 Thanks @lucasweng! - Added the useHtmlLang lint rule for HTML. The rule enforces that the html element has a lang attribute.

    Invalid:

    <html></html>
    <html lang></html>
    <html lang=""></html>

    Valid:

    <html lang="en"></html>
  • #8376 1a9334c Thanks @siketyan! - Added support for formatting and linting embedded GraphQL snippets in JavaScript.

    For example, the following snippets are now formatted:

    import gql from "graphql-tag";
    const PeopleCountQuery = gql`
    query PeopleCount {
    allPeople {
    totalCount
    }
    }
    `;
    import { graphql } from "./graphql";
    const PeopleCountQuery = graphql(`
    query PeopleCount {
    allPeople {
    totalCount
    }
    }
    `);

    This feature is experimental and must be enabled explicitly in the configuration:

    {
    "javascript": {
    "experimentalEmbeddedSnippetsEnabled": true
    }
    }
  • #7799 54682aa Thanks @PaulRBerg! - Added groupByNesting option to the useSortedKeys assist. When enabled, object keys are grouped by their value’s nesting depth before sorting alphabetically.

    Simple values (primitives, single-line arrays, and single-line objects) are sorted first, followed by nested values (multi-line arrays and multi-line objects).

    Example

    To enable this option, configure it in your biome.json:

    {
    "linter": {
    "rules": {
    "source": {
    "useSortedKeys": {
    "options": {
    "groupByNesting": true
    }
    }
    }
    }
    }
    }

    With this option, the following unsorted object:

    const object = {
    name: "Sample",
    details: {
    description: "nested",
    },
    id: 123,
    };

    Will be sorted as:

    const object = {
    id: 123,
    name: "Sample",
    details: {
    description: "nested",
    },
    };
  • #8641 1dc8dc2 Thanks @tt-a1i! - Added the noAutofocus lint rule for HTML. This rule enforces that the autofocus attribute is not used on elements, as it can cause usability issues for sighted and non-sighted users. The rule allows autofocus inside dialog elements or elements with the popover attribute, as these are modal contexts where autofocus is expected.

  • #8501 8eb3f19 Thanks @tt-a1i! - Added noPositiveTabindex to HTML. This rule prevents the usage of positive integers on the tabindex attribute, which can disrupt natural keyboard navigation order.

  • #8661 b36ff03 Thanks @tt-a1i! - Added the useAltText lint rule for HTML. This rule enforces that elements requiring alternative text (<img>, <area>, <input type="image">, <object>) provide meaningful information for screen reader users via alt, title (for objects), aria-label, or aria-labelledby attributes. Elements with aria-hidden="true" are exempt.

  • #7749 1c59333 Thanks @andogq! - Implements #1984. Updated useHookAtTopLevel to better catch invalid hook usage.

    This rule is now capable of finding invalid hook usage in more locations. A diagnostic will now be generated if:

    • A hook is used at the module level (top of the file, outside any function).
    • A hook is used within a function or method which is not a hook or component, unless it is a function expression (such as arrow functions commonly used in tests).

    Invalid:

    // Invalid: hooks cannot be called at the module level.
    useHook();
    // Invalid: hooks must be called from another hook or component.
    function notAHook() {
    useHook();
    }

    Valid:

    // Valid: hooks may be called from function expressions, such as in tests.
    test("my hook", () => {
    renderHook(() => useHook());
    renderHook(function () {
    return useHook();
    });
    });
  • #8307 789b0e7 Thanks @mehm8128! - Added the useValidAriaRole lint rule for HTML. The rule enforces that elements with ARIA roles must use a valid, non-abstract ARIA role.

  • #8814 4d9c676 Thanks @Netail! - Added ignore option to noUnknownFunction. If an unknown function name matches any of the items provided in ignore, a diagnostic won’t be emitted.

  • #8814 4d9c676 Thanks @Netail! - Added ignore option to noUnknownPseudoClass. If an unknown pseudo-class name matches any of the items provided in ignore, a diagnostic won’t be emitted.

  • #8623 dc1f94e Thanks @mldangelo! - Added the noDuplicateClasses assist action to detect and remove duplicate CSS classes.

    For JSX files: Supports class, className attributes and utility functions like clsx, cn, cva.

    For HTML files: Checks class attributes. This is the first assist action for HTML.

    // Before
    <div class="flex p-4 flex" />;
    // After
    <div class="flex p-4" />;
  • #8399 ab88099 Thanks @ematipico! - Improved the CSS parser for CSS modules. Biome now automatically enables CSS modules parsing for *.module.css files.

    If your codebase has only *.module.css files, you can remove the parser feature as follows, because now Biome does it for you:

    {
    "css": {
    "parser": {
    "cssModules": true
    }
    }
    }
  • #8399 ab88099 Thanks @ematipico! - Added support for parsing :global and :local inside .astro, .svelte and .vue files, in <style> portion of the file.

    This capability is only available when experimentalFullHtmlSupportedEnabled is set to true.

  • #9011 e014336 Thanks @ematipico! - Promoted 21 nursery rules to stable groups.

    Correctness

    Promoted the following rules to the correctness group:

    • noUnresolvedImports. The rule reports imports that cannot be resolved. The default rule severity is set to error.
    • noVueReservedProps. The rule reports Vue reserved props usage. The default rule severity is set to error.
    • noVueReservedKeys. The rule reports Vue reserved keys usage. The default rule severity is set to error.
    • noVueDataObjectDeclaration. The rule reports Vue 2 data declared as an object instead of a function. The default rule severity is set to warn.
    • noNextAsyncClientComponent. The rule reports async Next.js client components. The default rule severity is set to warn.
    • noVueDuplicateKeys. The rule reports duplicate keys in Vue component options. The default rule severity is set to error.
    • noVueSetupPropsReactivityLoss. The rule reports destructuring of props in Vue 3 setup which causes reactivity loss. The default rule severity is set to error.
    • useQwikMethodUsage. The rule enforces correct Qwik framework method usage. The default rule severity is set to error.
    • useQwikValidLexicalScope. The rule enforces valid lexical scope in Qwik framework. The default rule severity is set to error.

    Suspicious

    Promoted the following rules to the suspicious group:

    • noImportCycles. The rule reports circular imports. The default rule severity is set to warn.
    • noDeprecatedImports. The rule reports imports of deprecated symbols. The default rule severity is set to warn.
    • noReactForwardRef. The rule reports usage of React.forwardRef. The default rule severity is set to warn.
    • noUnusedExpressions. The rule reports expressions that are never used. The default rule severity is set to warn.
    • noEmptySource. The rule reports empty source files. The default rule severity is set to warn.
    • useDeprecatedDate. The rule enforces use of GraphQL @deprecated directive with date. The default rule severity is set to warn.
    • noDuplicateDependencies. The rule reports duplicate dependencies in package.json. The default rule severity is set to warn.

    Complexity

    Promoted the following rules to the complexity group:

    • noUselessUndefined. The rule reports useless undefined initialization and returns. The default rule severity is set to info.
    • useMaxParams. The rule enforces a maximum number of function parameters. The default rule severity is set to warn.
    • noUselessCatchBinding. The rule reports useless catch binding parameters. The default rule severity is set to info.

    Style

    Promoted the following rules to the style group:

    • useConsistentArrowReturn. The rule enforces consistent return in arrow functions. The default rule severity is set to info.
    • noJsxLiterals. The rule reports literal strings in JSX. The default rule severity is set to info.
  • #8695 d8f0309 Thanks @ematipico! - Added support for the top-level suppression comment biome-ignore-all format: <explanation>.

    When the comment biome-ignore-all format: <explanation> is placed at the beginning of the document, Biome won’t format the code.

    The feature works for all supported languages. In the following JavaScript snippet, the code isn’t formatted and will stay as is.

    // biome-ignore-all format: generated
    const a = [];
    const a = [];
    const a = [];
  • #8255 da85e3c Thanks @ryan-m-walker! - Added support for the typed attr function. Addresses issue #6183.

    Example

    .btn {
    width: attr(data-size type(<length> | <percentage>), 0px);
    }
  • #8165 e0b3f62 Thanks @lucasweng! - Added the noAccessKey lint rule for HTML. The rule enforces that the accesskey attribute is not used on any HTML element, as it can conflict with keyboard commands used by screen readers and keyboard-only users.

    Invalid:

    <input type="submit" accesskey="s" value="Submit" />
    <a href="https://webaim.org/" accesskey="w">WebAIM.org</a>
    <button accesskey="n">Next</button>

    Valid:

    <input type="submit" value="Submit" />
    <a href="https://webaim.org/">WebAIM.org</a>
    <button>Next</button>
  • #8278 7207eff Thanks @ematipico! - Added a feature that allows editors to inject a Biome configuration to the Biome Language Server without affecting the configuration of the project.

    If you have a Biome extension that is compatible with your preferred LSP-ready editor, you can map inlineConfig. The configuration will be merged with the configuration of the project (or the default configuration):

    For example, with the Zed editor, you would have the following configuration, which will format all files using four spaces as indentation style:

    .zed/settings.json
    {
    lsp: {
    biome: {
    settings: {
    inline_config: {
    formatter: {
    indentStyle: "space",
    indentWidth: 4,
    },
    },
    },
    },
    },
    }
  • #8368 8aa5f5b Thanks @Bertie690! - Added 2 options from typescript-eslint (ignoreDifferentlyNamedParameters and ignoreDifferentJsDoc) to useUnifiedTypeSignatures.

    Each option makes the rule ignore overload signatures whose parameter names or JSDoc comments differ.

    Examples

    Valid code with ignoreDifferentlyNamedParameters set to true:

    function cook(scoops: IceCreamScoop[]): void;
    function cook(cakeType: string): void;

    Valid code with ignoreDifferentJsDoc set to true:

    /** Does objs have "cow" inside it? */
    function hasCow(objs: string[]): boolean;
    /** @deprecated - convert to array */
    function hasCow(objs: string): boolean;
  • #8562 361350e Thanks @dyc3! - Added the rule profiler behind the --profile-rules cli flag. You can now see a report of which lint rules took the longest to execute.

  • #8234 e2e6e66 Thanks @ongyuxing! - Updated the CSS properties ordering to align with stylelint-config-recess-order v7.4.0.

    It adds support for:

    • Containment properties
    • Font synthesis properties
    • Ruby properties
    • Color adjustment properties
    • View transitions properties
    • Shapes properties
    • Motion path properties
    • etc.

    For the complete list of changes, see: https://github.com/stormwarning/stylelint-config-recess-order/compare/v6.0.0…v7.4.0.

  • #8814 4d9c676 Thanks @Netail! - Added ignore option to noUnknownPseudoElement. If an unknown pseudo-element name matches any of the items provided in ignore, a diagnostic won’t be emitted.

  • #8663 3dfea16 Thanks @ematipico! - Added the ability to load the configuration from new known paths. Biome now attempts to load the configuration files from the following locations:

    • $XDG_CONFIG_HOME or $HOME/.config/biome on Linux
    • /Users/$USER/Library/Application Support/biome on macOS
    • C:\Users\$USER\AppData\Roaming\biome\config on Windows

    The priority how Biome will attempt to load the configuration files is the following:

    1. project folder (working directory)
    2. parent folders
    3. config home
      1. $XDG_CONFIG_HOME or $HOME/.config/biome on Linux
      2. /Users/$USER/Library/Application Support/biome on macOS
      3. C:\Users\$USER\AppData\Roaming\biome\config on Windows
  • #7973 bc0e8b4 Thanks @siketyan! - Added support for formatting and linting embedded CSS snippets in JavaScript.

    For example, the following snippets are now formatted and linted:

    import styled from "styled-components";
    const Foo = styled.div`
    display: flex;
    color: red;
    `;
    import styled from "@emotion/styled";
    const Foo = styled(Box)`
    display: flex;
    color: red;
    `;
    import { css } from "@emotion/react";
    const style = css`
    display: flex;
    color: red;
    `;

    However, snippets with interpolations are not supported yet. For example, the following snippet isn’t formatted:

    import styled from "@emotion/styled";
    const Foo = styled.div<{ color: string }>`
    display: flex;
    color: ${(props) => props.color};
    `;

    This feature is experimental and must be enabled explicitly in the configuration:

    {
    "javascript": {
    "experimentalEmbeddedSnippetsEnabled": true
    }
    }
  • #8381 50c3513 Thanks @mehm8128! - Added the useAriaPropsForRole lint rule for HTML. The rule enforces that elements with ARIA roles must have all required ARIA attributes for that role.

  • #7762 5901d79 Thanks @dyc3! - Added the extensionMappings option to useImportExtensions. This allows users to specify custom file extensions for different module types.

    For example, if you want to ban all .ts imports in favor of .js imports, you can now do so with this option:

    {
    "options": {
    "extensionMappings": {
    "ts": "js"
    }
    }
    }
  • #8532 01bccc8 Thanks @jonaylor89! - Added --only and --skip options to biome check and biome ci, covering both lint diagnostics and assist actions. Biome now lets you run or exclude specific lint rules, assist actions, group or rules and actions, or domains when running these commands.

    Examples:

    Terminal window
    biome check --only=suspicious/noDebugger src/**/*.js
    biome ci --skip=project src/**
  • #8666 7733f90 Thanks @ematipico! - Added the rule noRedundantAlt to HTML. The rule enforces that the img element alt attribute does not contain the words “image”, “picture”, or “photo”.

  • #8287 a248e88 Thanks @mehm8128! - Added the noDistractingElements lint rule for HTML. The rule enforces that no distracting elements like <marquee> or <blink> are used.

  • #8564 adcce82 Thanks @ematipico! - Added the new linter domain types. This is a domain that enables all rules that require the type inference engine.

    As opposed to the project domain, which only enables rules that require the module graph to function.

    The following nursery rules have been moved to the types domain:

    • useArraySortCompare
    • useAwaitThenable
    • useFind
    • useRegexpExec
    • noUnnecessaryConditions
    • noMisusedPromises
    • noFloatingPromises
  • #8556 47a79f1 Thanks @mehm8128! - Added two new behaviors to the noSvgWithoutTitle rule.

    • Support for graphics-document and graphics-symbol roles.
    • Support for multiple role specifications.
  • #8663 3dfea16 Thanks @ematipico! - Added the ability to load the hidden files .biome.json and .biome.jsonc. This is the order how Biome will attempt the configuration file is:

    1. biome.json
    2. biome.jsonc
    3. .biome.json
    4. .biome.jsonc
  • #8334 ae8ac8e Thanks @ematipico! - Added the formatter option trailingNewline.

    When set to false, the formatter will remove the trailing newline at the end of formatted files. The default value is true, which preserves the current behavior of adding a trailing newline.

    This option is available globally and for each language-specific formatter configuration:

    {
    "formatter": {
    "trailingNewline": false
    },
    "javascript": {
    "formatter": {
    "trailingNewline": true
    }
    }
    }

    The following CLI flags have been added. They accept true or false as value:

    • --formatter-trailing-newline
    • --javascript-formatter-trailing-newline
    • --json-formatter-trailing-newline
    • --graphql-formatter-trailing-newline
    • --css-formatter-trailing-newline
    • --html-formatter-trailing-newline
  • #8854 1469968 Thanks @ematipico! - Formatting is now applied when applying safe/unsafe fixes via biome check.

  • #8642 46f33a7 Thanks @ematipico! - Improved the rule noUnusedVariables in Svelte files, by correctly detecting variables defined in the JavaScript blocks, and used inside the templates.

  • #8839 79b38aa Thanks @ryan-m-walker! - Added support for parsing and formatting the CSS @function at-rule from the CSS Mixins Module Level 1 specification. Addresses issue #8184.

    @function --transparent(--color <color>, --alpha <number>: 0.5) returns
    <color> {
    result: oklch(from var(--color) l c h / var(--alpha));
    }
  • #8412 73f4f53 Thanks @mehm8128! - Added the noSvgWithoutTitle lint rule to HTML. The rule enforces the usage of the title element for the svg element.

  • #8243 4291ff3 Thanks @ashnewmanjones! - Added the useButtonType lint rule for HTML. The rule enforces that the type attribute is present and valid on all button elements.

    Invalid:

    <button>Do something</button>
    <button type="incorrectType">Do something</button>
    <button type>Do something</button>
    <button type />

    Valid:

    <button type="button">Do something</button>
    <button type="reset">Do something</button>
    <button type="submit" />

Patch Changes

  • #8898 7e48bd4 Thanks @ematipico! - Added e18e ESLint plugin as a recognized rule source. Six Biome rules now reference their e18e equivalents: useAtIndex, useExponentiationOperator, noPrototypeBuiltins, useDateNow, useSpread, and useObjectSpread.

  • #8719 a215408 Thanks @ematipico! - Added proper parsing and formatting for Svelte directives when the html.experimentalFullSupportEnabled is set to true.

  • #8071 7f5bcf4 Thanks @ematipico! - Revamped the logging options for all Biome commands. Now the commands format, lint, check, ci, search, lsp-proxy and start accept the following CLI options.

    Some options might have been present before, but they were inconsistent. Plus, all new options have an environment variable as aliases.

    --log-file

    Optional path/file to redirect log messages to. This option is applicable only to the CLI. If omitted, logs are printed to stdout.

    Environment variable alias: BIOME_LOG_FILE

    --log-prefix-name

    Allows changing the prefix applied to the file name of the logs. This option is applicable only to the daemon.

    Environment variable alias: BIOME_LOG_PREFIX_NAME

    --log-path

    Allows changing the folder where logs are stored. This option is applicable only to the daemon.

    Environment variable alias: BIOME_LOG_PATH

    --log-level

    The level of logging. In order, from the most verbose to the least verbose: debug, info, warn, error

    The value none won’t show any logging.

    Environment variable alias: BIOME_LOG_LEVEL

    --log-kind

    What the log should look like.

    Environment variable alias: BIOME_LOG_KIND

    Reduce dumping of LSP logs

    When you use a Biome editor extension, Biome’s Daemon dumps its logs using the debug level. If you want to reduce the quantity of these logs, you can now customize it:

    Terminal window
    BIOME_LOG_LEVEL=info biome lsp-proxy
  • #8663 3dfea16 Thanks @ematipico! - Fixed #901. Biome now allows trailing commas in inside Zed settings.json and VSCode settings.json.

  • #8669 683f50d Thanks @tt-a1i! - Fixed #8628: useComponentExportOnlyModules now allows components referenced as object property values in exported expressions. This fixes false positives for TanStack Router patterns.

    export const Route = createFileRoute('/')({
    component: HomeComponent,
    })
    function HomeComponent() { ... } // no longer reported as "should be exported"
  • #9060 0e47f5a Thanks @dyc3! - Fixed #9057: Incorrect diagnostic spans for suppression comments and other raw diagnostics in HTML-ish files (Vue, Svelte, Astro). Previously, diagnostics like “unused suppression” pointed to the wrong location in the document due to the diagnostic offset not being applied.

  • #9028 5ac2ad6 Thanks @LouisLau-art! - Fixed #9024: Biome no longer reports <hr role="presentation"> under noInteractiveElementToNoninteractiveRole.

  • #9072 8656fc0 Thanks @dyc3! - Fixed #9068: The noVueDuplicateKeys rule now correctly handles toRefs(props) patterns and no longer produces false positives when destructuring props, particularly in <script setup> blocks.

  • #9049 c0ab6dd Thanks @ematipico! - Fixed #7138. Now the Biome language server correctly handles the configurationPath setting coming from the editor extension.

  • #8556 47a79f1 Thanks @mehm8128! - Fixed the noSvgWithoutTitle rule not to recursively traverse title elements.

  • #8894 6bf1b09 Thanks @ematipico! - Added proper parsing for spread attributes {...props} in Svelte and Astro files.

  • #8833 375792e Thanks @dyc3! - Fixed #4927, #6407: The HTML formatter will now correctly break a block-like element if it has more than 2 children, and at least one of them is another block-like element.

    <div>a<div>b</div> c</div>
    <div>
    a
    <div>b</div>
    c
    </div>
  • #8854 1469968 Thanks @ematipico! - Fixed #7912, where Biome incorrectly added a leading newline to the code contained inside the Astro frontmatter.

  • #8806 cb112ce Thanks @dyc3! - Major Breaking Changes to the HTML formatter only

    The HTML formatter (which is still experimental) has been completely overhauled from the ground up to more closely resemble Prettier’s formatting. If you have opted in to the HTML formatter, you may see large formatting diffs for your HTML, Vue, Svelte, and Astro files.

    This overhaul fixes several issues (#5150, #6625, #8437) around whitespace sensitivity that were causing incorrect formatting in certain scenarios that were difficult or impossible to fully address before.

  • #8700 0f5a05b Thanks @ematipico! - Improved the rules useConst, noUnusedImports, useImportTypes and noUnusedVariables inside Vue, Svelte and Astro files when experimentalFullSupportEnabled is set to true.

    Now variables and components that are imported or defined inside the files won’t trigger false positives.

    Until now, we suggested disabling these rules with an override. Now the rules are more stable; however, you might still experience a few false positives. Those are probably issues caused by our parser.

    If you use experimentalFullSupportEnabled, you can remove the following override:

    {
    "overrides": [
    {
    "includes": ["**/*.svelte", "**/*.astro", "**/*.vue"],
    "linter": {
    "rules": {
    "style": {
    "useConst": "off",
    "useImportType": "off"
    },
    "correctness": {
    "noUnusedVariables": "off",
    "noUnusedImports": "off"
    }
    }
    }
    }
    ]
    }
  • #8485 bf02ba6 Thanks @ematipico! - Fixed an issue where some info diagnostics weren’t tracked by the final summary.

  • #8846 5701ead Thanks @dyc3! - Fixed #8692: Biome now accepts Vue’s v-bind() function in CSS when Vue CSS modules parsing is enabled.

  • #9012 18cdd45 Thanks @kiroushi! - Fixed plugin diagnostics showing incorrect line numbers in Vue, Astro, and Svelte files. Plugin diagnostics now correctly account for the template/frontmatter offset, pointing to the right location in the <script> block.

2.3.15

Patch Changes

  • #9019 043b67c Thanks @dyc3! - Added the lint rule noNestedPromises. This rule detects nested .then() or .catch() calls that could be refactored into flat promise chains.

    // Invalid: nested promise that can be flattened
    doThing().then(function () {
    return doOtherThing().then(console.log);
    });
    // Valid: flat promise chain
    doThing()
    .then(() => doOtherThing())
    .then(console.log);

    The rule intelligently allows nesting when the inner callback references variables from the outer scope, as these cases cannot be safely flattened.

  • #9029 6ebf6c6 Thanks @ff1451! - Added the nursery rule noUselessReturn. The rule reports redundant return; statements that don’t affect the function’s control flow.

    // Invalid: return at end of function is redundant
    function foo() {
    doSomething();
    return;
    }
  • #9017 8bac2da Thanks @mdevils! - Reverted a behavior change in useExhaustiveDependencies that was accidentally included as part of the #8802 fix. The change made method calls on objects (e.g., props.data.forEach(...)) report only the object (props.data) as a missing dependency instead of the full member expression. This behavior change will be reconsidered separately.

  • #9005 c8dbbbe Thanks @corvid-agent! - Fixed #8790: The noAssignInExpressions rule no longer reports a false positive when an assignment is used as the expression body of an arrow function (e.g., const f = b => a += b).

  • #8519 ccdc602 Thanks @ruidosujeira! - Fixed #8518, where globally excluded files in a monorepo were still being processed when using "extends": "//".

    When a package-level configuration extends the root configuration with "extends": "//", glob patterns (such as those in files.includes) are now correctly resolved relative to the project root directory, instead of the current workspace directory.

  • #9033 0628e0a Thanks @mdevils! - Fixed #8967. useExhaustiveDependencies no longer reports false positives for variables destructured from a rest pattern.

  • #9023 8ef9d1d Thanks @siketyan! - Fixed #9020: When javascript.jsxRuntime is set to reactClassic, noUnusedImports and useImportType rules now allow importing the React identifier from a package other than react. This aligns the behavior with tsc (--jsx=react), which also allows importing React from any package.

  • #8646 16fd71d Thanks @siketyan! - Fixed #8605: Text expressions in some template languages ({{ expr }} or { expr }) at the top level of an HTML document no longer causes panicking.

  • #8930 51c158e Thanks @ANKANJAGTAP! - Fixed #8917 useExhaustiveDependencies now correctly detects JSX component identifiers as hook dependencies.

  • #9009 7d229c7 Thanks @Netail! - Fixed typo in noPositiveTabindex’s quick fix text.

  • #8758 8c789f1 Thanks @Pranav2612000! - Updated the useJsxKeyInIterable rule to not run inside Map constructors

  • #8977 bbe0e0c Thanks @FrankFMY! - Fixed #4888. noUnusedImports now adds export {} when removing the last import in a TypeScript file to prevent it from becoming an ambient module. This does not apply to embedded scripts in Vue, Svelte, or Astro files, which are already in a module context.

  • #9016 9d4cfa3 Thanks @dyc3! - Added eslint migration metadata for the rules @typescript/no-var-requires, @typescript/keyword-spacing, @typescript/func-call-spacing, vue/keyword-spacing, vue/func-call-spacing, and unicorn/empty-brace-spaces,

  • #8848 2cba2b3 Thanks @LouisLau-art! - Fixed #8845. Now useGenericFontNames doesn’t trigger when font is declared inside the @supports at-rule.

  • #8997 a5f3212 Thanks @mldangelo! - Fixed #8476. useAwaitThenable no longer reports false positives for await on call expressions whose return type cannot be resolved (e.g., cross-module function calls to Node.js builtins or npm packages).

  • #8978 cc7a478 Thanks @FrankFMY! - Fixed #8645. useAwait no longer reports async generator functions that use yield*, since yield* in an async generator delegates to an AsyncIterable and requires the async modifier.

2.3.14

Patch Changes

  • #8921 29e2435 Thanks @siketyan! - Fixed #8759: The useConsistentTypeDefinitions rule no longer converts empty object type declarations into interfaces, as it will conflict with the noEmptyInterface rule and can cause an infinite loop when both rules are enabled.

  • #8928 ccaeac4 Thanks @taga3s! - Added the nursery rule useGlobalThis. This rule enforces using globalThis over window, self and global.

  • #8602 9a18daa Thanks @dyc3! - Added the new nursery rule noVueArrowFuncInWatch. This rule forbids using arrow functions in watchers in Vue components, because arrow functions do not give access to the component instance (via this), while regular functions do.

  • #8905 9b1eea8 Thanks @ryan-m-walker! - Fixed #8428: Improved parsing recovery when encountering qualified rules inside CSS @page at-rule blocks.

  • #8900 f788cff Thanks @mdevils! - Fixed #8802: useExhaustiveDependencies now correctly suggests dependencies without including callback-scoped variables or method names.

    When accessing object properties with a callback-scoped variable, only the object path is suggested:

    // Now correctly suggests `props.value` instead of `props.value[day]`
    useMemo(() => {
    return WeekdayValues.filter((day) => props.value[day]);
    }, [props.value]);

    When calling methods on objects, only the object is suggested as a dependency:

    // Now correctly suggests `props.data` instead of `props.data.forEach`
    useMemo(() => {
    props.data.forEach((item) => console.log(item));
    }, [props.data]);
  • #8913 e1e20ea Thanks @dyc3! - Fixed #8363: HTML parser no longer crashes when encountering a < character followed by a digit in text content (e.g., <12 months). The parser now correctly emits an “Unescaped < bracket character” error instead of treating <12 as a tag name and crashing.

  • #8910 2fb63a4 Thanks @dyc3! - Fixed #8774: Type aliases with generic parameters that have extends constraints now properly indent comments after the equals sign.

    Previously, comments after the = in type aliases with extends constraints were not indented:

    type A<B, C extends D> = // Some comment
    undefined;
    type A<B, C extends D> =
    // Some comment
    undefined;
  • #8916 ea4bd04 Thanks @ryan-m-walker! - Fixed #4013, where comments in member chains caused unnecessary line breaks.

    // Before
    aFunction.b().c.d();
    // After
    aFunction.b().c.d();
  • #8945 fa66fe3 Thanks @fireairforce! - Fixed #8354: Don’t remove quotes when type memeber is new.

    // Input:
    type X = {
    "new"(): string;
    "foo"(): string;
    };
    // Format Output:
    type X = {
    "new()": string;
    foo(): string;
    };
  • #8927 0ef3da5 Thanks @littleKitchen! - Fixed #8907: useExhaustiveDependencies now correctly recognizes stable hook results (like useState setters and useRef values) when declared with let.

  • #8931 4561751 Thanks @koshin01! - Added the new nursery rule noRedundantDefaultExport, which flags redundant default exports where the default export references the same identifier as a named export.

  • #8900 f788cff Thanks @mdevils! - Fixed #8883: useExhaustiveDependencies no longer produces false positives when props are destructured in the function body of arrow function components without parentheses around the parameter.

    type Props = { msg: string };
    // Arrow function without parentheses around `props`
    const Component: React.FC<Props> = (props) => {
    const { msg } = props;
    // Previously, this incorrectly reported `msg` as unnecessary
    useEffect(() => console.log(msg), [msg]);
    };
  • #8861 3531687 Thanks @dyc3! - Added the noDeprecatedMediaType CSS rule to flag deprecated media types like tv and handheld.

  • #8775 7ea71cd Thanks @igas! - Fixed the noUnnecessararyConditions rule to prevent trigger for optional fallback patterns.

  • #8860 95f1eea Thanks @dyc3! - Added the nursery rule noHexColors, which flags the use of hexadecimal color codes in CSS and suggests using named colors or RGB/RGBA/HSL/HSLA formats instead.

  • #8786 d876a38 Thanks @Bertie690! - Added the nursery rule useConsistentMethodSignatures.
    Inspired by the similarly named version from typescript-eslint, this rule aims to enforce a consistent style for methods used inside object types and interfaces.

    Examples

    Invalid code with style set to "property" (the default):

    interface Foo {
    method(a: string): void;
    }

    Invalid code with style set to "method":

    type Bar = {
    prop: (a: string) => void;
    }
  • #8864 5e97119 Thanks @dyc3! - Improved the summary provided by biome migrate eslint to be clearer on why rules were not migrated. Biome now specifies a reason when a rule is not migrated, such as being incompatible with the formatter or not implemented yet. This helps users make more informed decisions when migrating their ESLint configurations to Biome.

  • #8924 99b4cd1 Thanks @tmohammad78! - Fixed #8920: noUnknownFunction now knows about sibling-count, and sibling-index css functions

  • #8900 f788cff Thanks @mdevils! - Fixed #8885: useExhaustiveDependencies no longer incorrectly reports variables as unnecessary dependencies when they are derived from expressions containing post/pre-increment operators (++/--) or compound assignment operators (+=, -=, etc.).

    let renderCount = 0;
    export const MyComponent = () => {
    // `count` is now correctly recognized as a required dependency
    // because `renderCount++` can produce different values between renders
    const count = renderCount++;
    useEffect(() => {
    console.log(count);
    }, [count]); // no longer reports `count` as unnecessary
    };
  • #8619 d78e01d Thanks @Netail! - Added the nursery rule useInputName. Require mutation arguments to be called “input”, and the input type to be called Mutation name + “Input”.

    Invalid:

    type Mutation {
    SetMessage(message: String): String
    }
  • #8922 871b45e Thanks @siketyan! - Fixed #8829: Revamped the noGlobalDirnameFilename rule to catch many false negatives that have not been reported.

2.3.13

Patch Changes

  • #8815 f924f23 Thanks @dyc3! - Improved useVueValidVOn to be more closely aligned with the source rule. It will now properly allow modifiers for all possible keyboard events. It should have better performance when there are no violations of the rule as well.

    Now treated valid:

    <div @keydown.arrow-down="handler"></div>
    <div @keydown.a="handler"></div>
    <div @keydown.b="handler"></div>
    <div @keydown.27="foo"></div>
  • #8856 85f81f9 Thanks @dyc3! - Fixed #8710: Biome now parses Vue dynamic slot shorthand arguments that use template literals in [].

  • #8850 2a190e0 Thanks @dyc3! - Fixed #8708: Tailwind @utility directives now parse functional utility names like px-* when Tailwind directives are enabled.

  • #8863 79386e0 Thanks @dyc3! - Fixed an issue with biome migrate eslint where it couldn’t detect rules for CSS, GraphQL, and HTML.

  • #8771 6f56b6e Thanks @lghuahua! - Fix the --reporter=summary output incorrectly merging and displaying wrong issue counts for different rules. Fixes #8730

  • #8714 ac3a71f Thanks @Netail! - Added new nursery rule use-consistent-enum-value-type. This rule disallows enums from having both number and string members.

2.3.12

Patch Changes

  • #8653 047576d Thanks @dyc3! - Added new nursery rule noDuplicateAttributes to forbid duplicate attributes in HTML elements.

  • #8648 96d09f4 Thanks @BaeSeokJae! - Added a new nursery rule noVueOptionsApi.

    Biome now reports Vue Options API usage, which is incompatible with Vue 3.6’s Vapor Mode. This rule detects Options API patterns in <script> blocks, defineComponent(), and createApp() calls, helping prepare codebases for Vapor Mode adoption.

    For example, the following now triggers this rule:

    <script>
    export default {
    data() {
    return { count: 0 };
    },
    };
    </script>
  • #8832 b08270b Thanks @Exudev! - Fixed #8809, #7985, and #8136: the noSecrets rule no longer reports false positives on common CamelCase identifiers like paddingBottom, backgroundColor, unhandledRejection, uncaughtException, and IngestGatewayLogGroup.

    The entropy calculation algorithm now uses “average run length” to distinguish between legitimate CamelCase patterns (which have longer runs of same-case letters) and suspicious alternating case patterns (which have short runs).

  • #8793 c19fb0e Thanks @TheBaconWizard! - Properly handle parameters metavariables for arrow_function GritQL queries. The following biome search command no longer throws an error:

    Terminal window
    biome search 'arrow_function(parameters=$parameters, body=$body)'
  • #8561 981affb Thanks @wataryooou! - Fixed noUnusedVariables to ignore type parameters declared in ambient contexts such as declare module blocks.

  • #8817 652cfbb Thanks @dyc3! - Fixed #8765: The HTML parser can now parse directive modifiers with a single colon, e.g. @keydown.:.

  • #8704 a1914d4 Thanks @Netail! - Added the nursery rule noRootType. Disallow the usage of specified root types. (e.g. mutation and/or subscription)

    Invalid:

    {
    "options": {
    "disallow": ["mutation"]
    }
    }
    type Mutation {
    SetMessage(message: String): String
    }
  • #8712 251b47b Thanks @Netail! - Renamed the following GraphQL nursery rules to match the Biome standard:

    • useUniqueArgumentNames -> noDuplicateArgumentNames
    • useUniqueFieldDefinitionNames -> noDuplicateFieldDefinitionNames
    • useUniqueGraphqlOperationName -> noDuplicateGraphqlOperationName
    • useUniqueInputFieldNames -> noDuplicateInputFieldNames
    • useUniqueVariableNames -> noDuplicateVariableNames

    Run the biome migrate --write command to automatically update the configuration file.

  • #7602 957cd8e Thanks @kedevked! - Added the nursery lint rule useErrorCause.

    This rule enforces that errors caught in a catch clause are not rethrown without wrapping them in a new Error object and specifying the original error as the cause. This helps preserve the error’s stack trace and context for better debugging.

    It can be configured with the following option:

    • requireCatchParameter: (default: true)
      • When true, the rule requires that catch clauses have a parameter. If a throw statement appears inside a catch clause without a parameter, it will be flagged.

    Invalid examples:

    try {
    foo();
    } catch {
    throw new Error("fail");
    }
    try {
    foo();
    } catch (err) {
    throw new Error(err.message);
    }

    Valid examples:

    try {
    foo();
    } catch (err) {
    throw new Error("fail", { cause: err });
    }
    try {
    foo();
    } catch (error) {
    throw new Error("Something went wrong", { cause: error });
    }

    Valid example when requireCatchParameter is false:

    Valid:

    try {
    foo();
    } catch {
    throw new Error("fail");
    }
  • #8725 95aba98 Thanks @dyc3! - Fixed #8715: The CSS parser will now recover slightly better if a semicolon is missing from Tailwind’s @apply at-rule.

  • #8616 4ee3bda Thanks @Netail! - Added the nursery rule useLoneAnonymousOperation. Disallow anonymous operations when more than one operation specified in document.

    Invalid:

    query {
    fieldA
    }
    query B {
    fieldB
    }
  • #8624 291c9f2 Thanks @taga3s! - Added the nursery rule useInlineScriptId to the Next.js domain. This rule enforces id attribute on next/script components with inline content or dangerouslySetInnerHTML.

    The following code is invalid:

    import Script from "next/script";
    export default function Page() {
    return (
    <Script>{`console.log('Hello');`}</Script> // must have `id` attribute
    );
    }
  • #8767 0d15370 Thanks @mdevils! - Fixed #3512: useExhaustiveDependencies now properly handles nested destructuring patterns from hook results.

    const [[x, y], setXY] = useState([1, 2]);
    useEffect(() => {
    console.log(x, y);
    }, [x, y]); // x and y are now correctly recognized as unstable
  • #8757 17ed9d3 Thanks @Netail! - Added the nursery rule noDivRegex. Disallow equal signs explicitly at the beginning of regular expressions.

    Invalid:

    var f = function () {
    return /=foo/;
    };
  • #8836 aab1d17 Thanks @dyc3! - Fixed #7858: Biome now parses Astro files with empty frontmatter blocks.

  • #8755 3a15c29 Thanks @arturalkaim! - Fixed #6670. The $filename metavariable can now be used in GritQL where clauses to filter matches by filename.

  • #8821 63e68a1 Thanks @playhardgopro! - Fixed several bugs in Vue conditional rules (useVueValidVIf, useVueValidVElse, and useVueValidVElseIf) related to whitespace handling, newlines, and self-closing tags.

  • #8767 0d15370 Thanks @mdevils! - Fixed #3685: useExhaustiveDependencies now properly handles transparent expression wrappers like non-null assertions and type assertions in dependency comparisons.

    useMemo(() => Boolean(myObj!.x), [myObj!.x]); // No longer reports incorrect diagnostics
    useMemo(() => myObj!.x?.y === true, [myObj!.x?.y]); // Now correctly matches dependencies
  • #8597 f764007 Thanks @Netail! - Added the nursery rule noDuplicateEnumValueNames. Enforce unique enum value names.

    Invalid:

    enum A {
    TEST
    TesT
    }
  • #8679 33dfd7c Thanks @ematipico! - Fixed #8678. Now Biome correctly parses components inside Vue, Svelte and Astro files when they have the same name of self-closing elements.

  • #8617 31a9bfe Thanks @Netail! - Added the nursery rule useLoneExecutableDefinition. Require queries, mutations, subscriptions or fragments to be located in separate files.

    Invalid:

    query Foo {
    id
    }
    fragment Bar on Baz {
    id
    }
  • #8697 8519669 Thanks @Faizanq! - Added the nursery lint rule noExcessiveLinesPerFile to CSS and GraphQL.

  • #8711 365f7aa Thanks @Netail! - Added new nursery rule noDuplicateEnumValues, which disallows defining an enum with multiple members initialized to the same value.

  • #8767 0d15370 Thanks @mdevils! - Fixed #5914: useExhaustiveDependencies now properly handles variables declared in the same statement.

    const varA = Math.random(),
    varB = useMemo(() => varA, [varA]); // varA is now correctly recognized as needed
  • #8767 0d15370 Thanks @mdevils! - Fixed #8427: useExhaustiveDependencies now properly resolves variable references to detect captured dependencies.

    const fe = fetchEntity;
    useEffect(() => {
    fe(id);
    }, [id, fe]); // fe is now correctly detected as needed
  • #8767 0d15370 Thanks @mdevils! - Fixed #8484: useExhaustiveDependencies now properly handles member access on stable hook results.

    const stableObj = useStable();
    useMemo(() => {
    return stableObj.stableValue; // stableObj.stableValue is now correctly recognized as stable
    }, []);
  • #8767 0d15370 Thanks @mdevils! - Fixed #7982: useExhaustiveDependencies now properly handles callback expressions with type assertions.

    const callback = useCallback(
    (() => {
    return count * 2;
    }) as Function,
    [count], // count is now correctly detected
    );
  • #8766 39eb545 Thanks @Netail! - Fixed #8761: Reverted wrapping the URL of rule descriptions with <>, causing broken URLs in VSCode.

  • #8767 0d15370 Thanks @mdevils! - Fixed #3080: useExhaustiveDependencies now properly analyzes captures within referenced functions passed to hooks.

    function myEffect() {
    console.log(foo, bar);
    }
    useEffect(myEffect, [foo, bar]); // foo and bar are now correctly detected
  • #8740 4962ed0 Thanks @Netail! - Extra rule source references. biome migrate eslint should do a bit better detecting rules in your eslint configurations.

  • #8776 395746f Thanks @codiini! - Fixed #6003: noUselessUndefinedInitialization no longer reports exported variables initialized to undefined. In Svelte 4, this pattern is used to declare optional component props.

  • #8767 0d15370 Thanks @mdevils! - Fixed #4248: useExhaustiveDependencies now correctly handles function props passed as callbacks.

    const data = React.useMemo(getData, [getData]); // getData is now correctly recognized as needed
  • #8819 bc191ff Thanks @Netail! - Fixed #6567: noUnknownProperty now ignores unknown properties in at-rules which support descriptors.

  • #8787 adb652f Thanks @tuyuritio! - Fixed #8777: Add support for :active-view-transition pseudo-class.

  • #8639 6577e32 Thanks @ohnoah! - Added the nursery lint rule noExcessiveLinesPerFile. Biome now reports files that exceed a configurable line limit.

    // maxLines: 2
    const a = 1;
    const b = 2;
    const c = 3;
  • #8753 71b5c6e Thanks @Netail! - Added the nursery rule noExcessiveClassesPerFile. Enforce a maximum number of classes per file.

    Invalid:

    class Foo {}
    class Bar {}
  • #8754 d6b2bda Thanks @Netail! - Added the nursery rule noFloatingClasses. Disallow new operators outside of assignments or comparisons.

    Invalid:

    new Date();

2.3.11

Patch Changes

  • #8583 83be210 Thanks @dyc3! - Added the new nursery rule useVueValidTemplateRoot.

    This rule validates only root-level <template> elements in Vue single-file components. If the <template> has a src attribute, it must be empty. Otherwise, it must contain content.

    Invalid examples:

    <template src="./foo.html">content</template>
    <template></template>

    Valid examples:

    <template>content</template>
    <template src="./foo.html"></template>
  • #8586 df8fe06 Thanks @dyc3! - Added a new nursery rule useVueConsistentVBindStyle. Enforces consistent v-bind style (:prop shorthand vs v-bind:prop longhand). Default prefers shorthand; configurable via rule options.

  • #8587 9a8c98d Thanks @dyc3! - Added the rule useVueVForKey, which enforces that any element using v-for also specifies a key.

    Invalid

    <li v-for="item in items">{{ item }}</li>

    Valid

    <li v-for="item in items" :key="item.id">{{ item }}</li>
  • #8586 df8fe06 Thanks @dyc3! - Added a new nursery rule useVueConsistentVOnStyle. Enforces consistent v-on style (@event shorthand vs v-on:event longhand). Default prefers shorthand; configurable via rule options.

  • #8583 83be210 Thanks @dyc3! - Added the new nursery rule useVueValidVOnce. Enforces that usages of the v-once directive in Vue.js SFC are valid.

    <!-- Valid -->
    <div v-once />
    <!-- Invalid -->
    <div v-once:aaa />
    <div v-once.bbb />
    <div v-once="ccc" />
  • #8498 d80fa41 Thanks @tt-a1i! - Fixed #8494. Extended noUndeclaredEnvVars to support bracket notation (process.env["VAR"], import.meta.env["VAR"]), Bun runtime (Bun.env.VAR, Bun.env["VAR"]), and Deno runtime (Deno.env.get("VAR")).

  • #8509 574a909 Thanks @ematipico! - Added support for parsing and formatting the Svelte {#await} syntax, when html.experimentalFullSupportEnabled is set to true.

    {#await promise then name }
    {#await promise then name}
    {:catch name}
    {:catch name}
    {/await}
  • #8316 d64e92d Thanks @washbin! - Added the new nursery rule noMultiAssign. This rule helps to prevent multiple chained assignments.

    For example, the following code triggers because there are two assignment expressions in the same statement.

    const a = (b = 0);
  • #8592 a5f59cd Thanks @Netail! - Added the nursery rule useUniqueInputFieldNames. Require fields within an input object to be unique.

    Invalid:

    query A($x: Int, $x: Int) {
    field
    }
  • #8524 17a6156 Thanks @JacquesLeupin! - Fixed #8488: Relative plugin paths are now resolved from the configuration file directory, including when configurations are merged (e.g. extends: "//").

  • #8655 3260ec9 Thanks @JacquesLeupin! - Fixed #8636: Biome’s CSS formatter now breaks comma-separated declaration values at top-level commas when wrapping.

  • #8537 cc3e851 Thanks @dibashthapa! - Fixed #8491: Resolved false positive errors for safe boolean expressions. There are still pending fixes. Head to #8491 (comment) for more details

    This new change will check for safe boolean expressions in variable declarations.

    For example,

    Valid:

    let isOne = 1;
    let isPositiveNumber = number > 0;
    return (
    <div>
    {" "}
    {isOne && "One"} {isPositiveNumber && "Is positive"}
    </div>
    );

    Invalid:

    let emptyStr = "";
    let isZero = 0;
    return (
    <div>
    {emptyStr && "Empty String"} {isZero && "Number is zero"}{" "}
    </div>
    );
  • #8511 16a9036 Thanks @ematipico! - Improved the diagnostics of the rules useSortedClasses and noUnnecessaryConditions. The diagnostics now state that these rules are a work in progress and link to the relevant GitHub issue.

  • #8521 a704be9 Thanks @ToBinio! - Added the nursery rule useVueConsistentDefinePropsDeclaration, which enforces consistent defineProps declaration style.

    Invalid

    <script setup lang="ts">
    const props = defineProps({
    kind: { type: String },
    });
    </script>

    Valid

    <script setup lang="ts">
    const props = defineProps<{
    kind: string;
    }>();
    </script>
  • #8595 7c85bf0 Thanks @dyc3! - Fixed #8584: The HTML formatter will preserve whitespace after some elements and embedded expressions, which more closely aligns with Prettier’s behavior.

    <h1>Hello, {framework}and Svelte!</h1>
    <h1>Hello, {framework} and Svelte!</h1>
  • #8598 5e85d43 Thanks @Netail! - Added the nursery rule useUniqueFieldDefinitionNames. Require all fields of a type to be unique.

    Invalid:

    type SomeObject {
    foo: String
    foo: String
    }
  • #8495 b573d14 Thanks @taga3s! - Fixed #8405: noMisusedPromises now emits warnings/errors when a function returns union types such as T | Promise<T> which is used in conditionals.

    const a = (): boolean | Promise<boolean> => Promise.resolve(true);
    if (a()) {
    } // Now correctly flagged
  • #8632 0be7d12 Thanks @Bertie690! - The documentation & rule sources for lint/complexity/noBannedTypes have been updated to fix a few oversights.

    In addition to some general typo fixes:

    • The rule now recommends Record<keyof any, never> instead of Record<string, never> (the latter of which incorrectly allows symbol-keyed properties).

    • The rule mentions an alternate method to enforce object emptiness involving unique symbol-based guards used by type-fest and many other packages:

      declare const mySym: unique symbol;
      // Since this type's only property is an unexported `unique symbol`, nothing that imports it can specify any properties directly
      // (as far as excess property checks go)
      export type EmptyObject = { [mySym]?: never };
      export type IsEmptyObject<T> = T extends EmptyObject ? true : false;

    The rule’s listed sources have been updated as well to reflect the original source rule (ban-types) having been split into 3 separate rules circa April 2024.

  • #8580 a3a1ad2 Thanks @taga3s! - Added the nursery rule noBeforeInteractiveScriptOutsideDocument to the Next.js domain. This rule prevents usage of next/script’s beforeInteractive strategy outside of pages/_document.js.

  • #8493 5fc24f4 Thanks @ematipico! - Added support for parsing and formatting the Svelte {#each} syntax, when html.experimentalFullSupportEnabled is set to true.

    {#each items as item }
    {#each items as item}
    {/each}
  • #8546 0196c0e Thanks @Zaczero! - Hardened union static-member type flattening in edge cases (e.g. unions containing unknown or inferred expression types). This keeps inference conservative and avoids unstable type growth in node = node.parent-style loops.

  • #8569 1022c76 Thanks @ematipico! - Fixed an issue where the Biome HTML parser would emit a parse error when certain keywords are inside the text of HTML tags.

  • #8606 f50723b Thanks @dyc3! - Fixed #8563: fixed a bounds check on bogus regex literals that caused panics when doing type inference

  • #7410 ab9af9a Thanks @sgarcialaguna! - Added the new nursery rule noJsxPropsBind. This rule disallows .bind(), arrow functions, or function expressions in JSX props.

    Invalid:

    <Foo onClick={() => console.log("Hello!")}></Foo>
  • #8523 5f22f1c Thanks @ematipico! - Improved the diagnostics of nursery rules. Added a message to diagnostics emitted by nursery rules, so that users are aware of nature of nursery rules.

  • #8571 03666fd Thanks @dyc3! - Improved the performance of noRedeclare by eliminating string allocations

  • #8591 9dd9ca7 Thanks @Netail! - Added the nursery rule useUniqueArgumentNames. Enforce unique arguments for GraphQL fields & directives.

    Invalid:

    query {
    field(arg1: "value", arg1: "value")
    }
  • #8521 a704be9 Thanks @ToBinio! - Update useVueDefineMacrosOrder to only run on

  • #8344 7b982ba Thanks @ematipico! - Reduced the system calls when running the CLI. The performances might be noticeable in big projects that have multiple libraries and enable project rules.

  • #8588 958e24b Thanks @Netail! - Added the nursery rule useUniqueVariableNames. Enforce unique variable names for GraphQL operations.

    Invalid:

    query ($x: Int, $x: Int) {
    field
    }
  • #8529 8794883 Thanks @mdevils! - Fixed #8499: useExhaustiveDependencies properly handles aliased destructured object keys when using stableResult configuration.

  • #8557 4df2f4d Thanks @dyc3! - Fixed an issue with the HTML formatter where it wouldn’t add a space before the /> in self closing elements. This brings the HTML formatter more in line with Prettier.

    <Component/>
    <Component />
  • #8509 574a909 Thanks @ematipico! - Added support for parsing and formatting the Svelte {#snippet} syntax, when html.experimentalFullSupportEnabled is set to true.

    {#snippet foo() }
    {#snippet foo()}
    {/snippe}
  • #8248 1231a5c Thanks @emilyinure! - Added new nursery rule noReturnAssign, which disallows assignments inside return statements.

    Invalid:

    function f(a) {
    return (a = 1);
    }
  • #8531 6b09620 Thanks @taga3s! - Fixed #8472: The CSS parser can now accept multiple comma separated parameters in :active-view-transition-type.

  • #8615 b9da66d Thanks @taga3s! - Remove next/script component name check from noBeforeInteractiveScriptOutsideDocument since it is a default export.

  • #8536 efbfbe2 Thanks @dyc3! - Fixed #8527: Improved type inference where analyzing code with repeated object property access and assignments (e.g. node = node.parent, a pattern common when traversing trees in a while loop) could hit an internal type limit. Biome now handles these cases without exceeding the type limit.

  • #8583 83be210 Thanks @dyc3! - Added the new nursery rule useVueValidVCloak. Enforces that usages of the v-cloak directive in Vue.js SFC are valid.

    <!-- Valid -->
    <div v-cloak />
    <!-- Invalid -->
    <div v-cloak:aaa />
    <div v-cloak.bbb />
    <div v-cloak="ccc" />
  • #8583 83be210 Thanks @dyc3! - Added the new nursery rule useVueValidVPre. Enforces that usages of the v-pre directive in Vue.js SFC are valid.

    <!-- Valid -->
    <div v-pre />
    <!-- Invalid -->
    <div v-pre:aaa />
    <div v-pre.bbb />
    <div v-pre="ccc" />
  • #8644 a3a27a7 Thanks @JacquesLeupin! - Added the nursery rule useVueVapor to enforce <script setup vapor> in Vue SFCs. For example <script setup> is invalid.

  • #8508 b86842c Thanks @tt-a1i! - Fixed #6783: now, when a path is provided via --stdin-file-path, Biome checks whether the file exists on disk. If the path doesn’t exist (virtual path), ignore checks (files.includes and VCS ignore rules) are skipped.

2.3.10

Patch Changes

  • #8417 c3a2557 Thanks @taga3s! - Fixed #7809: noRedeclare no longer reports redeclarations for infer type in conditional types.

  • #8477 90e8684 Thanks @dyc3! - Fixed #8475: fixed a regression in how noExtraNonNullAssertion flags extra non-null assertions

  • #8479 250b519 Thanks @dyc3! - Fixed #8473: The semantic model now indexes typescript constructor method definitions, and no longer panics if you use one (a regression in 2.3.9).

  • #8448 2af85c1 Thanks @mdevils! - Improved handling of defineProps() macro in Vue components. The noVueReservedKeys rule now avoids false positives in non-setup scripts.

  • #8420 42033b0 Thanks @vsn4ik! - Fixed the nursery rule noLeakedRender.

    The biome migrate eslint command now correctly detects the rule react/jsx-no-leaked-render in your eslint configurations.

  • #8426 285d932 Thanks @anthonyshew! - Added a Turborepo domain and a new “noUndeclaredEnvVars” rule in it for warning users of unsafe environment variable usage in Turborepos.

  • #8410 a21db74 Thanks @ematipico! - Fixed #2988 where Biome couldn’t handle properly characters that contain multiple code points when running in stdin mode.

  • #8372 b352ee4 Thanks @Netail! - Added the nursery rule noAmbiguousAnchorText, which disallows ambiguous anchor descriptions.

    Invalid

    <a>learn more</a>

2.3.9

Patch Changes

  • #8232 84c9e08 Thanks @ruidosujeira! - Added the nursery rule noScriptUrl.

    This rule disallows the use of javascript: URLs, which are considered a form of eval and can pose security risks such as XSS vulnerabilities.

    <a href="javascript:alert('XSS')">Click me</a>
  • #8341 343dc4d Thanks @arendjr! - Added the nursery rule useAwaitThenable, which enforces that await is only used on Promise values.

    Invalid

    await "value";
    const createValue = () => "value";
    await createValue();

    Caution

    This is a first iteration of the rule, and does not yet detect generic “thenable” values.

  • #8034 e7e0f6c Thanks @Netail! - Added the nursery rule useRegexpExec. Enforce RegExp#exec over String#match if no global flag is provided.

  • #8137 d407efb Thanks @denbezrukov! - Reduced the internal memory used by the Biome formatter.

  • #8281 30b046f Thanks @tylersayshi! - Added the rule useRequiredScripts, which enforces presence of configurable entries in the scripts section of package.json files.

  • #8290 d74c8bd Thanks @dyc3! - The HTML formatter has been updated to match Prettier 3.7’s behavior for handling <iframe>’s allow attribute.

    <iframe allow="layout-animations 'none'; unoptimized-images 'none'; oversized-images 'none'; sync-script 'none'; sync-xhr 'none'; unsized-media 'none';"></iframe>
    <iframe
    allow="
    layout-animations 'none';
    unoptimized-images 'none';
    oversized-images 'none';
    sync-script 'none';
    sync-xhr 'none';
    unsized-media 'none';
    "
    ></iframe>
  • #8302 d1d5014 Thanks @mlafeldt! - Fixed #8109: return statements in Astro frontmatter no longer trigger “Illegal return statement” errors when using experimentalFullSupportEnabled.

  • #8346 f3aee1a Thanks @arendjr! - Fixed #8292: Implement tracking of types of TypeScript constructor parameter properties.

    This resolves certain false negatives in noFloatingPromises and other typed rules.

    Example

    class AsyncClass {
    async returnsPromise() {
    return "value";
    }
    }
    class ShouldBeReported {
    constructor(public field: AsyncClass) {}
    // ^^^^^^^^^^^^----------------- Parameter property declaration
    async shouldBeReported() {
    // `noFloatingPromises` will now report the following usage:
    this.field.returnsPromise();
    }
    }
  • #8326 153e3c6 Thanks @ematipico! - Improved the rule noBiomeFirstException. The rule can now inspect if extended configurations already contain the catch-all ** inside files.includes and, if so, the rule suggests removing ** from the user configuration.

  • #8433 397547a Thanks @dyc3! - Fixed #7920: The CSS parser, with Tailwind directives enabled, will no longer error when you use things like prefix(tw) in @import at rules.

  • #8378 cc2a62e Thanks @Bertie690! - Clarify diagnostic message for lint/style/useUnifiedTypeSignatures

    The rule’s diagnostic message now clearly states that multiple similar overload signatures are hard to read & maintain, as opposed to overload signatures in general.

  • #8296 9d3ef10 Thanks @dyc3! - biome rage now shows if you have experimental HTML full support enabled.

  • #8414 09acf2a Thanks @Bertie690! - Updated the documentation & diagnostic message for lint/nursery/noProto, mentioning the reasons for its longstanding deprecation and why more modern alternatives are preferred.

    Notably, the rule clearly states that using __proto__ inside object literal definitions is still allowed, being a standard way to set the prototype of a newly created object.

  • #8445 c3df0e0 Thanks @tt-a1i! - Fix --changed and --staged flags throwing “No such file or directory” error when a file has been deleted or renamed in the working directory. The CLI now filters out files that no longer exist before processing.

  • #8459 b17d12b Thanks @ruidosujeira! - Fix #8435: resolved false positive in noUnusedVariables for generic type parameters in construct signature type members (new <T>(): T).

  • #8439 a78774b Thanks @tt-a1i! - Fixed #8011: useConsistentCurlyBraces no longer suggests removing curly braces from JSX expression children containing characters that would cause parsing issues or semantic changes when converted to plain JSX text ({, }, <, >, &).

  • #8436 a392c06 Thanks @ruidosujeira! - Fixed #8429. Formatter, linter, and assist settings now correctly inherit from global configuration when not explicitly specified in overrides.

    Before this fix, when an override specified only one feature (e.g., only linter), other features would be incorrectly disabled instead of inheriting from global settings.

    Example configuration that now works correctly:

    {
    "formatter": { "enabled": true },
    "overrides": [
    {
    "includes": ["*.vue"],
    "linter": { "enabled": false }
    }
    ]
    }

    After this fix, .vue files will have the linter disabled (as specified in the override) but the formatter enabled (inherited from global settings).

  • #8411 9f1b3b0 Thanks @rriski! - Properly handle name, type_arguments, and attributes slots for JsxOpeningElement and JsxSelfClosingElement GritQL patterns.

    The following biome search commands no longer throw errors:

    Terminal window
    biome search 'JsxOpeningElement(name = $elem_name) where { $elem_name <: "div" }'
    biome search 'JsxSelfClosingElement(name = $elem_name) where { $elem_name <: "div" }'
  • #8441 cf37d0d Thanks @tt-a1i! - Fixed #6577: noUselessUndefined no longer reports () => undefined in arrow function expression bodies. Previously, the rule would flag this pattern and suggest replacing it with () => {}, which conflicts with the noEmptyBlockStatements rule.

  • #8444 8caa7a0 Thanks @tt-a1i! - Fix noUnknownMediaFeatureName false positive for prefers-reduced-transparency media feature. The feature name was misspelled as prefers-reduded-transparency in the keywords list.

  • #8443 c3fa5a1 Thanks @tt-a1i! - Fix useGenericFontNames false positive when a CSS variable is used as the last value in font-family or font. The rule now correctly ignores cases like font-family: "Noto Serif", var(--serif) and font: 1em Arial, var(--fallback).

  • #8281 30b046f Thanks @tylersayshi! - Fixed noDuplicateDependencies incorrectly triggering on files like _package.json.

  • #8315 c7915c4 Thanks @hirokiokada77! - Fixed #5213: The noDoneCallback rule no longer flags false positives when a method is called on a regular variable bound to identifiers such as before, after, beforeEach, and afterEach.

  • #8398 204844f Thanks @Bertie690! - The default value of the ignoreRestSiblings option for noUnusedVariables’ has been reverted to its prior value of true after an internal refactor accidentally changed it.

    The diagnostic message has also been tweaked for readability.

  • #8242 9694e37 Thanks @dyc3! - Fixed bugs in the HTML parser so that it will flag invalid shorthand syntaxes instead of silently accepting them. For example, <Foo : foo="5" /> is now invalid because there is a space after the :.

  • #8297 efa694c Thanks @Yonom! - Added support for negative value utilities in useSortedClasses. Negative value utilities such as -ml-2 or -top-4 are now recognized and sorted correctly alongside their positive counterparts.

    // Now detected as unsorted:
    <div class="-ml-2 p-4 -mt-1" />
    // Suggested fix:
    <div class="-mt-1 -ml-2 p-4" />
  • #8335 3710702 Thanks @dibashthapa! - Added the new nursery rule useDestructuring. This rule helps to encourage destructuring from arrays and objects.

    For example, the following code triggers because the variable name x matches the property foo.x, making it ideal for object destructuring syntax.

    var x = foo.x;
  • #8383 59b2f9a Thanks @ematipico! - Fixed #7927: noExtraNonNullAssertion incorrectly flagged separate non-null assertions on both sides of an assignment.

    The rule now correctly distinguishes between nested non-null assertions (still flagged) and separate non-null assertions on different sides of an assignment (allowed).

    Examples

    Valid (now allowed)
    arr[0]! ^= arr[1]!;
    Invalid (still flagged)
    arr[0]!! ^= arr[1];
    arr[0] ^= arr[1]!!;
  • #8401 382786b Thanks @Bertie690! - useExhaustiveDependencies now correctly validates custom hooks whose dependency arrays come before their callbacks.

    Previously, a logical error caused the rule to be unable to detect dependency arrays placed before hook callbacks, producing spurious errors and blocking further diagnostics.

    {
    "linter": {
    "rules": {
    "correctness": {
    "useExhaustiveDependencies": {
    "level": "error",
    "options": {
    "hooks": [
    {
    "name": "doSomething",
    "closureIndex": 2,
    "dependenciesIndex": 0
    }
    ]
    }
    }
    }
    }
    }
    }
    function component() {
    let thing = 5;
    // The rule will now correctly recognize `thing` as being specified
    // instead of erroring due to "missing" dependency arrays
    doSomething([thing], "blah", () => {
    console.log(thing);
    });
    }

    The rule documentation & diagnostic messages have also been reworked for improved clarity.

  • #8365 8f36051 Thanks @JacquesLeupin! - Fixed #8360: GritQL plugins defined in child configurations with extends: "//" now work correctly.

  • #8306 8de2774 Thanks @dibashthapa! - Fixed #8288: Fixed the issue with false positive errors

    This new change will ignore attribute and only show diagnostics for JSX Expressions

    For example

    Valid:

    <Something checked={isOpen && items.length} />

    Invalid:

    const Component = () => {
    return isOpen && items.length;
    };
  • #8356 f9673fc Thanks @ematipico! - Fixed #7917, where Biome removed the styles contained in a <style lang="scss">, when experimentalFullSupportEnabled is enabled.

  • #8371 d71924e Thanks @ematipico! - Fixed #7343, where Biome failed to resolve extended configurations from parent directories using relative paths.

  • #8404 6a221f9 Thanks @fireairforce! - Fixed #7826, where a class member named async will not cause the parse error.

  • #8249 893e36c Thanks @cormacrelf! - Addressed #7538. Reduced the volume of logging from the LSP server.

    Use biome clean to remove large logs.

  • #8303 db2c65b Thanks @hirokiokada77! - Fixed #8300: noUnusedImports now detects JSDoc tags on object properties.

    import type LinkOnObjectProperty from "mod";
    const testLinkOnObjectProperty = {
    /**
    * {@link LinkOnObjectProperty}
    */
    property: 0,
    };
  • #8328 9cf2332 Thanks @Netail! - Corrected rule source reference. biome migrate eslint should do a bit better detecting rules in your eslint configurations.

  • #8403 c96dcf2 Thanks @dyc3! - Fixed #8340: noUnknownProperty will no longer flag anything in @plugin when the parser option tailwindDirectives is enabled

  • #8284 4976d1b Thanks @denbezrukov! - Improved the performance of the Biome Formatter by enabling the internal source maps only when needed.

  • #8260 a226b28 Thanks @ho991217! - Fixed biome-vscode#817: Biome now updates documents when the textDocument/didSave notification is received.

  • #8183 b064786 Thanks @hornta! - Fixed #8179: The useConsistentArrowReturn rule now correctly handles multiline expressions in its autofix when the style option is set to "always".

    Previously, the autofix would incorrectly place a newline after the return keyword, causing unexpected behavior.

    Example:

    const foo = (l) => l.split("\n");

    Now correctly autofixes to:

    const foo = (l) => {
    return
    l.split('\n');
    return l.split('\n');
    }
  • #8382 7409cba Thanks @fireairforce! - Fixed #8338: Ignored the noUnknownTypeSelector check when the root selector is used under View Transition pseudo-elements.

    Example

    ::view-transition-old(root),
    ::view-transition-new(root) {
    z-index: 1;
    }
  • #7513 e039f3b Thanks @AsherDe! - Added the nursery rule noVueSetupPropsReactivityLoss.

    This new rule disallows usages that cause the reactivity of props passed to the setup function to be lost.

    Invalid code example:

    export default {
    setup({ count }) {
    // `count` is no longer reactive here.
    return () => h("div", count);
    },
    };

2.3.8

Patch Changes

  • #8188 4ca088c Thanks @ematipico! - Fixed #7390, where Biome couldn’t apply the correct configuration passed via --config-path.

    If you have multiple root configuration files, running any command with --config-path will now apply the chosen configuration file.

  • #8171 79adaea Thanks @dibashthapa! - Added the new rule noLeakedRender. This rule helps prevent potential leaks when rendering components that use binary expressions or ternaries.

    For example, the following code triggers the rule because the component would render 0:

    const Component = () => {
    const count = 0;
    return <div>{count && <span>Count: {count}</span>}</div>;
    };
  • #8116 b537918 Thanks @Netail! - Added the nursery rule noDuplicatedSpreadProps. Disallow JSX prop spreading the same identifier multiple times.

    Invalid:

    <div {...props} something="else" {...props} />
  • #8256 f1e4696 Thanks @cormacrelf! - Fixed a bug where logs were discarded (the kind from --log-level=info etc.). This is a regression introduced after an internal refactor that wasn’t adequately tested.

  • #8226 3f19b52 Thanks @dyc3! - Fixed #8222: The HTML parser, with Vue directives enabled, can now parse v-slot shorthand syntax, e.g. <template #foo>.

  • #8007 182ecdc Thanks @brandonmcconnell! - Added support for dollar-sign-prefixed filenames in the useFilenamingConvention rule.

    Biome now allows filenames starting with the dollar-sign (e.g. $postId.tsx) by default to support naming conventions used by frameworks such as TanStack Start for file-based-routing.

  • #8218 91484d1 Thanks @hirokiokada77! - Added the noMultiStr rule, which disallows creating multiline strings by escaping newlines.

    Invalid:

    const foo =
    "Line 1\n\
    Line 2";

    Valid:

    const foo = "Line 1\nLine 2";
    const bar = `Line 1
    Line 2`;
  • #8225 98ca2ae Thanks @ongyuxing! - Fixed #7806: Prefer breaking after the assignment operator for conditional types with generic parameters to match Prettier.

    type True = unknown extends Type<
    "many",
    "generic",
    "parameters",
    "one",
    "two",
    "three"
    >
    ? true
    : false;
    type True =
    unknown extends Type<"many", "generic", "parameters", "one", "two", "three">
    ? true
    : false;
  • #6765 23f7855 Thanks @emilyinure! - Fixed #6569: Allow files to export from themselves with noImportCycles.

    This means the following is now allowed:

    example.js
    export function example() {
    return 1;
    }
    // Re-exports all named exports from the current module under a single namespace
    // and then imports the namespace from the current module.
    // Allows for encapsulating functions/variables into a namespace instead
    // of using a static class.
    export * as Example from "./example.js";
    import { Example } from "./example.js";
  • #8214 68c052e Thanks @hirokiokada77! - Added the noEqualsToNull rule, which enforces the use of === and !== for comparison with null instead of == or !=.

    Invalid:

    foo == null;
    foo != null;

    Valid:

    foo === null;
    foo !== null;
  • #8219 793bb9a Thanks @dyc3! - Fixed #8190: The HTML parser will now parse Vue event handlers that contain : correctly, e.g. @update:modelValue="onUpdate".

  • #8259 4a9139b Thanks @hirokiokada77! - Fixed #8254: The noParameterAssign rule with propertyAssignment: "deny" was incorrectly reporting an error when a function parameter was used on the right-hand side of an assignment to a local variable’s property.

    The rule should only flag assignments that modify the parameter binding or its properties (L-value), not the use of its value.

    Valid:

    (input) => {
    const local = { property: 0 };
    local.property = input;
    };
  • #8201 cd2edd7 Thanks @Netail! - Added the nursery rule noTernary. Disallow ternary operators.

    Invalid:

    const foo = isBar ? baz : qux;
  • #8172 de98933 Thanks @JeremyMoeglich! - Fixed #8145: handling of large hex literals, which previously caused both false positives and false negatives.

    This affects noPrecisionLoss and noConstantMathMinMaxClamp.

  • #8210 7b44e9e Thanks @Netail! - Corrected rule source reference. biome migrate eslint should do a bit better detecting rules in your eslint configurations.

  • #8213 e430555 Thanks @ruidosujeira! - Fixed #8209: Recognized formatting capability when either range or on-type formatting is supported, not only full-file formatting. This ensures editors and the language server correctly detect formatting support in files like JSONC.

  • #8202 6f49d95 Thanks @hirokiokada77! - Fixed #8079: Properly handle name and value metavariables for JsxAttribute GritQL queries.

    The following biome search command no longer throws an error:

    biome search 'JsxAttribute($name, $value) as $attr where { $name <: "style" }'
  • #8276 f7e836f Thanks @hirokiokada77! - Added the noProto rule, which disallows the use of the __proto__ property for getting or setting the prototype of an object.

    Invalid:

    obj.__proto__ = a;
    const b = obj.__proto__;

    Valid:

    const a = Object.getPrototypeOf(obj);
    Object.setPrototypeOf(obj, b);

2.3.7

Patch Changes

  • #8169 7fdcec8 Thanks @arendjr! - Fixed #7999: Correctly place await after leading comment in auto-fix action from noFloatingPromises rule.

  • #8157 12d5b42 Thanks @Conaclos! - Fixed #8148. noInvalidUseBeforeDeclaration no longer reports some valid use before declarations.

    The following code is no longer reported as invalid:

    class classA {
    C = C;
    }
    const C = 0;
  • #8178 6ba4157 Thanks @dyc3! - Fixed #8174, where the HTML parser would parse 2 directives as a single directive because it would not reject whitespace in Vue directives. This would cause the formatter to erroneously merge the 2 directives into one, resulting in broken code.

    <Component v-else:property="123" />
    <Component v-else :property="123" />
  • #8088 0eb08e8 Thanks @db295! - Fixed #7876: The noUnusedImports rule now ignores imports that are used by @linkcode and @linkplain (previously supported @link and @see).

    The following code will no longer be a false positive:

    import type { a } from "a"
    /**
    * {@linkcode a}
    */
    function func() {}
  • #8119 8d64655 Thanks @ematipico! - Improved the detection of the rule noUnnecessaryConditions. Now the rule isn’t triggered for variables that are mutated inside a module.

    This logic deviates from the original rule, hence noUnnecessaryConditions is now marked as “inspired”.

    In the following example, hey starts as false, but then it’s assigned to a string. The rule isn’t triggered inside the if check.

    let hey = false;
    function test() {
    hey = "string";
    }
    if (hey) {
    }
  • #8149 e0a02bf Thanks @Netail! - Fixed #8144: Improve noSyncScripts, ignore script tags with type="module" as these are always non-blocking.

  • #8182 e9f068e Thanks @hirokiokada77! - Fixed #7877: Range suppressions now handle suppressed categories properly.

    Valid:

    // biome-ignore-start lint: explanation
    const foo = 1;
    // biome-ignore-end lint: explanation
  • #8111 bf1a836 Thanks @ryan-m-walker! - Added support for parsing and formatting the CSS if function.

    Example

    .basic-style {
    color: if(style(--scheme: dark): #eeeeee; else: #000000;);
    }
  • #8173 7fc07c1 Thanks @ematipico! - Fixed #8138 by reverting an internal refactor that caused a regression to the rule noUnusedPrivateClassMembers.

  • #8119 8d64655 Thanks @ematipico! - Improved the type inference engine, by resolving types for variables that are assigned to multiple values.

  • #8158 fb1458b Thanks @dyc3! - Added the useVueValidVText lint rule to enforce valid v-text directives. The rule reports when v-text has an argument, has modifiers, or is missing a value.

    Invalid:

    <div v-text />
    <!-- missing value -->
    <div v-text:aaa="foo" />
    <!-- has argument -->
    <div v-text.bbb="foo" />
    <!-- has modifier -->
  • #8158 fb1458b Thanks @dyc3! - Fixed useVueValidVHtml so that it will now flag empty strings, e.g. v-html=""

  • #7078 bb7a15c Thanks @emilyinure! - Fixed #6675: Now only flags noAccumulatingSpread on Object.assign when a new object is being allocated on each iteration. Before, all cases using Object.assign with reduce parameters were warned despite not making new allocations.

    The following code will no longer be a false positive:

    foo.reduce((acc, bar) => Object.assign(acc, bar), {});

    The following cases which do make new allocations will continue to warn:

    foo.reduce((acc, bar) => Object.assign({}, acc, bar), {});
  • #8175 0c8349e Thanks @ryan-m-walker! - Fixed CSS formatting of dimension units to use correct casing for Q, Hz and kHz.

    Before:

    .cssUnits {
    a: 1Q;
    b: 1Hz;
    c: 1kHz;
    }

    After:

    .cssUnits {
    a: 1Q;
    b: 1Hz;
    c: 1kHz;
    }