github biomejs/biome @biomejs/biome@2.4.11
Biome CLI v2.4.11

7 hours ago

2.4.11

Patch Changes

  • #9350 4af4a3a Thanks @dyc3! - Added the new nursery rule useConsistentTestIt in the test domain. The rule enforces consistent use of either it or test for test functions in Jest/Vitest suites, with separate control for top-level tests and tests inside describe blocks.

    Invalid:

    test("should fly", () => {}); // Top-level test using 'test' flagged, convert to 'it'
    
    describe("pig", () => {
      test("should fly", () => {}); // Test inside 'describe' using 'test' flagged, convert to 'it'
    });
  • #9429 a2f3f7e Thanks @ematipico! - Added the new nursery lint rule useExplicitReturnType. It reports TypeScript functions and methods that omit an explicit return type.

    function toString(x: any) {
      // rule triggered, it doesn't declare a return type
      return x.toString();
    }
  • #9828 9e40844 Thanks @ematipico! - Fixed #9484: the formatter no longer panics when formatting files that contain graphql tagged template literals combined with parenthesized expressions.

  • #9886 e7c681e Thanks @ematipico! - Fixed an issue where, occasionally, some bindings and references were not properly tracked, causing false positives from noUnusedVariables and noUndeclaredVariables in Svelte, Vue, and Astro files.

  • #9760 5b16d18 Thanks @myx0m0p! - Fixed #4093: the noDelete rule no longer triggers for delete process.env.FOO, since delete is the documented way to remove environment variables in Node.js.

  • #9799 2af8efd Thanks @minseong0324! - Added the rule noMisleadingReturnType. The rule detects when a function's return type annotation is wider than what the implementation actually returns.

    // Flagged: `: string` is wider than `"loading" | "idle"`
    function getStatus(b: boolean): string {
      if (b) return "loading";
      return "idle";
    }
  • #9880 7f67749 Thanks @dyc3! - Improved the diagnostics for useFind to better explain the problem, why it matters, and how to fix it.

  • #9755 bff7bdb Thanks @ematipico! - Improved performance of fix-all operations (--write). Biome is now smarter when it runs lint rules and assist actions. First, it runs only rules that have code fixes, and then runs the rest of the rules.

  • #8651 aafca2d Thanks @siketyan! - Add a new lint rule useDisposables for JavaScript, which detects disposable objects assigned to variables without using or await using syntax. Disposable objects that implement the Disposable or AsyncDisposable interface are intended to be disposed of after use. Not disposing them can lead to resource or memory leaks, depending on the implementation.

    Invalid:

    function createDisposable(): Disposable {
      return {
        [Symbol.dispose]() {
          // do something
        },
      };
    }
    
    const disposable = createDisposable();

    Valid:

    function createDisposable(): Disposable {
      return {
        [Symbol.dispose]() {
          // do something
        },
      };
    }
    
    using disposable = createDisposable();
  • #9788 53b8e57 Thanks @MeGaNeKoS! - Fixed #7760: Added support for CSS scroll-driven animation timeline-range-name keyframe selectors (cover, contain, entry, exit, entry-crossing, exit-crossing). Biome no longer reports parse errors on keyframes like entry 0% { ... } or exit 100% { ... }.

  • #9728 5085424 Thanks @mkosei! - Fixed #9696: Astro frontmatter now correctly parses regular expression literals like /\d{4}/.

  • #9261 16b6c49 Thanks @ematipico! - Fixed #8409: CSS formatter now correctly places comments after the colon in property declarations.

    Previously, comments that appeared after the colon in CSS property values were incorrectly moved before the property name:

    [lang]:lang(ja) {
    -  /* system-ui,*/ font-family:
    +  font-family: /* system-ui,*/
        Hiragino Sans,
        sans-serif;
    }
  • #9441 957ea4c Thanks @soconnor-seeq! - Fixed #1630: LSP project selection now prefers the most specific project root in nested workspaces.

  • #9878 de6210f Thanks @ematipico! - Fixed #9118: noUnusedImports no longer reports false positives for default imports used inside Svelte, Vue and Astro components.

  • #9879 ce7e2b7 Thanks @dyc3! - Fixed a parser diagnostic's message when vue syntax is disabled so that it no longer references the non-existant html.parser.vue option. This option will become available in 2.5.

  • #9880 7f67749 Thanks @dyc3! - Improved the diagnostics for useRegexpExec to better explain the problem, why it matters, and how to fix it.

  • #9846 b7134d9 Thanks @ematipico! - Fixed #9140: Biome now parses Astro's attribute shorthand inside .astro files. The following snippet no longer reports a parse error:

    ---
    const items = ['a', 'b'];
    ---
    <ul>
      {items.map((item) => <li {item}>row</li>)}
    </ul>
  • #9790 67df09d Thanks @dyc3! - Fixed #9781: Trailing comments after a top-level biome-ignore-all format suppression are now preserved instead of being dropped. This applies to JavaScript, CSS, HTML, JSONC, GraphQL, and Grit files.

  • #9745 d87073e Thanks @ematipico! - Fixed #9741: the LSP server now correctly returns the organizeImports code action when the client requests it via source.organizeImports.biome in the only filter. Previously, editors with codeAction/resolve support (e.g. Zed) received an empty response because the action was serialized with the wrong kind (source.biome.organizeImports instead of source.organizeImports.biome).

  • #9880 7f67749 Thanks @dyc3! - Improved the diagnostics for useArraySome to better explain the problem, why it matters, and how to fix it.

  • #9795 1d09f0f Thanks @dyc3! - Relaxed useExplicitType for trivially inferrable types.

    Type annotations can now be omitted when types are trivially inferrable from:

    • Binary expressions (const sum = 1 + 1)
    • Comparison expressions (const isEqual = 'a' === 'b', const isTest = process.env.NODE_ENV === 'test')
    • Logical expressions (const and = true && false)
    • Class instantiation (const date = new Date())
    • Array literals (const arr = [1, 2, 3])
    • Conditional expressions (const val = true ? 'yes' : 'no')
    • Function calls (const num = Math.random())
    • Parameter defaults - any expression is now allowed (const fn = (max = MAX_ATTEMPTS) => ...)

    Comparison expressions always return boolean, so any operands are now allowed
    (including property access like process.env.NODE_ENV).

    Parameters with default values no longer require type annotations, as TypeScript
    can infer the type from the default value (even when referencing variables).

    Also removed the redundant any type validation from this rule. The any type
    is now only validated by the dedicated noExplicitAny rule, following the
    Single Responsibility Principle.

  • #9809 e8cad58 Thanks @Netail! - Added the new nursery rule useQwikLoaderLocation, which enforces that Qwik loader functions are declared in the correct location.

  • #9877 fc9d715 Thanks @ematipico! - Fixed #9136 and #9653: noUndeclaredVariables and noUnusedVariables no longer report false positives on several Svelte template constructs that declare or reference bindings in the host grammar:

    • {#snippet name(params)} — the snippet name and its parameters (including object, array, rest, and nested destructuring) are now tracked.
    • {@render name(args)} — the snippet name used at the render site is now resolved against the snippet declaration.
    • {#each items as item, index (key)} — the item binding (plain identifier or destructured), the optional index, and the optional key expression are now tracked.
    • {@const name = value} — the declared name is now tracked as a binding and the initializer is analyzed for undeclared references.
    • {@debug a, b, c} — each debugged identifier is now analyzed and reported if undeclared.
    • Shorthand attributes <img {src} /> — the curly-shorthand attribute is now analyzed as an expression, so undeclared references inside it are reported.

    For example, the following template no longer triggers either rule:

    <script>
    let items = [];
    let total = 0;
    </script>
    
    {#snippet figure(image)}
        <figure>
            <img src={image.src} alt={image.caption} />
            <figcaption>{image.caption}</figcaption>
        </figure>
    {/snippet}
    
    {#each items as item}
        {@const price = item.price}
        {@render figure(item)}
        <span>{price}</span>
    {/each}
    
    {@debug items, total}
  • #9869 78bce77 Thanks @Netail! - Updated noDuplicateFieldDefinitionNames to also flag duplicate fields within type extensions, interface extensions & input extensions.

  • #9739 0bc2198 Thanks @dyc3! - Fixed Grit queries that use native Biome AST node names with the native field names that are in our .ungram grammar files. Queries such as JsConditionalExpression(consequent = $cons, alternate = $alt) now compile successfully in biome search and grit plugins.

  • #9811 2dddca3 Thanks @dyc3! - Updated noImpliedEval to flag new Function() usages, as its a form of indirect eval, and to include no-new-func as a rule source.

  • #9870 ccf9770 Thanks @Netail! - Marked eslint-qwik-plugin's unused-server as redundant since it was covered by noUnusedVariables.

  • #9701 1417c3b Thanks @dyc3! - Added the new nursery rule noUselessTypeConversion, which reports redundant primitive conversion patterns such as String(value) when value is already a string.

  • #9248 49f00a3 Thanks @pkallos! - useNullishCoalescing now also detects ternary expressions that check for null or undefined and suggests rewriting them with ??. A new ignoreTernaryTests option allows disabling this behavior.

  • #9863 6a44619 Thanks @ematipico! - Fixed #9690: biome check --write is now idempotent on HTML files that contain embedded <style> or <script> blocks. Previously, each run reported "Fixed 1 file" even when the file content did not actually change, because the embedded language formatter's output was not re-indented to match the surrounding HTML block.

What's Changed

  • feat(md/fmt): format more nodes by @ematipico in #9713
  • fix(markdown): preserve nested list indent tokens by @jfmcdowell in #9717
  • fix(html): handle escaped regex literals in astro frontmatter by @mkosei in #9728
  • test(markdown): add regression tests for mixed list markers across blank lines by @jfmcdowell in #9732
  • fix(lsp): prefer most specific project root by @soconnor-seeq in #9441
  • fix(markdown): fix fenced code block closing inside list items by @jfmcdowell in #9730
  • fix(markdown): fix HTML block parsing inside list item continuations by @jfmcdowell in #9740
  • fix(markdown): fix panic on multi-byte characters in emphasis context by @jfmcdowell in #9735
  • refactor(markdown): replace skipped trivia with formatter-safe recovery by @jfmcdowell in #9746
  • refactor(markdown): cleanup nits from #9746 by @jfmcdowell in #9751
  • fix(lsp): regression codeAction/resolve by @ematipico in #9745
  • feat(lint/js): add noUselessTypeConversion by @dyc3 in #9701
  • fix(markdown): replace panicking code with safe fallbacks in lexer by @jfmcdowell in #9753
  • refactor(markdown): emit continuation indent as structural CST node by @jfmcdowell in #9737
  • fix(markdown): fix false diagnostic on nested lists with double blank lines by @jfmcdowell in #9764
  • feat(css): add support for SCSS string interpolation by @denbezrukov in #9756
  • refactor(markdown): deduplicate shared helper functions by @jfmcdowell in #9766
  • fix(markdown): remove debug scaffolding and parser cleanup by @jfmcdowell in #9765
  • refactor(flags): make variables predictable by @ematipico in #9769
  • fix(markdown_parser): emit MdIndentTokenList for headers inside list items by @jfmcdowell in #9774
  • fix(markdown_parser): fix lazy continuation at nested list marker indent by @jfmcdowell in #9776
  • docs: clarify that elements in scope for useAltText is not configurable by @yogaraptor in #9773
  • fix(markdown_parser): fix multi-byte character panic in emphasis context by @jfmcdowell in #9775
  • perf(core): refactor fix-all logic by @ematipico in #9755
  • feat(css): add support for scroll-driven animation keyframe selectors by @MeGaNeKoS in #9788
  • fix(format): don't remove trailing comments when formatting is suppressed by @dyc3 in #9790
  • test(markdown_parser): add reference HTML validation and structural invariants by @jfmcdowell in #9779
  • fix(markdown_parser): reject multiline inline HTML open tag when > at line start is blockquote marker by @jfmcdowell in #9783
  • fix: noDelete should not suggest undefined assignment for process.env by @myx0m0p in #9760
  • feat(lint/js): add useConsistentTestIt by @dyc3 in #9350
  • feat(useExplicitType): relax rule for trivially inferrable types by @dyc3 in #9795
  • chore(deps): update dependency tombi to v0.9.13 by @renovate[bot] in #9819
  • fix(markdown_parser): split bullet lists when marker type changes across blank lines by @jfmcdowell in #9785
  • fix(markdown_parser): recognize setext heading inside blockquote by @jfmcdowell in #9782
  • chore(deps): update github-actions by @renovate[bot] in #9823
  • fix(deps): update @biomejs packages by @renovate[bot] in #9822
  • chore(deps): update rust crate libc to 0.2.184 by @renovate[bot] in #9821
  • chore(deps): update dependency dprint to v0.53.2 by @renovate[bot] in #9818
  • refactor(useConsistentTestIt): review feedback by @dyc3 in #9827
  • fix(cli): fix codeAction/resolve not considering assist actions by @elliotcourant in #9812
  • test(markdown_parser): add differential fuzzer against commonmark.js by @jfmcdowell in #9784
  • feat(markdown): implement basic formatter features by @tidefield in #9693
  • feat(lint): add ternary expression detection to useNullishCoalescing by @pkallos in #9248
  • chore(deps): update rust crate indexmap to 2.13.1 by @renovate[bot] in #9820
  • fix: embedded snippets with parenthesis by @ematipico in #9828
  • feat(js/lint): implement rule useDisposables by @siketyan in #8651
  • fix(markdown_parser): reject link reference definition with trailing text after destination by @jfmcdowell in #9780
  • feat(lint): rule useExplicitReturnType by @ematipico in #9429
  • fix(markdown_parser): incorrect tight/loose list classification at marker boundaries by @jfmcdowell in #9787
  • ci: add cargo-deny for paste crate by @dyc3 in #9579
  • chore: format by @dyc3 in #9834
  • chore(skills): better diagnostic advice by @dyc3 in #9830
  • feat(lint): add nursery rule noMisleadingReturnType by @minseong0324 in #9799
  • chore: update guidelines to protect maintainers by @ematipico in #9825
  • chore(deps): update dependency vite to v7.3.2 [security] by @renovate[bot] in #9844
  • refactor(markdown_parser): deduplicate normalize_html test helper by @jfmcdowell in #9833
  • chore(deps): update rust crate tokio to 1.51.0 by @renovate[bot] in #9602
  • fix(deps): update rust crates by @renovate[bot] in #9708
  • refactor(migrate): auto derive variant_index() function by @dyc3 in #9803
  • feat(noImpliedEval): flag new Function(...) by @dyc3 in #9811
  • test: infra for custom rule migrators by @dyc3 in #9836
  • refactor(markdown_parser): deduplicate link helper functions by @jfmcdowell in #9840
  • fix(js): parse short hand identifier in Astro JSX files by @ematipico in #9846
  • fix(ci): remove unused import: JsFileSource by @tidefield in #9858
  • fix(grit): biome native node field names now work by @dyc3 in #9739
  • fix(md-formatter): remove last hard line break by @tidefield in #9856
  • feat(lint): detect tuple widening and inferred unions in noMisleadingReturnType by @minseong0324 in #9843
  • docs: improve useSimplifiedLogicExpression docs by @ematipico in #9864
  • fix(core): update snippet via fix all by @ematipico in #9863
  • feat(js_analyze): implement useQwikLoaderLocation by @Netail in #9809
  • chore: missing rule source by @Netail in #9871
  • chore: unsupported covered by by @Netail in #9870
  • fix(graphql_analyze): also flag duplicate fields within extensions by @Netail in #9869
  • fix(css/formatter): comment placement in lists by @ematipico in #9261
  • fix(core): track of default specifiers by @ematipico in #9878
  • fix(parse/html): fix disabled vue error message by @dyc3 in #9879
  • fix(core): tracking of snippet and render function calls by @ematipico in #9877
  • fix(lint/js): improve diagnostics to better follow rule pillars by @dyc3 in #9880
  • fix(core): tracking of bindings and value references by @ematipico in #9886
  • ci: release by @github-actions[bot] in #9733

New Contributors

Full Changelog: https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.10...@biomejs/biome@2.4.11

Don't miss a new biome release

NewReleases is sending notifications on new releases.